use Alpha channel and selection channel info when available to build the

2003-09-03  Pedro Gimeno  <pggimeno@wanadoo.es>

	* ccanalyze.c (analyze): use Alpha channel and selection
	channel info when available to build the histogram and to
	include/exclude colors in the color count. Fixes bug #121097
	and handling of INDEXEDA images which was broken.
	(histogram, insertcolor, fillPreview): updated to use
	gdoubles where appropriate.
This commit is contained in:
Pedro Gimeno
2003-09-03 19:22:49 +00:00
committed by Pedro Gimeno Fortea
parent 41edbeb907
commit 48b06a23ee
2 changed files with 99 additions and 45 deletions

View File

@ -1,3 +1,12 @@
2003-09-03 Pedro Gimeno <pggimeno@wanadoo.es>
* ccanalyze.c (analyze): use Alpha channel and selection
channel info when available to build the histogram and to
include/exclude colors in the color count. Fixes bug #121097
and handling of INDEXEDA images which was broken.
(histogram, insertcolor, fillPreview): updated to use
gdoubles where appropriate.
2003-09-03 Pedro Gimeno <pggimeno@wanadoo.es> 2003-09-03 Pedro Gimeno <pggimeno@wanadoo.es>
* ccanalyze.c: Changed from CR/LF style to LF style in preparation * ccanalyze.c: Changed from CR/LF style to LF style in preparation

View File

@ -111,7 +111,7 @@ struct _ColorNode
guchar g; guchar g;
guchar b; guchar b;
gint count; gdouble count;
}; };
@ -128,11 +128,13 @@ static void analyze (GimpDrawable *drawable);
static void histogram (guchar r, static void histogram (guchar r,
guchar g, guchar g,
guchar b); guchar b,
gdouble a);
static void fillPreview (GtkWidget *preview); static void fillPreview (GtkWidget *preview);
static void insertcolor (guchar r, static void insertcolor (guchar r,
guchar g, guchar g,
guchar b); guchar b,
gdouble a);
static void doLabel (GtkWidget *table, static void doLabel (GtkWidget *table,
const char *format, const char *format,
@ -142,8 +144,8 @@ static void doLabel (GtkWidget *table,
static gchar *filename = NULL; static gchar *filename = NULL;
static gint width, height, bpp; static gint width, height, bpp;
static ColorNode *color_table = NULL; static ColorNode *color_table = NULL;
static gint32 hist_red[256], hist_green[256], hist_blue[256]; static gdouble hist_red[256], hist_green[256], hist_blue[256];
static gint maxred = 0, maxgreen = 0, maxblue = 0; static gdouble maxred = 0.0, maxgreen = 0.0, maxblue = 0.0;
static gint uniques = 0; static gint uniques = 0;
static gint32 imageID; static gint32 imageID;
@ -263,8 +265,14 @@ analyze (GimpDrawable *drawable)
gint x, y, numcol; gint x, y, numcol;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
guchar r, g, b; guchar r, g, b;
gint a;
guchar idx; guchar idx;
gboolean gray; gboolean gray;
gboolean has_alpha;
gboolean has_sel;
guchar *sel;
GimpPixelRgn selPR;
gint ofsx, ofsy;
gimp_progress_init (_("Colorcube Analysis...")); gimp_progress_init (_("Colorcube Analysis..."));
@ -285,69 +293,101 @@ analyze (GimpDrawable *drawable)
height = drawable->height; height = drawable->height;
bpp = drawable->bpp; bpp = drawable->bpp;
/* allocate row buffer */ if (x2 <= x1 || y2 <= y1)
src_row = g_malloc ((x2 - x1) * bpp); return;
has_sel = !gimp_selection_is_empty (imageID);
gimp_drawable_offsets (drawable->drawable_id, &ofsx, &ofsy);
/* initialize the pixel region */ /* initialize the pixel region */
gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
cmap = gimp_image_get_cmap (imageID, &numcol); cmap = gimp_image_get_cmap (imageID, &numcol);
gray = gimp_drawable_is_gray (drawable->drawable_id); gray = (gimp_drawable_is_gray (drawable->drawable_id)
|| gimp_drawable_is_channel (drawable->drawable_id));
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
gimp_pixel_rgn_init (&selPR,
gimp_drawable_get (gimp_image_get_selection (imageID)),
0, 0, width, height, FALSE, FALSE);
/* allocate row buffer */
src_row = g_malloc ((x2 - x1) * bpp);
sel = g_malloc (x2 - x1);
for (y = y1; y < y2; y++) for (y = y1; y < y2; y++)
{ {
gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y, (x2 - x1)); gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y, (x2 - x1));
if (has_sel)
gimp_pixel_rgn_get_row (&selPR, sel, x1 + ofsx, y + ofsy, (x2 - x1));
for (x = 0; x < x2 - x1; x++) for (x = 0; x < x2 - x1; x++)
{ {
/* Start with full opacity. */
a = 255;
/* /*
* If the image is indexed, fetch RGB values * If the image is indexed, fetch RGB values
* from colormap. * from colormap.
*/ */
if (cmap) if (cmap)
{ {
idx = src_row[x]; idx = src_row[x * bpp];
r = cmap[idx * 3]; r = cmap[idx * 3];
g = cmap[idx * 3 + 1]; g = cmap[idx * 3 + 1];
b = cmap[idx * 3 + 2]; b = cmap[idx * 3 + 2];
if (has_alpha)
a = src_row[x * bpp + 1];
} }
else if (gray) else if (gray)
{ {
r = g = b = src_row[x * bpp]; r = g = b = src_row[x * bpp];
if (has_alpha)
a = src_row[x * bpp + 1];
} }
else else
{ {
r = src_row[x * bpp]; r = src_row[x * bpp];
g = src_row[x * bpp + 1]; g = src_row[x * bpp + 1];
b = src_row[x * bpp + 2]; b = src_row[x * bpp + 2];
if (has_alpha)
a = src_row[x * bpp + 3];
} }
insertcolor (r, g, b); if (has_sel)
a *= sel[x];
else
a *= 255;
if (a != 0)
insertcolor (r, g, b, (gdouble) a * (1.0 / (255.0 * 255.0)));
} }
/* tell the user what we're doing */ /* tell the user what we're doing */
if ((y % 10) == 0) if ((y % 10) == 0)
gimp_progress_update ((double) y / (double) (y2 - y1)); gimp_progress_update ((gdouble) y / (gdouble) (y2 - y1));
} }
/* clean up */ /* clean up */
g_free (src_row); g_free (src_row);
g_free (sel);
} }
/* here's were we actually store our color-table */ /* here's where we actually store our color-table */
static void static void
insertcolor (guchar r, insertcolor (guchar r,
guchar g, guchar g,
guchar b) guchar b,
gdouble a)
{ {
ColorNode *node, *next = NULL, *prev = NULL, ColorNode *node, *next = NULL, *prev = NULL,
*newred, *newgreen = NULL, *newblue; *newred, *newgreen = NULL, *newblue;
ColorType type = RED; ColorType type = RED;
histogram (r, g, b); histogram (r, g, b, a);
/* lets walk the tree, and see if it already contains this color */ /* let's walk the tree, and see if it already contains this color */
for (node = color_table; node != NULL; prev = node, node = next) for (node = color_table; node != NULL; prev = node, node = next)
{ {
if (node->color == RED) if (node->color == RED)
@ -389,10 +429,10 @@ insertcolor (guchar r,
} }
} }
/* this color was already stored -> update it's count */ /* this color was already stored -> update its count */
if (node) if (node)
{ {
node->count++; node->count += a;
return; return;
} }
@ -414,7 +454,7 @@ insertcolor (guchar r,
newblue->r = r; newblue->r = r;
newblue->g = g; newblue->g = g;
newblue->b = b; newblue->b = b;
newblue->count = 1; newblue->count = a;
/* previous was green: create link to axis */ /* previous was green: create link to axis */
if (prev && prev->color == GREEN && type == BLUE) if (prev && prev->color == GREEN && type == BLUE)
@ -436,7 +476,7 @@ insertcolor (guchar r,
newgreen->g = g; newgreen->g = g;
/* count doesn't matter here */ /* count doesn't matter here */
newgreen->count = -1; /*newgreen->count = -1;*/
/* previous was red: create link to axis */ /* previous was red: create link to axis */
if (prev && prev->color == RED && type == GREEN) if (prev && prev->color == RED && type == GREEN)
@ -459,7 +499,7 @@ insertcolor (guchar r,
newred->r = r; newred->r = r;
/* count doesn't matter here */ /* count doesn't matter here */
newred->count = -1; /*newred->count = -1;*/
/* previous was red, update its neighbour link */ /* previous was red, update its neighbour link */
if (prev) if (prev)
@ -479,15 +519,20 @@ insertcolor (guchar r,
static void static void
histogram (guchar r, histogram (guchar r,
guchar g, guchar g,
guchar b) guchar b,
gdouble a)
{ {
if (++hist_red[r] > maxred) hist_red[r] += a;
hist_green[g] += a;
hist_blue[b] += a;
if (hist_red[r] > maxred)
maxred = hist_red[r]; maxred = hist_red[r];
if (++hist_green[g] > maxgreen) if (hist_green[g] > maxgreen)
maxgreen = hist_green[g]; maxgreen = hist_green[g];
if (++hist_blue[b] > maxblue) if (hist_blue[b] > maxblue)
maxblue = hist_blue[b]; maxblue = hist_blue[b];
} }
@ -563,7 +608,7 @@ doDialog (void)
doLabel (table, _("Compressed size in bytes: %u"), filesize); doLabel (table, _("Compressed size in bytes: %u"), filesize);
doLabel (table, _("Compression ratio (approx.): %d to 1"), doLabel (table, _("Compression ratio (approx.): %d to 1"),
(gint) RINT ((double) (width * height * bpp) / filesize)); (gint) RINT ((gdouble) (width * height * bpp) / filesize));
} }
/* show stuff */ /* show stuff */
@ -607,7 +652,7 @@ fillPreview (GtkWidget *preview)
{ {
guchar *image, *pimage, *pixel; guchar *image, *pimage, *pixel;
gint x, y, rowstride; gint x, y, rowstride;
gint histcount, val; gdouble histcount, val;
image = g_malloc0 (PREWIDTH * PREHEIGHT * 3); image = g_malloc0 (PREWIDTH * PREHEIGHT * 3);
@ -620,9 +665,9 @@ fillPreview (GtkWidget *preview)
* and build a one-pixel bar. * and build a one-pixel bar.
* ... in the respective channel, preserving the other ones. --hb * ... in the respective channel, preserving the other ones. --hb
*/ */
histcount = hist_red[x] ? hist_red[x] : 1; histcount = hist_red[x] > 1.0 ? hist_red[x] : 1.0;
val = (gint) (log ((gdouble) histcount) * (PREHEIGHT / 12)); val = log (histcount) * (PREHEIGHT / 12);
if (val > PREHEIGHT) if (val > PREHEIGHT)
val = PREHEIGHT; val = PREHEIGHT;
@ -633,9 +678,9 @@ fillPreview (GtkWidget *preview)
*pixel = 255; *pixel = 255;
} }
histcount = hist_green[x] ? hist_green[x] : 1; histcount = hist_green[x] > 1.0 ? hist_green[x] : 1.0;
val = (gint) (log ((gdouble) histcount) * (PREHEIGHT / 12)); val = log (histcount) * (PREHEIGHT / 12);
if (val > PREHEIGHT) if (val > PREHEIGHT)
val = PREHEIGHT; val = PREHEIGHT;
@ -646,9 +691,9 @@ fillPreview (GtkWidget *preview)
*(pixel + 1) = 255; *(pixel + 1) = 255;
} }
histcount = hist_blue[x] ? hist_blue[x] : 1; histcount = hist_blue[x] > 1.0 ? hist_blue[x] : 1.0;
val = (gint) (log ((gdouble) histcount) * (PREHEIGHT / 12)); val = log (histcount) * (PREHEIGHT / 12);
if (val > PREHEIGHT) if (val > PREHEIGHT)
val = PREHEIGHT; val = PREHEIGHT;