1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpimage-convert-indexed.c
5 * Copyright (C) 1997-2004 Adam D. Moss <adam@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 /*
22 * 2005-09-04 - Switch 'positional' dither matrix to a 32x32 Bayer,
23 * which generates results that compress somewhat better (and may look
24 * worse or better depending on what you enjoy...). [adam@gimp.org]
25 *
26 * 2004-12-12 - Use a slower but much nicer technique for finding the
27 * two best colors to dither between when using fixed/positional
28 * dither methods. Makes positional dither much less lame. [adam@gimp.org]
29 *
30 * 2002-02-10 - Quantizer version 3.0 (the rest of the commit started
31 * a year ago -- whoops). Divide colors within CIE L*a*b* space using
32 * CPercep module (cpercep.[ch]), color-match and dither likewise,
33 * change the underlying box selection criteria and division point
34 * logic, bump luminance precision upwards, etc.etc. Generally
35 * chooses a much richer color set, especially for low numbers of
36 * colors. n.b.: Less luminance-sloppy in straight remapping which is
37 * good for color but a bit worse for high-frequency detail (that's
38 * partly what fs-dithering is for -- use it). [adam@gimp.org]
39 *
40 * 2001-03-25 - Define accessor function/macro for histogram reads and
41 * writes. This slows us down a little because we avoid some of the
42 * dirty tricks we used when we knew that the histogram was a straight
43 * 3d array, so I've recovered some of the speed loss by implementing
44 * a 5d accessor function with good locality of reference. This change
45 * is the first step towards quantizing in a more interesting colorspace
46 * than frumpy old RGB. [Adam]
47 *
48 * 2000/01/30 - Use palette_selector instead of option_menu for custom
49 * palette. Use libgimp callback functions. [Sven]
50 *
51 * 99/09/01 - Created a low-bleed FS-dither option. [Adam]
52 *
53 * 99/08/29 - Deterministic color dithering to arbitrary palettes.
54 * Ideal for animations that are going to be delta-optimized or simply
55 * don't want to look 'busy' in static areas. Also a bunch of bugfixes
56 * and tweaks. [Adam]
57 *
58 * 99/08/28 - Deterministic alpha dithering over layers, reduced bleeding
59 * of transparent values into opaque values, added optional stage to
60 * remove duplicate or unused color entries from final colormap. [Adam]
61 *
62 * 99/02/24 - Many revisions to the box-cut quantizer used in RGB->INDEXED
63 * conversion. Box to be cut is chosen on the basis of possessing an axis
64 * with the largest sum of weighted perceptible error, rather than based on
65 * volume or population. The box is split along this axis rather than its
66 * longest axis, at the point of error mean rather than simply at its centre.
67 * Error-limiting in the F-S dither has been disabled - it may become optional
68 * again later. If you're convinced that you have an image where the old
69 * dither looks better, let me know. [Adam]
70 *
71 * 99/01/10 - Hourglass... [Adam]
72 *
73 * 98/07/25 - Convert-to-indexed now remembers the last invocation's
74 * settings. Also, GRAY->INDEXED is more flexible. [Adam]
75 *
76 * 98/07/05 - Sucked the warning about quantizing to too many colors into
77 * a text widget embedded in the dialog, improved intelligence of dialog
78 * to default 'custom palette' selection to 'Web' if available, and
79 * in this case not bother to present the native WWW-palette radio
80 * button. [Adam]
81 *
82 * 98/04/13 - avoid a division by zero when converting an empty gray-scale
83 * image (who would like to do such a thing anyway??) [Sven ]
84 *
85 * 98/03/23 - fixed a longstanding fencepost - hopefully the *right*
86 * way, *again*. [Adam]
87 *
88 * 97/11/14 - added a proper pdb interface and support for dithering
89 * to custom palettes (based on a patch by Eric Hernes) [Yosh]
90 *
91 * 97/11/04 - fixed the accidental use of the color-counting case
92 * when palette_type is WEB or MONO. [Adam]
93 *
94 * 97/10/25 - color-counting implemented (could use some hashing, but
95 * performance actually seems okay) - now RGB->INDEXED conversion isn't
96 * destructive if it doesn't have to be. [Adam]
97 *
98 * 97/10/14 - fixed divide-by-zero when converting a completely transparent
99 * RGB image to indexed. [Adam]
100 *
101 * 97/07/01 - started todo/revision log. Put code back in to
102 * eliminate full-alpha pixels from RGB histogram.
103 * [Adam D. Moss - adam@gimp.org]
104 */
105
106 /* TODO for Convert:
107 *
108 * . Tweak, tweak, tweak. Old RGB code was tuned muchly.
109 *
110 * . Re-enable Heckbert locality for matching, benchmark it
111 *
112 * . Try faster fixed-point sRGB<->L*a*b* pixel conversion (see cpercep.c)
113 *
114 * . Use palette of another open INDEXED image?
115 *
116 * . Do error-splitting trick for GREY->INDEXED (hardly worth it)
117 */
118
119 /* CODE READABILITY BUGS:
120 *
121 * . Most uses of variants of the R,G,B variable naming convention
122 * are referring to L*a*b* co-ordinates, not RGB co-ordinates!
123 *
124 * . Each said variable is usually one of the following, but it is
125 * rarely clear which one:
126 * - (assumed sRGB) raw non-linear 8-bit RGB co-ordinates
127 * - 'full'-precision (unshifted) 8-bit L*a*b* co-ordinates
128 * - box-space (reduced-precision shifted L*a*b*) co-ordinates
129 */
130
131 #include "config.h"
132
133 #include <stdlib.h>
134 #include <stdio.h>
135 #include <string.h>
136
137 #include <cairo.h>
138 #include <gdk-pixbuf/gdk-pixbuf.h>
139 #include <gegl.h>
140
141 #include "libgimpcolor/gimpcolor.h"
142 #include "libgimpmath/gimpmath.h"
143
144 #include "core-types.h"
145
146 #include "gegl/gimp-babl.h"
147 #include "gegl/gimp-gegl-utils.h"
148
149 #include "gimp.h"
150 #include "gimpcontainer.h"
151 #include "gimpdrawable.h"
152 #include "gimperror.h"
153 #include "gimpimage.h"
154 #include "gimpimage-color-profile.h"
155 #include "gimpimage-colormap.h"
156 #include "gimpimage-undo.h"
157 #include "gimpimage-undo-push.h"
158 #include "gimplayer.h"
159 #include "gimpobjectqueue.h"
160 #include "gimppalette.h"
161 #include "gimpprogress.h"
162
163 #include "text/gimptextlayer.h"
164
165 #include "gimpimage-convert-fsdither.h"
166 #include "gimpimage-convert-data.h"
167 #include "gimpimage-convert-indexed.h"
168
169 #include "gimp-intl.h"
170
171
172 /* basic memory/quality tradeoff */
173 #define PRECISION_R 8
174 #define PRECISION_G 6
175 #define PRECISION_B 6
176
177 #define HIST_R_ELEMS (1<<PRECISION_R)
178 #define HIST_G_ELEMS (1<<PRECISION_G)
179 #define HIST_B_ELEMS (1<<PRECISION_B)
180
181 #define BITS_IN_SAMPLE 8
182
183 #define R_SHIFT (BITS_IN_SAMPLE-PRECISION_R)
184 #define G_SHIFT (BITS_IN_SAMPLE-PRECISION_G)
185 #define B_SHIFT (BITS_IN_SAMPLE-PRECISION_B)
186
187 /* we've stretched our non-cubic L*a*b* volume to touch the
188 * faces of the logical cube we've allocated for it, so re-scale
189 * again in inverse proportion to get back to linear proportions.
190 */
191 #define R_SCALE 13 /* scale R (L*) distances by this much */
192 #define G_SCALE 24 /* scale G (a*) distances by this much */
193 #define B_SCALE 26 /* and B (b*) by this much */
194
195
196 typedef struct _Color Color;
197 typedef struct _QuantizeObj QuantizeObj;
198
199 typedef void (* Pass1Func) (QuantizeObj *quantize_obj);
200 typedef void (* Pass2InitFunc) (QuantizeObj *quantize_obj);
201 typedef void (* Pass2Func) (QuantizeObj *quantize_obj,
202 GimpLayer *layer,
203 GeglBuffer *new_buffer);
204 typedef void (* CleanupFunc) (QuantizeObj *quantize_obj);
205
206 typedef guint64 ColorFreq;
207 typedef ColorFreq * CFHistogram;
208
209 typedef enum { AXIS_UNDEF, AXIS_RED, AXIS_BLUE, AXIS_GREEN } AxisType;
210
211 typedef double etype;
212
213
214 /*
215 We provide two different histogram access interfaces. HIST_LIN()
216 accesses the histogram in histogram-native space, taking absolute
217 histogram co-ordinates. HIST_RGB() accesses the histogram in RGB
218 space. This latter takes unsigned 8-bit co-ordinates, internally
219 converts those co-ordinates to histogram-native space and returns
220 the access pointer to the corresponding histogram cell.
221
222 Using these two interfaces we can import RGB data into a more
223 interesting space and efficiently work in the latter space until
224 it is time to output the quantized values in RGB again. For
225 this final conversion we implement the function lin_to_rgb().
226
227 We effectively pull our three-dimensional space into five dimensions
228 such that the most-entropic bits lay in the lowest bits of the resulting
229 array index. This gives significantly better locality of reference
230 and hence a small speedup despite the extra work involved in calculating
231 the index.
232
233 Why not six dimensions? The expansion of dimensionality is good for random
234 access such as histogram population and the query pattern typical of
235 dithering but we have some code which iterates in a scanning manner, for
236 which the expansion is suboptimal. The compromise is to leave the B
237 dimension unmolested in the lower-order bits of the index, since this is
238 the dimension most commonly iterated through in the inner loop of the
239 scans.
240
241 --adam
242
243 RhGhRlGlB
244 */
245 #define VOL_GBITS (PRECISION_G)
246 #define VOL_BBITS (PRECISION_B)
247 #define VOL_RBITS (PRECISION_R)
248 #define VOL_GBITSh (VOL_GBITS - 3)
249 #define VOL_GBITSl (VOL_GBITS - VOL_GBITSh)
250 #define VOL_BBITSh (VOL_BBITS - 4)
251 #define VOL_BBITSl (VOL_BBITS - VOL_BBITSh)
252 #define VOL_RBITSh (VOL_RBITS - 3)
253 #define VOL_RBITSl (VOL_RBITS - VOL_RBITSh)
254 #define VOL_GMASKh (((1<<VOL_GBITSh)-1) << VOL_GBITSl)
255 #define VOL_GMASKl ((1<<VOL_GBITSl)-1)
256 #define VOL_BMASKh (((1<<VOL_BBITSh)-1) << VOL_BBITSl)
257 #define VOL_BMASKl ((1<<VOL_BBITSl)-1)
258 #define VOL_RMASKh (((1<<VOL_RBITSh)-1) << VOL_RBITSl)
259 #define VOL_RMASKl ((1<<VOL_RBITSl)-1)
260 /* The 5d compromise thing. */
261 #define REF_FUNC(r,g,b) \
262 ( \
263 (((r) & VOL_RMASKh) << (VOL_BBITS + VOL_GBITS)) | \
264 (((r) & VOL_RMASKl) << (VOL_GBITSl + VOL_BBITS)) | \
265 (((g) & VOL_GMASKh) << (VOL_RBITSl + VOL_BBITS)) | \
266 (((g) & VOL_GMASKl) << (VOL_BBITS)) | \
267 (b) \
268 )
269 /* The full-on 6d thing. */
270 /*
271 #define REF_FUNC(r,g,b) \
272 ( \
273 (((r) & VOL_RMASKh) << (VOL_BBITS + VOL_GBITS)) | \
274 (((r) & VOL_RMASKl) << (VOL_GBITSl + VOL_BBITSl)) | \
275 (((g) & VOL_GMASKh) << (VOL_RBITSl + VOL_BBITS)) | \
276 (((g) & VOL_GMASKl) << (VOL_BBITSl)) | \
277 (((b) & VOL_BMASKh) << (VOL_RBITSl + VOL_GBITSl)) | \
278 ((b) & VOL_BMASKl) \
279 )
280 */
281 /* The boring old 3d thing. */
282 /*
283 #define REF_FUNC(r,g,b) (((r)<<(PRECISION_G+PRECISION_B)) | ((g)<<(PRECISION_B)) | (b))
284 */
285
286 /* You even get to choose whether you want the accessor function
287 implemented as a macro or an inline function. Don't say I never
288 give you anything. */
289 /*
290 #define HIST_LIN(hist_ptr,r,g,b) (&(hist_ptr)[REF_FUNC((r),(g),(b))])
291 */
292 static inline ColorFreq *
HIST_LIN(ColorFreq * hist_ptr,const gint r,const gint g,const gint b)293 HIST_LIN (ColorFreq *hist_ptr,
294 const gint r,
295 const gint g,
296 const gint b)
297 {
298 return (&(hist_ptr) [REF_FUNC (r, g, b)]);
299 }
300
301
302 #define LOWA (-86.181F)
303 #define LOWB (-107.858F)
304 #define HIGHA (98.237F)
305 #define HIGHB (94.480F)
306
307 #if 1
308 #define LRAT (2.55F)
309 #define ARAT (255.0F / (HIGHA - LOWA))
310 #define BRAT (255.0F / (HIGHB - LOWB))
311 #else
312 #define LRAT (1.0F)
313 #define ARAT (1.0F)
314 #define BRAT (1.0F)
315 #endif
316
317 static const Babl *rgb_to_lab_fish = NULL;
318 static const Babl *lab_to_rgb_fish = NULL;
319
320 static inline void
rgb_to_unshifted_lin(const guchar r,const guchar g,const guchar b,gint * hr,gint * hg,gint * hb)321 rgb_to_unshifted_lin (const guchar r,
322 const guchar g,
323 const guchar b,
324 gint *hr,
325 gint *hg,
326 gint *hb)
327 {
328 gint or, og, ob;
329 gfloat rgb[3] = { r / 255.0, g / 255.0, b / 255.0 };
330 gfloat lab[3];
331
332 babl_process (rgb_to_lab_fish, rgb, lab, 1);
333
334 /* fprintf(stderr, " %d-%d-%d -> %0.3f,%0.3f,%0.3f ", r, g, b, sL, sa, sb);*/
335
336 or = RINT(lab[0] * LRAT);
337 og = RINT((lab[1] - LOWA) * ARAT);
338 ob = RINT((lab[2] - LOWB) * BRAT);
339
340 *hr = CLAMP(or, 0, 255);
341 *hg = CLAMP(og, 0, 255);
342 *hb = CLAMP(ob, 0, 255);
343
344 /* fprintf(stderr, " %d:%d:%d ", *hr, *hg, *hb); */
345 }
346
347
348 static inline void
rgb_to_lin(const guchar r,const guchar g,const guchar b,gint * hr,gint * hg,gint * hb)349 rgb_to_lin (const guchar r,
350 const guchar g,
351 const guchar b,
352 gint *hr,
353 gint *hg,
354 gint *hb)
355 {
356 gint or, og, ob;
357
358 /*
359 double sL, sa, sb;
360 {
361 double low_l = 999.0, low_a = 999.9, low_b = 999.0;
362 double high_l = -999.0, high_a = -999.0, high_b = -999.0;
363
364 int r,g,b;
365
366 for (r=0; r<256; r++)
367 for (g=0; g<256; g++)
368 for (b=0; b<256; b++)
369 {
370 cpercep_rgb_to_space(r,g,b, &sL, &sa, &sb);
371
372 if (sL > high_l)
373 high_l = sL;
374 if (sL < low_l)
375 low_l = sL;
376 if (sa > high_a)
377 high_a = sa;
378 if (sa < low_a)
379 low_a = sa;
380 if (sb > high_b)
381 high_b = sb;
382 if (sb < low_b)
383 low_b = sb;
384 }
385
386 fprintf(stderr, " [L: %0.3f -> %0.3f / a: %0.3f -> %0.3f / b: %0.3f -> %0.3f]\t", low_l, high_l, low_a, high_a, low_b, high_b);
387
388 exit(-1);
389 }
390 */
391
392 rgb_to_unshifted_lin (r, g, b, &or, &og, &ob);
393
394 #if 0
395 #define RSDF(r) ((r) >= ((HIST_R_ELEMS-1) << R_SHIFT) ? HIST_R_ELEMS-1 : \
396 ((r) + ((1<<R_SHIFT)>>1) ) >> R_SHIFT)
397 #define GSDF(g) ((g) >= ((HIST_G_ELEMS-1) << G_SHIFT) ? HIST_G_ELEMS-1 : \
398 ((g) + ((1<<G_SHIFT)>>1) ) >> G_SHIFT)
399 #define BSDF(b) ((b) >= ((HIST_B_ELEMS-1) << B_SHIFT) ? HIST_B_ELEMS-1 : \
400 ((b) + ((1<<B_SHIFT)>>1) ) >> B_SHIFT)
401 #else
402 #define RSDF(r) ((r) >> R_SHIFT)
403 #define GSDF(g) ((g) >> G_SHIFT)
404 #define BSDF(b) ((b) >> B_SHIFT)
405 #endif
406
407 or = RSDF (or);
408 og = GSDF (og);
409 ob = BSDF (ob);
410
411 *hr = or;
412 *hg = og;
413 *hb = ob;
414 }
415
416
417 static inline ColorFreq *
HIST_RGB(ColorFreq * hist_ptr,const gint r,const gint g,const gint b)418 HIST_RGB (ColorFreq *hist_ptr,
419 const gint r,
420 const gint g,
421 const gint b)
422 {
423 gint hr, hg, hb;
424
425 rgb_to_lin (r, g, b, &hr, &hg, &hb);
426
427 return HIST_LIN (hist_ptr, hr, hg, hb);
428 }
429
430
431 static inline void
lin_to_rgb(const gdouble hr,const gdouble hg,const gdouble hb,guchar * r,guchar * g,guchar * b)432 lin_to_rgb (const gdouble hr,
433 const gdouble hg,
434 const gdouble hb,
435 guchar *r,
436 guchar *g,
437 guchar *b)
438 {
439 gfloat rgb[3];
440 gfloat lab[3];
441 gdouble ir, ig, ib;
442
443 ir = ((gdouble) (hr)) * 255.0F / (gdouble) (HIST_R_ELEMS - 1);
444 ig = ((gdouble)( hg)) * 255.0F / (gdouble) (HIST_G_ELEMS - 1);
445 ib = ((gdouble)( hb)) * 255.0F / (gdouble) (HIST_B_ELEMS - 1);
446
447 ir = ir / LRAT;
448 ig = (ig / ARAT) + LOWA;
449 ib = (ib / BRAT) + LOWB;
450
451 lab[0] = ir;
452 lab[1] = ig;
453 lab[2] = ib;
454
455 babl_process (lab_to_rgb_fish, lab, rgb, 1);
456
457 *r = RINT (CLAMP (rgb[0] * 255, 0.0F, 255.0F));
458 *g = RINT (CLAMP (rgb[1] * 255, 0.0F, 255.0F));
459 *b = RINT (CLAMP (rgb[2] * 255, 0.0F, 255.0F));
460 }
461
462
463
464 struct _Color
465 {
466 gint red;
467 gint green;
468 gint blue;
469 };
470
471 struct _QuantizeObj
472 {
473 Pass1Func first_pass; /* first pass over image data creates colormap */
474 Pass2InitFunc second_pass_init; /* Initialize data which persists over invocations */
475 Pass2Func second_pass; /* second pass maps from image data to colormap */
476 CleanupFunc delete_func; /* function to clean up data associated with private */
477
478 GimpPalette *custom_palette; /* The custom palette, if any */
479
480 gint desired_number_of_colors; /* Number of colors we will allow */
481 gint actual_number_of_colors; /* Number of colors actually needed */
482 Color cmap[256]; /* colormap created by quantization */
483 Color clin[256]; /* .. converted back to linear space */
484 guint64 index_used_count[256]; /* how many times an index was used */
485 CFHistogram histogram; /* holds the histogram */
486
487 gboolean want_dither_alpha;
488 gint error_freedom; /* 0=much bleed, 1=controlled bleed */
489
490 GimpProgress *progress;
491 };
492
493 typedef struct
494 {
495 /* The bounds of the box (inclusive); expressed as histogram indexes */
496 gint Rmin, Rmax;
497 gint Rhalferror;
498 gint Gmin, Gmax;
499 gint Ghalferror;
500 gint Bmin, Bmax;
501 gint Bhalferror;
502
503 /* The volume (actually 2-norm) of the box */
504 gint volume;
505
506 /* The number of nonzero histogram cells within this box */
507 gint64 colorcount;
508
509 /* The sum of the weighted error within this box */
510 guint64 error;
511 /* The sum of the unweighted error within this box */
512 guint64 rerror;
513 guint64 gerror;
514 guint64 berror;
515
516 } box, *boxptr;
517
518
519 static void zero_histogram_gray (CFHistogram histogram);
520 static void zero_histogram_rgb (CFHistogram histogram);
521 static void generate_histogram_gray (CFHistogram hostogram,
522 GimpLayer *layer,
523 gboolean dither_alpha);
524 static void generate_histogram_rgb (CFHistogram histogram,
525 GimpLayer *layer,
526 gint col_limit,
527 gboolean dither_alpha,
528 GimpProgress *progress);
529
530 static QuantizeObj * initialize_median_cut (GimpImageBaseType old_type,
531 gint max_colors,
532 GimpConvertDitherType dither_type,
533 GimpConvertPaletteType palette_type,
534 GimpPalette *custom_palette,
535 gboolean dither_alpha,
536 GimpProgress *progress);
537
538 static void compute_color_lin8 (QuantizeObj *quantobj,
539 CFHistogram histogram,
540 boxptr boxp,
541 const int icolor);
542
543
544 static guchar found_cols[MAXNUMCOLORS][3];
545 static gint num_found_cols;
546 static gboolean needs_quantize;
547 static gboolean had_white;
548 static gboolean had_black;
549
550
551 /**********************************************************/
552 typedef struct
553 {
554 gint64 used_count;
555 guchar initial_index;
556 } PalEntry;
557
558 static int
mapping_compare(const void * a,const void * b)559 mapping_compare (const void *a,
560 const void *b)
561 {
562 PalEntry *m1 = (PalEntry *) a;
563 PalEntry *m2 = (PalEntry *) b;
564
565 return (m2->used_count - m1->used_count);
566 }
567
568 /* FWIW, the make_remap_table() and mapping_compare() function source
569 * and PalEntry may be re-used under the XFree86-style license.
570 * <adam@gimp.org>
571 */
572 static void
make_remap_table(const guchar old_palette[],guchar new_palette[],const guint64 index_used_count[],guchar remap_table[],gint * num_entries)573 make_remap_table (const guchar old_palette[],
574 guchar new_palette[],
575 const guint64 index_used_count[],
576 guchar remap_table[],
577 gint *num_entries)
578 {
579 gint i, j, k;
580 guchar temppal[256 * 3];
581 guint64 tempuse[256];
582 guint64 transmap[256];
583 PalEntry *palentries;
584 gint used = 0;
585
586 memset (temppal, 0, 256 * 3);
587 memset (tempuse, 0, 256 * sizeof (guint64));
588 memset (transmap, 255, 256 * sizeof (guint64));
589
590 /* First pass - only collect entries which are marked as being used
591 * at all in index_used_count.
592 */
593 for (i = 0; i < *num_entries; i++)
594 {
595 if (index_used_count[i])
596 {
597 temppal[used*3 + 0] = old_palette[i*3 + 0];
598 temppal[used*3 + 1] = old_palette[i*3 + 1];
599 temppal[used*3 + 2] = old_palette[i*3 + 2];
600
601 tempuse[used] = index_used_count[i];
602 transmap[i] = used;
603
604 used++;
605 }
606 }
607
608 /* Second pass - remove duplicates. (O(n^3), could do better!) */
609 for (i = 0; i < used; i++)
610 {
611 for (j = 0; j < i; j++)
612 {
613 if ((temppal[i*3 + 1] == temppal[j*3 + 1]) &&
614 (temppal[i*3 + 0] == temppal[j*3 + 0]) &&
615 (temppal[i*3 + 2] == temppal[j*3 + 2]) &&
616 tempuse[j] &&
617 tempuse[i])
618 {
619 /* Move the 'used' tally from one to the other. */
620 tempuse[i] += tempuse[j];
621 /* zero one of them, deactivating its entry. */
622 tempuse[j] = 0;
623
624 /* change all mappings from this dead index to the live
625 * one.
626 */
627 for (k = 0; k < *num_entries; k++)
628 {
629 if (index_used_count[k] && (transmap[k] == j))
630 transmap[k] = i;
631 }
632 }
633 }
634 }
635
636 /* Third pass - rank all used indices to the beginning of the
637 * palette.
638 */
639 palentries = g_new (PalEntry, used);
640
641 for (i = 0; i < used; i++)
642 {
643 palentries[i].initial_index = i;
644 palentries[i].used_count = tempuse[i];
645 }
646
647 qsort (palentries, used, sizeof (PalEntry), &mapping_compare);
648
649 for (i = 0; i < *num_entries; i++)
650 {
651 if (index_used_count[i])
652 {
653 for (j = 0; j < used; j++)
654 {
655 if ((transmap[i] == palentries[j].initial_index)
656 && (palentries[j].used_count))
657 {
658 remap_table[i] = j;
659 break;
660 }
661 }
662 }
663 }
664 for (i = 0; i < *num_entries; i++)
665 {
666 if (index_used_count[i])
667 {
668 new_palette[remap_table[i] * 3 + 0] = old_palette[i * 3 + 0];
669 new_palette[remap_table[i] * 3 + 1] = old_palette[i * 3 + 1];
670 new_palette[remap_table[i] * 3 + 2] = old_palette[i * 3 + 2];
671 }
672 }
673
674 *num_entries = 0;
675
676 for (j = 0; j < used; j++)
677 {
678 if (palentries[j].used_count)
679 {
680 (*num_entries)++;
681 }
682 }
683
684 g_free (palentries);
685 }
686
687 static void
remap_indexed_layer(GimpLayer * layer,const guchar * remap_table,gint num_entries)688 remap_indexed_layer (GimpLayer *layer,
689 const guchar *remap_table,
690 gint num_entries)
691 {
692 GeglBufferIterator *iter;
693 const Babl *format;
694 gint bpp;
695 gboolean has_alpha;
696
697 format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
698
699 bpp = babl_format_get_bytes_per_pixel (format);
700 has_alpha = babl_format_has_alpha (format);
701
702 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
703 NULL, 0, NULL,
704 GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE, 1);
705
706 while (gegl_buffer_iterator_next (iter))
707 {
708 guchar *data = iter->items[0].data;
709 gint length = iter->length;
710
711 if (has_alpha)
712 {
713 while (length--)
714 {
715 if (data[ALPHA_I])
716 data[INDEXED] = remap_table[data[INDEXED]];
717 else
718 data[INDEXED] = 0;
719
720 data += bpp;
721 }
722 }
723 else
724 {
725 while (length--)
726 {
727 data[INDEXED] = remap_table[data[INDEXED]];
728
729 data += bpp;
730 }
731 }
732 }
733 }
734
735 static gint
color_quicksort(const void * c1,const void * c2)736 color_quicksort (const void *c1,
737 const void *c2)
738 {
739 Color *color1 = (Color *) c1;
740 Color *color2 = (Color *) c2;
741
742 gdouble v1 = GIMP_RGB_LUMINANCE (color1->red, color1->green, color1->blue);
743 gdouble v2 = GIMP_RGB_LUMINANCE (color2->red, color2->green, color2->blue);
744
745 if (v1 < v2)
746 return -1;
747 else if (v1 > v2)
748 return 1;
749 else
750 return 0;
751 }
752
753 gboolean
gimp_image_convert_indexed(GimpImage * image,GimpConvertPaletteType palette_type,gint max_colors,gboolean remove_duplicates,GimpConvertDitherType dither_type,gboolean dither_alpha,gboolean dither_text_layers,GimpPalette * custom_palette,GimpProgress * progress,GError ** error)754 gimp_image_convert_indexed (GimpImage *image,
755 GimpConvertPaletteType palette_type,
756 gint max_colors,
757 gboolean remove_duplicates,
758 GimpConvertDitherType dither_type,
759 gboolean dither_alpha,
760 gboolean dither_text_layers,
761 GimpPalette *custom_palette,
762 GimpProgress *progress,
763 GError **error)
764 {
765 QuantizeObj *quantobj = NULL;
766 GimpObjectQueue *queue = NULL;
767 GimpProgress *sub_progress = NULL;
768 GimpImageBaseType old_type;
769 GList *all_layers;
770 GList *list;
771 GimpColorProfile *dest_profile = NULL;
772
773 g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
774 g_return_val_if_fail (gimp_image_get_base_type (image) != GIMP_INDEXED, FALSE);
775 g_return_val_if_fail (gimp_babl_is_valid (GIMP_INDEXED,
776 gimp_image_get_precision (image)),
777 FALSE);
778 g_return_val_if_fail (custom_palette == NULL ||
779 GIMP_IS_PALETTE (custom_palette), FALSE);
780 g_return_val_if_fail (custom_palette == NULL ||
781 gimp_palette_get_n_colors (custom_palette) <= 256,
782 FALSE);
783 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
784 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
785
786 if (palette_type == GIMP_CONVERT_PALETTE_CUSTOM)
787 {
788 if (! custom_palette)
789 palette_type = GIMP_CONVERT_PALETTE_MONO;
790
791 if (gimp_palette_get_n_colors (custom_palette) == 0)
792 {
793 g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
794 _("Cannot convert image: palette is empty."));
795 return FALSE;
796 }
797 }
798
799 gimp_set_busy (image->gimp);
800
801 all_layers = gimp_image_get_layer_list (image);
802
803 g_object_freeze_notify (G_OBJECT (image));
804
805 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_CONVERT,
806 C_("undo-type", "Convert Image to Indexed"));
807
808 /* Push the image type to the stack */
809 gimp_image_undo_push_image_type (image, NULL);
810
811 /* Set the new base type */
812 old_type = gimp_image_get_base_type (image);
813
814 g_object_set (image, "base-type", GIMP_INDEXED, NULL);
815
816 /* when converting from GRAY, convert to the new type's builtin
817 * profile.
818 */
819 if (old_type == GIMP_GRAY)
820 {
821 if (gimp_image_get_color_profile (image))
822 dest_profile = gimp_image_get_builtin_color_profile (image);
823 }
824
825 /* Build histogram if necessary. */
826 rgb_to_lab_fish = babl_fish (babl_format ("R'G'B' float"),
827 babl_format ("CIE Lab float"));
828 lab_to_rgb_fish = babl_fish (babl_format ("CIE Lab float"),
829 babl_format ("R'G'B' float"));
830
831 /* don't dither if the input is grayscale and we are simply mapping
832 * every color
833 */
834 if (old_type == GIMP_GRAY &&
835 max_colors == 256 &&
836 palette_type == GIMP_CONVERT_PALETTE_GENERATE)
837 {
838 dither_type = GIMP_CONVERT_DITHER_NONE;
839 }
840
841 if (progress)
842 {
843 queue = gimp_object_queue_new (progress);
844 sub_progress = GIMP_PROGRESS (queue);
845
846 gimp_object_queue_push_list (queue, all_layers);
847 }
848
849 quantobj = initialize_median_cut (old_type, max_colors, dither_type,
850 palette_type, custom_palette,
851 dither_alpha,
852 sub_progress);
853
854 if (palette_type == GIMP_CONVERT_PALETTE_GENERATE)
855 {
856 if (old_type == GIMP_GRAY)
857 zero_histogram_gray (quantobj->histogram);
858 else
859 zero_histogram_rgb (quantobj->histogram);
860
861 /* To begin, assume that there are fewer colors in the image
862 * than the user actually asked for. In that case, we don't
863 * need to quantize or color-dither.
864 */
865 needs_quantize = FALSE;
866 had_black = FALSE;
867 had_white = FALSE;
868 num_found_cols = 0;
869
870 /* Build the histogram */
871 for (list = all_layers;
872 list;
873 list = g_list_next (list))
874 {
875 GimpLayer *layer = list->data;
876
877 if (queue)
878 gimp_object_queue_pop (queue);
879
880 if (old_type == GIMP_GRAY)
881 {
882 generate_histogram_gray (quantobj->histogram,
883 layer, dither_alpha);
884 }
885 else
886 {
887 /* Note: generate_histogram_rgb may set needs_quantize
888 * if the image contains more colors than the limit
889 * specified by the user.
890 */
891 generate_histogram_rgb (quantobj->histogram,
892 layer, max_colors, dither_alpha,
893 sub_progress);
894 }
895 }
896 }
897
898 if (progress)
899 gimp_progress_set_text_literal (progress,
900 _("Converting to indexed colors (stage 2)"));
901
902 if (old_type == GIMP_RGB &&
903 ! needs_quantize &&
904 palette_type == GIMP_CONVERT_PALETTE_GENERATE)
905 {
906 gint i;
907
908 /* If this is an RGB image, and the user wanted a custom-built
909 * generated palette, and this image has no more colors than
910 * the user asked for, we don't need the first pass
911 * (quantization).
912 *
913 * There's also no point in dithering, since there's no error
914 * to spread. So we destroy the old quantobj and make a new
915 * one with the remapping function set to a special LUT-based
916 * no-dither remapper.
917 */
918
919 quantobj->delete_func (quantobj);
920 quantobj = initialize_median_cut (old_type, max_colors,
921 GIMP_CONVERT_DITHER_NODESTRUCT,
922 palette_type,
923 custom_palette,
924 dither_alpha,
925 sub_progress);
926 /* We can skip the first pass (palette creation) */
927
928 quantobj->actual_number_of_colors = num_found_cols;
929 for (i = 0; i < num_found_cols; i++)
930 {
931 quantobj->cmap[i].red = found_cols[i][0];
932 quantobj->cmap[i].green = found_cols[i][1];
933 quantobj->cmap[i].blue = found_cols[i][2];
934 }
935 }
936 else
937 {
938 quantobj->first_pass (quantobj);
939 }
940
941 if (palette_type == GIMP_CONVERT_PALETTE_GENERATE)
942 qsort (quantobj->cmap,
943 quantobj->actual_number_of_colors, sizeof (Color),
944 color_quicksort);
945
946 if (progress)
947 {
948 gimp_progress_set_text_literal (progress,
949 _("Converting to indexed colors (stage 3)"));
950
951 gimp_object_queue_clear (queue);
952 gimp_object_queue_push_list (queue, all_layers);
953 }
954
955 /* Initialise data which must persist across indexed layer iterations */
956 if (quantobj->second_pass_init)
957 quantobj->second_pass_init (quantobj);
958
959 /* Set the generated palette on the image, we need it to
960 * convert the layers. We optionally remove duplicate entries
961 * after the layer conversion.
962 */
963 {
964 guchar colormap[GIMP_IMAGE_COLORMAP_SIZE];
965 gint i, j;
966
967 for (i = 0, j = 0; i < quantobj->actual_number_of_colors; i++)
968 {
969 colormap[j++] = quantobj->cmap[i].red;
970 colormap[j++] = quantobj->cmap[i].green;
971 colormap[j++] = quantobj->cmap[i].blue;
972 }
973
974 gimp_image_set_colormap (image, colormap,
975 quantobj->actual_number_of_colors, TRUE);
976 }
977
978 /* Convert all layers */
979 for (list = all_layers;
980 list;
981 list = g_list_next (list))
982 {
983 GimpLayer *layer = list->data;
984 gboolean quantize;
985
986 if (queue)
987 gimp_object_queue_pop (queue);
988
989 if (gimp_item_is_text_layer (GIMP_ITEM (layer)))
990 quantize = dither_text_layers;
991 else
992 quantize = TRUE;
993
994 if (quantize)
995 {
996 GeglBuffer *new_buffer;
997 gboolean has_alpha;
998
999 has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer));
1000
1001 new_buffer =
1002 gegl_buffer_new (GEGL_RECTANGLE (0, 0,
1003 gimp_item_get_width (GIMP_ITEM (layer)),
1004 gimp_item_get_height (GIMP_ITEM (layer))),
1005 gimp_image_get_layer_format (image,
1006 has_alpha));
1007
1008 quantobj->second_pass (quantobj, layer, new_buffer);
1009
1010 gimp_drawable_set_buffer (GIMP_DRAWABLE (layer), TRUE, NULL,
1011 new_buffer);
1012 g_object_unref (new_buffer);
1013 }
1014 else
1015 {
1016 gimp_drawable_convert_type (GIMP_DRAWABLE (layer), image,
1017 GIMP_INDEXED,
1018 gimp_drawable_get_precision (GIMP_DRAWABLE (layer)),
1019 gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)),
1020 dest_profile,
1021 GEGL_DITHER_NONE, GEGL_DITHER_NONE,
1022 TRUE, sub_progress);
1023 }
1024 }
1025
1026 /* Set the final palette on the image */
1027 if (remove_duplicates &&
1028 (palette_type != GIMP_CONVERT_PALETTE_GENERATE) &&
1029 (palette_type != GIMP_CONVERT_PALETTE_MONO))
1030 {
1031 guchar colormap[GIMP_IMAGE_COLORMAP_SIZE];
1032 gint i, j;
1033 guchar old_palette[256 * 3];
1034 guchar new_palette[256 * 3];
1035 guchar remap_table[256];
1036 gint num_entries;
1037
1038 for (i = 0, j = 0; i < quantobj->actual_number_of_colors; i++)
1039 {
1040 old_palette[j++] = quantobj->cmap[i].red;
1041 old_palette[j++] = quantobj->cmap[i].green;
1042 old_palette[j++] = quantobj->cmap[i].blue;
1043 }
1044
1045 num_entries = quantobj->actual_number_of_colors;
1046
1047 /* Generate a remapping table */
1048 make_remap_table (old_palette, new_palette,
1049 quantobj->index_used_count,
1050 remap_table, &num_entries);
1051
1052 /* Convert all layers */
1053 for (list = all_layers; list; list = g_list_next (list))
1054 {
1055 remap_indexed_layer (list->data, remap_table, num_entries);
1056 }
1057
1058 for (i = 0, j = 0; i < num_entries; i++)
1059 {
1060 colormap[j] = new_palette[j]; j++;
1061 colormap[j] = new_palette[j]; j++;
1062 colormap[j] = new_palette[j]; j++;
1063 }
1064
1065 gimp_image_set_colormap (image, colormap, num_entries, TRUE);
1066 }
1067
1068 /* When converting from GRAY, set the new profile.
1069 */
1070 if (old_type == GIMP_GRAY)
1071 {
1072 if (gimp_image_get_color_profile (image))
1073 gimp_image_set_color_profile (image, dest_profile, NULL);
1074 else
1075 gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (image));
1076 }
1077
1078 /* Delete the quantizer object, if there is one */
1079 if (quantobj)
1080 quantobj->delete_func (quantobj);
1081
1082 gimp_image_undo_group_end (image);
1083
1084 gimp_image_mode_changed (image);
1085 g_object_thaw_notify (G_OBJECT (image));
1086
1087 g_clear_object (&queue);
1088
1089 g_list_free (all_layers);
1090
1091 gimp_unset_busy (image->gimp);
1092
1093 return TRUE;
1094 }
1095
1096 /*
1097 * Indexed color conversion machinery
1098 */
1099
1100 static void
zero_histogram_gray(CFHistogram histogram)1101 zero_histogram_gray (CFHistogram histogram)
1102 {
1103 gint i;
1104
1105 for (i = 0; i < 256; i++)
1106 histogram[i] = 0;
1107 }
1108
1109
1110 static void
zero_histogram_rgb(CFHistogram histogram)1111 zero_histogram_rgb (CFHistogram histogram)
1112 {
1113 memset (histogram, 0,
1114 HIST_R_ELEMS * HIST_G_ELEMS * HIST_B_ELEMS * sizeof (ColorFreq));
1115 }
1116
1117
1118 static void
generate_histogram_gray(CFHistogram histogram,GimpLayer * layer,gboolean dither_alpha)1119 generate_histogram_gray (CFHistogram histogram,
1120 GimpLayer *layer,
1121 gboolean dither_alpha)
1122 {
1123 GeglBufferIterator *iter;
1124 const Babl *format;
1125 gint bpp;
1126 gboolean has_alpha;
1127
1128 format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
1129
1130 g_return_if_fail (format == babl_format_with_space ("Y' u8", format) ||
1131 format == babl_format_with_space ("Y'A u8", format));
1132
1133 bpp = babl_format_get_bytes_per_pixel (format);
1134 has_alpha = babl_format_has_alpha (format);
1135
1136 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
1137 NULL, 0, format,
1138 GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);
1139
1140 while (gegl_buffer_iterator_next (iter))
1141 {
1142 const guchar *data = iter->items[0].data;
1143 gint length = iter->length;
1144
1145 if (has_alpha)
1146 {
1147 while (length--)
1148 {
1149 if (data[ALPHA_G] > 127)
1150 histogram[*data]++;
1151
1152 data += bpp;
1153 }
1154 }
1155 else
1156 {
1157 while (length--)
1158 {
1159 histogram[*data]++;
1160
1161 data += bpp;
1162 }
1163 }
1164 }
1165 }
1166
1167 static void
check_white_or_black(const guchar * data)1168 check_white_or_black (const guchar *data)
1169 {
1170 if (data[RED] == 255 &&
1171 data[GREEN] == 255 &&
1172 data[BLUE] == 255)
1173 had_white = TRUE;
1174 if (data[RED] ==0 &&
1175 data[GREEN]==0 &&
1176 data[BLUE] ==0)
1177 had_black = TRUE;
1178 }
1179
1180 static void
generate_histogram_rgb(CFHistogram histogram,GimpLayer * layer,gint col_limit,gboolean dither_alpha,GimpProgress * progress)1181 generate_histogram_rgb (CFHistogram histogram,
1182 GimpLayer *layer,
1183 gint col_limit,
1184 gboolean dither_alpha,
1185 GimpProgress *progress)
1186 {
1187 GeglBufferIterator *iter;
1188 const Babl *format;
1189 GeglRectangle *roi;
1190 ColorFreq *colfreq;
1191 gint nfc_iter;
1192 gint row, col, coledge;
1193 gint offsetx, offsety;
1194 gint64 layer_size;
1195 gint64 total_size = 0;
1196 gint count = 0;
1197 gint bpp;
1198 gboolean has_alpha;
1199
1200 format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
1201
1202 g_return_if_fail (format == babl_format ("R'G'B' u8") ||
1203 format == babl_format ("R'G'B'A u8"));
1204
1205 bpp = babl_format_get_bytes_per_pixel (format);
1206 has_alpha = babl_format_has_alpha (format);
1207
1208 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
1209
1210 layer_size = (gimp_item_get_width (GIMP_ITEM (layer)) *
1211 gimp_item_get_height (GIMP_ITEM (layer)));
1212
1213 /* g_printerr ("col_limit = %d, nfc = %d\n", col_limit, num_found_cols); */
1214
1215 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
1216 NULL, 0, format,
1217 GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);
1218 roi = &iter->items[0].roi;
1219
1220 if (progress)
1221 gimp_progress_set_value (progress, 0.0);
1222
1223 while (gegl_buffer_iterator_next (iter))
1224 {
1225 const guchar *data = iter->items[0].data;
1226 gint length = iter->length;
1227
1228 total_size += length;
1229
1230 /* g_printerr (" [%d,%d - %d,%d]", srcPR.x, src_roi->y, offsetx, offsety); */
1231
1232 if (needs_quantize)
1233 {
1234 if (dither_alpha)
1235 {
1236 /* if alpha-dithering,
1237 we need to be deterministic w.r.t. offsets */
1238
1239 col = roi->x + offsetx;
1240 coledge = col + roi->width;
1241 row = roi->y + offsety;
1242
1243 while (length--)
1244 {
1245 gboolean transparent = FALSE;
1246
1247 if (has_alpha &&
1248 data[ALPHA] <
1249 DM[col & DM_WIDTHMASK][row & DM_HEIGHTMASK])
1250 transparent = TRUE;
1251
1252 if (! transparent)
1253 {
1254 colfreq = HIST_RGB (histogram,
1255 data[RED],
1256 data[GREEN],
1257 data[BLUE]);
1258 check_white_or_black (data);
1259 (*colfreq)++;
1260 }
1261
1262 col++;
1263 if (col == coledge)
1264 {
1265 col = roi->x + offsetx;
1266 row++;
1267 }
1268
1269 data += bpp;
1270 }
1271 }
1272 else
1273 {
1274 while (length--)
1275 {
1276 if ((has_alpha && ((data[ALPHA] > 127)))
1277 || (!has_alpha))
1278 {
1279 colfreq = HIST_RGB (histogram,
1280 data[RED],
1281 data[GREEN],
1282 data[BLUE]);
1283 check_white_or_black (data);
1284 (*colfreq)++;
1285 }
1286
1287 data += bpp;
1288 }
1289 }
1290 }
1291 else
1292 {
1293 /* if alpha-dithering, we need to be deterministic w.r.t. offsets */
1294 col = roi->x + offsetx;
1295 coledge = col + roi->width;
1296 row = roi->y + offsety;
1297
1298 while (length--)
1299 {
1300 gboolean transparent = FALSE;
1301
1302 if (has_alpha)
1303 {
1304 if (dither_alpha)
1305 {
1306 if (data[ALPHA] <
1307 DM[col & DM_WIDTHMASK][row & DM_HEIGHTMASK])
1308 transparent = TRUE;
1309 }
1310 else
1311 {
1312 if (data[ALPHA] <= 127)
1313 transparent = TRUE;
1314 }
1315 }
1316
1317 if (! transparent)
1318 {
1319 colfreq = HIST_RGB (histogram,
1320 data[RED],
1321 data[GREEN],
1322 data[BLUE]);
1323 (*colfreq)++;
1324
1325 if (!needs_quantize)
1326 {
1327 for (nfc_iter = 0;
1328 nfc_iter < num_found_cols;
1329 nfc_iter++)
1330 {
1331 if ((data[RED] == found_cols[nfc_iter][0]) &&
1332 (data[GREEN] == found_cols[nfc_iter][1]) &&
1333 (data[BLUE] == found_cols[nfc_iter][2]))
1334 goto already_found;
1335 }
1336
1337 /* Color was not in the table of
1338 * existing colors
1339 */
1340
1341 num_found_cols++;
1342
1343 if (num_found_cols > col_limit)
1344 {
1345 /* There are more colors in the image than
1346 * were allowed. We switch to plain
1347 * histogram calculation with a view to
1348 * quantizing at a later stage.
1349 */
1350 needs_quantize = TRUE;
1351 /* g_print ("\nmax colors exceeded - needs quantize.\n");*/
1352 goto already_found;
1353 }
1354 else
1355 {
1356 /* Remember the new color we just found.
1357 */
1358 found_cols[num_found_cols-1][0] = data[RED];
1359 found_cols[num_found_cols-1][1] = data[GREEN];
1360 found_cols[num_found_cols-1][2] = data[BLUE];
1361
1362 check_white_or_black (data);
1363 }
1364 }
1365 }
1366 already_found:
1367
1368 col++;
1369 if (col == coledge)
1370 {
1371 col = roi->x + offsetx;
1372 row++;
1373 }
1374
1375 data += bpp;
1376 }
1377 }
1378
1379 if (progress && (count % 16 == 0))
1380 gimp_progress_set_value (progress,
1381 (gdouble) total_size / (gdouble) layer_size);
1382 }
1383
1384 /* g_print ("O: col_limit = %d, nfc = %d\n", col_limit, num_found_cols);*/
1385 }
1386
1387
1388
1389 static boxptr
find_split_candidate(const boxptr boxlist,const gint numboxes,AxisType * which_axis,const gint desired_colors)1390 find_split_candidate (const boxptr boxlist,
1391 const gint numboxes,
1392 AxisType *which_axis,
1393 const gint desired_colors)
1394 {
1395 boxptr boxp;
1396 gint i;
1397 etype maxc = 0;
1398 boxptr which = NULL;
1399 gdouble Lbias;
1400
1401 *which_axis = AXIS_UNDEF;
1402
1403 /* we only perform the initial L-split bias /at all/ if the final
1404 number of desired colors is quite low, otherwise it all comes
1405 out in the wash anyway and this initial bias generally only hurts
1406 us in the long run. */
1407 if (desired_colors <= 16)
1408 {
1409 #define BIAS_FACTOR 2.66F
1410 #define BIAS_NUMBER 2 /* 0 */
1411
1412 /* we bias towards splitting across L* for first few colors */
1413 Lbias = (numboxes > BIAS_NUMBER) ? 1.0F : ((gdouble) (BIAS_NUMBER + 1) -
1414 ((gdouble) numboxes)) /
1415 ((gdouble) BIAS_NUMBER / BIAS_FACTOR);
1416 /*Lbias = 1.0;
1417 fprintf(stderr, " [[%d]] ", numboxes);
1418 fprintf(stderr, "Using ramped L-split bias.\n");
1419 fprintf(stderr, "R\n");
1420 */
1421 }
1422 else
1423 Lbias = 1.0F;
1424
1425 for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++)
1426 {
1427 if (boxp->volume > 0)
1428 {
1429 #ifndef _MSC_VER
1430 etype rpe = (double)((boxp->rerror) * R_SCALE * R_SCALE);
1431 etype gpe = (double)((boxp->gerror) * G_SCALE * G_SCALE);
1432 etype bpe = (double)((boxp->berror) * B_SCALE * B_SCALE);
1433 #else
1434 /*
1435 * Sorry about the mess, otherwise would get :
1436 * error C2520: conversion from unsigned __int64 to double
1437 * not implemented, use signed __int64
1438 */
1439 etype rpe = (double)(((__int64)boxp->rerror) * R_SCALE * R_SCALE);
1440 etype gpe = (double)(((__int64)boxp->gerror) * G_SCALE * G_SCALE);
1441 etype bpe = (double)(((__int64)boxp->berror) * B_SCALE * B_SCALE);
1442 #endif
1443
1444 if (Lbias * rpe > maxc &&
1445 boxp->Rmin < boxp->Rmax)
1446 {
1447 which = boxp;
1448 maxc = Lbias * rpe;
1449 *which_axis = AXIS_RED;
1450 }
1451
1452 if (gpe > maxc &&
1453 boxp->Gmin < boxp->Gmax)
1454 {
1455 which = boxp;
1456 maxc = gpe;
1457 *which_axis = AXIS_GREEN;
1458 }
1459
1460 if (bpe > maxc &&
1461 boxp->Bmin < boxp->Bmax)
1462 {
1463 which = boxp;
1464 maxc = bpe;
1465 *which_axis = AXIS_BLUE;
1466 }
1467 }
1468 }
1469
1470 /* fprintf(stderr, " %f,%p ", maxc, which); */
1471 /* fprintf(stderr, " %llu ", maxc); */
1472
1473 return which;
1474 }
1475
1476
1477 /* Find the splittable box with the largest (scaled) volume Returns
1478 * NULL if no splittable boxes remain
1479 */
1480 static boxptr
find_biggest_volume(const boxptr boxlist,const gint numboxes)1481 find_biggest_volume (const boxptr boxlist,
1482 const gint numboxes)
1483 {
1484 boxptr boxp;
1485 gint i;
1486 gint maxv = 0;
1487 boxptr which = NULL;
1488
1489 for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++)
1490 {
1491 if (boxp->volume > maxv)
1492 {
1493 which = boxp;
1494 maxv = boxp->volume;
1495 }
1496 }
1497
1498 return which;
1499 }
1500
1501
1502 /* Shrink the min/max bounds of a box to enclose only nonzero
1503 * elements, and recompute its volume and population
1504 */
1505 static void
update_box_gray(const CFHistogram histogram,boxptr boxp)1506 update_box_gray (const CFHistogram histogram,
1507 boxptr boxp)
1508 {
1509 gint i, min, max, dist;
1510 ColorFreq ccount;
1511
1512 min = boxp->Rmin;
1513 max = boxp->Rmax;
1514
1515 if (max > min)
1516 for (i = min; i <= max; i++)
1517 {
1518 if (histogram[i] != 0)
1519 {
1520 boxp->Rmin = min = i;
1521 break;
1522 }
1523 }
1524
1525 if (max > min)
1526 for (i = max; i >= min; i--)
1527 {
1528 if (histogram[i] != 0)
1529 {
1530 boxp->Rmax = max = i;
1531 break;
1532 }
1533 }
1534
1535 /* Update box volume.
1536 * We use 2-norm rather than real volume here; this biases the method
1537 * against making long narrow boxes, and it has the side benefit that
1538 * a box is splittable iff norm > 0.
1539 * Since the differences are expressed in histogram-cell units,
1540 * we have to shift back to JSAMPLE units to get consistent distances;
1541 * after which, we scale according to the selected distance scale factors.
1542 */
1543 dist = max - min;
1544 boxp->volume = dist * dist;
1545
1546 /* Now scan remaining volume of box and compute population */
1547 ccount = 0;
1548 for (i = min; i <= max; i++)
1549 if (histogram[i] != 0)
1550 ccount++;
1551
1552 boxp->colorcount = ccount;
1553 }
1554
1555
1556 /* Shrink the min/max bounds of a box to enclose only nonzero
1557 * elements, and recompute its volume, population and error
1558 */
1559 static void
update_box_rgb(const CFHistogram histogram,boxptr boxp,const gint cells_remaining)1560 update_box_rgb (const CFHistogram histogram,
1561 boxptr boxp,
1562 const gint cells_remaining)
1563 {
1564 gint R, G, B;
1565 gint Rmin, Rmax, Gmin, Gmax, Bmin, Bmax;
1566 gint dist0, dist1, dist2;
1567 ColorFreq ccount;
1568 /*
1569 guint64 tempRerror;
1570 guint64 tempGerror;
1571 guint64 tempBerror;
1572 */
1573 QuantizeObj dummyqo;
1574 box dummybox;
1575
1576 /* fprintf(stderr, "U"); */
1577
1578 Rmin = boxp->Rmin; Rmax = boxp->Rmax;
1579 Gmin = boxp->Gmin; Gmax = boxp->Gmax;
1580 Bmin = boxp->Bmin; Bmax = boxp->Bmax;
1581
1582 if (Rmax > Rmin)
1583 for (R = Rmin; R <= Rmax; R++)
1584 for (G = Gmin; G <= Gmax; G++)
1585 {
1586 for (B = Bmin; B <= Bmax; B++)
1587 {
1588 if (*HIST_LIN (histogram, R, G, B) != 0)
1589 {
1590 boxp->Rmin = Rmin = R;
1591 goto have_Rmin;
1592 }
1593 }
1594 }
1595 have_Rmin:
1596 if (Rmax > Rmin)
1597 for (R = Rmax; R >= Rmin; R--)
1598 for (G = Gmin; G <= Gmax; G++)
1599 {
1600 for (B = Bmin; B <= Bmax; B++)
1601 {
1602 if (*HIST_LIN (histogram, R, G, B) != 0)
1603 {
1604 boxp->Rmax = Rmax = R;
1605 goto have_Rmax;
1606 }
1607 }
1608 }
1609 have_Rmax:
1610 if (Gmax > Gmin)
1611 for (G = Gmin; G <= Gmax; G++)
1612 for (R = Rmin; R <= Rmax; R++)
1613 {
1614 for (B = Bmin; B <= Bmax; B++)
1615 {
1616 if (*HIST_LIN (histogram, R, G, B) != 0)
1617 {
1618 boxp->Gmin = Gmin = G;
1619 goto have_Gmin;
1620 }
1621 }
1622 }
1623 have_Gmin:
1624 if (Gmax > Gmin)
1625 for (G = Gmax; G >= Gmin; G--)
1626 for (R = Rmin; R <= Rmax; R++)
1627 {
1628 for (B = Bmin; B <= Bmax; B++)
1629 {
1630 if (*HIST_LIN (histogram, R, G, B) != 0)
1631 {
1632 boxp->Gmax = Gmax = G;
1633 goto have_Gmax;
1634 }
1635 }
1636 }
1637 have_Gmax:
1638 if (Bmax > Bmin)
1639 for (B = Bmin; B <= Bmax; B++)
1640 for (R = Rmin; R <= Rmax; R++)
1641 {
1642 for (G = Gmin; G <= Gmax; G++)
1643 {
1644 if (*HIST_LIN (histogram, R, G, B) != 0)
1645 {
1646 boxp->Bmin = Bmin = B;
1647 goto have_Bmin;
1648 }
1649 }
1650 }
1651 have_Bmin:
1652 if (Bmax > Bmin)
1653 for (B = Bmax; B >= Bmin; B--)
1654 for (R = Rmin; R <= Rmax; R++)
1655 {
1656 for (G = Gmin; G <= Gmax; G++)
1657 {
1658 if (*HIST_LIN (histogram, R, G, B) != 0)
1659 {
1660 boxp->Bmax = Bmax = B;
1661 goto have_Bmax;
1662 }
1663 }
1664 }
1665 have_Bmax:
1666
1667 /* Update box volume.
1668 * We use 2-norm rather than real volume here; this biases the method
1669 * against making long narrow boxes, and it has the side benefit that
1670 * a box is splittable iff norm > 0. (ADM: note: this isn't true.)
1671 * Since the differences are expressed in histogram-cell units,
1672 * we have to shift back to JSAMPLE units to get consistent distances;
1673 * after which, we scale according to the selected distance scale factors.
1674 */
1675 dist0 = ((1 + Rmax - Rmin) << R_SHIFT) * R_SCALE;
1676 dist1 = ((1 + Gmax - Gmin) << G_SHIFT) * G_SCALE;
1677 dist2 = ((1 + Bmax - Bmin) << B_SHIFT) * B_SCALE;
1678 boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
1679 /* boxp->volume = dist0 * dist1 * dist2; */
1680
1681 compute_color_lin8(&dummyqo, histogram, boxp, 0);
1682
1683 /*printf("(%d %d %d)\n", dummyqo.cmap[0].red,dummyqo.cmap[0].green,dummyqo.cmap[0].blue);
1684 fflush(stdout);*/
1685
1686 /* Now scan remaining volume of box and compute population */
1687 ccount = 0;
1688 boxp->error = 0;
1689 boxp->rerror = 0;
1690 boxp->gerror = 0;
1691 boxp->berror = 0;
1692 for (R = Rmin; R <= Rmax; R++)
1693 {
1694 for (G = Gmin; G <= Gmax; G++)
1695 {
1696 for (B = Bmin; B <= Bmax; B++)
1697 {
1698 ColorFreq freq_here;
1699
1700 freq_here = *HIST_LIN (histogram, R, G, B);
1701
1702 if (freq_here != 0)
1703 {
1704 int ge, be, re;
1705
1706 dummybox.Rmin = dummybox.Rmax = R;
1707 dummybox.Gmin = dummybox.Gmax = G;
1708 dummybox.Bmin = dummybox.Bmax = B;
1709 compute_color_lin8(&dummyqo, histogram, &dummybox, 1);
1710
1711 re = dummyqo.cmap[0].red - dummyqo.cmap[1].red;
1712 ge = dummyqo.cmap[0].green - dummyqo.cmap[1].green;
1713 be = dummyqo.cmap[0].blue - dummyqo.cmap[1].blue;
1714
1715 boxp->rerror += freq_here * (re) * (re);
1716 boxp->gerror += freq_here * (ge) * (ge);
1717 boxp->berror += freq_here * (be) * (be);
1718
1719 ccount += freq_here;
1720 }
1721 }
1722 }
1723 }
1724
1725 #if 0
1726 fg d;flg fd;kg fld;gflkfld
1727 /* Scan again, taking note of halfway error point for red axis */
1728 tempRerror = 0;
1729 boxp->Rhalferror = Rmin;
1730 #warning r<=?
1731 for (R = Rmin; R <= Rmax; R++)
1732 {
1733 for (G = Gmin; G <= Gmax; G++)
1734 {
1735 for (B = Bmin; B <= Bmax; B++)
1736 {
1737 ColorFreq freq_here;
1738 freq_here = *HIST_LIN(histogram, R, G, B);
1739 if (freq_here != 0)
1740 {
1741 int re;
1742 int idist;
1743 double dist;
1744
1745 dummybox.Rmin = dummybox.Rmax = R;
1746 dummybox.Gmin = dummybox.Gmax = G;
1747 dummybox.Bmin = dummybox.Bmax = B;
1748 compute_color_lin8(&dummyqo, histogram, &dummybox, 1);
1749
1750 re = dummyqo.cmap[0].red - dummyqo.cmap[1].red;
1751
1752 tempRerror += freq_here * (re) * (re);
1753
1754 if (tempRerror*2 >= boxp->rerror)
1755 goto green_axisscan;
1756 else
1757 boxp->Rhalferror = R;
1758 }
1759 }
1760 }
1761 }
1762 fprintf(stderr, " D:");
1763 green_axisscan:
1764
1765 fprintf(stderr, "<%d: %llu/%llu> ", R, tempRerror, boxp->rerror);
1766 /* Scan again, taking note of halfway error point for green axis */
1767 tempGerror = 0;
1768 boxp->Ghalferror = Gmin;
1769 #warning G<=?
1770 for (G = Gmin; G <= Gmax; G++)
1771 {
1772 for (R = Rmin; R <= Rmax; R++)
1773 {
1774 for (B = Bmin; B <= Bmax; B++)
1775 {
1776 ColorFreq freq_here;
1777 freq_here = *HIST_LIN(histogram, R, G, B);
1778 if (freq_here != 0)
1779 {
1780 int ge;
1781 dummybox.Rmin = dummybox.Rmax = R;
1782 dummybox.Gmin = dummybox.Gmax = G;
1783 dummybox.Bmin = dummybox.Bmax = B;
1784 compute_color_lin8(&dummyqo, histogram, &dummybox, 1);
1785
1786 ge = dummyqo.cmap[0].green - dummyqo.cmap[1].green;
1787
1788 tempGerror += freq_here * (ge) * (ge);
1789
1790 if (tempGerror*2 >= boxp->gerror)
1791 goto blue_axisscan;
1792 else
1793 boxp->Ghalferror = G;
1794 }
1795 }
1796 }
1797 }
1798
1799 blue_axisscan:
1800 /* Scan again, taking note of halfway error point for blue axis */
1801 tempBerror = 0;
1802 boxp->Bhalferror = Bmin;
1803 #warning B<=?
1804 for (B = Bmin; B <= Bmax; B++)
1805 {
1806 for (R = Rmin; R <= Rmax; R++)
1807 {
1808 for (G = Gmin; G <= Gmax; G++)
1809 {
1810 ColorFreq freq_here;
1811 freq_here = *HIST_LIN(histogram, R, G, B);
1812 if (freq_here != 0)
1813 {
1814 int be;
1815 dummybox.Rmin = dummybox.Rmax = R;
1816 dummybox.Gmin = dummybox.Gmax = G;
1817 dummybox.Bmin = dummybox.Bmax = B;
1818 compute_color_lin8(&dummyqo, histogram, &dummybox, 1);
1819
1820 be = dummyqo.cmap[0].blue - dummyqo.cmap[1].blue;
1821
1822 tempBerror += freq_here * (be) * (be);
1823
1824 if (tempBerror*2 >= boxp->berror)
1825 goto finished_axesscan;
1826 else
1827 boxp->Bhalferror = B;
1828 }
1829 }
1830 }
1831 }
1832 finished_axesscan:
1833 #else
1834
1835 boxp->Rhalferror = Rmin + (Rmax - Rmin + 1) / 2;
1836 boxp->Ghalferror = Gmin + (Gmax - Gmin + 1) / 2;
1837 boxp->Bhalferror = Bmin + (Bmax - Bmin + 1) / 2;
1838
1839 if (dist0 && dist1 && dist2)
1840 {
1841 AxisType longest_ax = AXIS_UNDEF;
1842 gint longest_length = 0;
1843 gint longest_length2 = 0;
1844 gint ratio;
1845
1846 /*
1847 fprintf(stderr, "[%d,%d,%d=%d,%d,%d] ",
1848 (Rmax - Rmin), (Gmax - Gmin), (Bmax - Bmin),
1849 dist0, dist1, dist2);
1850 */
1851
1852 if (dist0 >= longest_length)
1853 {
1854 longest_length2 = longest_length;
1855 longest_length = dist0;
1856 longest_ax = AXIS_RED;
1857 }
1858 else if (dist0 >= longest_length2)
1859 {
1860 longest_length2 = dist0;
1861 }
1862
1863 if (dist1 >= longest_length)
1864 {
1865 longest_length2 = longest_length;
1866 longest_length = dist1;
1867 longest_ax = AXIS_GREEN;
1868 }
1869 else if (dist1 >= longest_length2)
1870 {
1871 longest_length2 = dist1;
1872 }
1873
1874 if (dist2 >= longest_length)
1875 {
1876 longest_length2 = longest_length;
1877 longest_length = dist2;
1878 longest_ax = AXIS_BLUE;
1879 }
1880 else if (dist2 >= longest_length2)
1881 {
1882 longest_length2 = dist2;
1883 }
1884
1885 if (longest_length2 == 0)
1886 longest_length2 = 1;
1887
1888 ratio = (longest_length + longest_length2/2) / longest_length2;
1889 /* fprintf(stderr, " ratio:(%d/%d)=%d ", longest_length, longest_length2, ratio);
1890 fprintf(stderr, "C%d ", cells_remaining); */
1891
1892 if (ratio > cells_remaining + 1)
1893 ratio = cells_remaining + 1;
1894
1895 if (ratio > 2)
1896 {
1897 switch (longest_ax)
1898 {
1899 case AXIS_RED:
1900 if (Rmin + (Rmax - Rmin + ratio / 2) / ratio < Rmax)
1901 {
1902 /* fprintf(stderr, "FR%d \007\n",ratio);*/
1903 boxp->Rhalferror = Rmin + (Rmax - Rmin + ratio / 2) / ratio;
1904 }
1905 break;
1906 case AXIS_GREEN:
1907 if (Gmin + (Gmax - Gmin + ratio / 2) / ratio < Gmax)
1908 {
1909 /* fprintf(stderr, "FG%d \007\n",ratio);*/
1910 boxp->Ghalferror = Gmin + (Gmax - Gmin + ratio / 2) / ratio;
1911 }
1912 break;
1913 case AXIS_BLUE:
1914 if (Bmin + (Bmax - Bmin + ratio / 2) / ratio < Bmax)
1915 {
1916 /* fprintf(stderr, "FB%d \007\n",ratio);*/
1917 boxp->Bhalferror = Bmin + (Bmax - Bmin + ratio / 2) / ratio;
1918 }
1919 break;
1920 default:
1921 g_warning ("GRR, UNDEF LONGEST AXIS\007\n");
1922 }
1923 }
1924 }
1925
1926 if (boxp->Rhalferror == Rmax)
1927 boxp->Rhalferror = Rmin;
1928 if (boxp->Ghalferror == Gmax)
1929 boxp->Ghalferror = Gmin;
1930 if (boxp->Bhalferror == Bmax)
1931 boxp->Bhalferror = Bmin;
1932
1933 /*
1934 boxp->Rhalferror = RSDF(dummyqo.cmap[0].red);
1935 boxp->Ghalferror = GSDF(dummyqo.cmap[0].green);
1936 boxp->Bhalferror = BSDF(dummyqo.cmap[0].blue);
1937 */
1938
1939 /*
1940 boxp->Rhalferror = (RSDF(dummyqo.cmap[0].red) + (Rmin+Rmax)/2)/2;
1941 boxp->Ghalferror = (GSDF(dummyqo.cmap[0].green) + (Gmin+Gmax)/2)/2;
1942 boxp->Bhalferror = (BSDF(dummyqo.cmap[0].blue) + (Bmin+Bmax)/2)/2;
1943 */
1944
1945
1946 #endif
1947 /*
1948 fprintf(stderr, " %d,%d", dummyqo.cmap[0].blue, boxp->Bmax);
1949
1950 gimp_assert (boxp->Rhalferror >= boxp->Rmin);
1951 gimp_assert (boxp->Rhalferror < boxp->Rmax);
1952 gimp_assert (boxp->Ghalferror >= boxp->Gmin);
1953 gimp_assert (boxp->Ghalferror < boxp->Gmax);
1954 gimp_assert (boxp->Bhalferror >= boxp->Bmin);
1955 gimp_assert (boxp->Bhalferror < boxp->Bmax);*/
1956
1957 /*boxp->error = (sqrt((double)(boxp->error/ccount)));*/
1958 /* boxp->rerror = (sqrt((double)((boxp->rerror)/ccount)));
1959 boxp->gerror = (sqrt((double)((boxp->gerror)/ccount)));
1960 boxp->berror = (sqrt((double)((boxp->berror)/ccount)));*/
1961 /*printf(":%lld / %ld: ", boxp->error, ccount);
1962 printf("(%d-%d-%d)(%d-%d-%d)(%d-%d-%d)\n",
1963 Rmin, boxp->Rhalferror, Rmax,
1964 Gmin, boxp->Ghalferror, Gmax,
1965 Bmin, boxp->Bhalferror, Bmax
1966 );
1967 fflush(stdout);*/
1968
1969 boxp->colorcount = ccount;
1970 }
1971
1972
1973 /* Repeatedly select and split the largest box until we have enough
1974 * boxes
1975 */
1976 static gint
median_cut_gray(CFHistogram histogram,boxptr boxlist,gint numboxes,gint desired_colors)1977 median_cut_gray (CFHistogram histogram,
1978 boxptr boxlist,
1979 gint numboxes,
1980 gint desired_colors)
1981 {
1982 gint lb;
1983 boxptr b1, b2;
1984
1985 while (numboxes < desired_colors)
1986 {
1987 /* Select box to split.
1988 * Current algorithm: by population for first half, then by volume.
1989 */
1990
1991 b1 = find_biggest_volume (boxlist, numboxes);
1992
1993 if (b1 == NULL) /* no splittable boxes left! */
1994 break;
1995
1996 b2 = boxlist + numboxes; /* where new box will go */
1997 /* Copy the color bounds to the new box. */
1998 b2->Rmax = b1->Rmax;
1999 b2->Rmin = b1->Rmin;
2000
2001 /* Current algorithm: split at halfway point.
2002 * (Since the box has been shrunk to minimum volume,
2003 * any split will produce two nonempty subboxes.)
2004 * Note that lb value is max for lower box, so must be < old max.
2005 */
2006 lb = (b1->Rmax + b1->Rmin) / 2;
2007 b1->Rmax = lb;
2008 b2->Rmin = lb + 1;
2009
2010 /* Update stats for boxes */
2011 update_box_gray (histogram, b1);
2012 update_box_gray (histogram, b2);
2013 numboxes++;
2014 }
2015
2016 return numboxes;
2017 }
2018
2019 /* Repeatedly select and split the largest box until we have enough
2020 * boxes
2021 */
2022 static gint
median_cut_rgb(CFHistogram histogram,boxptr boxlist,gint numboxes,gint desired_colors,GimpProgress * progress)2023 median_cut_rgb (CFHistogram histogram,
2024 boxptr boxlist,
2025 gint numboxes,
2026 gint desired_colors,
2027 GimpProgress *progress)
2028 {
2029 gint lb;
2030 boxptr b1, b2;
2031 AxisType which_axis;
2032
2033 while (numboxes < desired_colors)
2034 {
2035 b1 = find_split_candidate (boxlist, numboxes, &which_axis, desired_colors);
2036
2037 if (b1 == NULL) /* no splittable boxes left! */
2038 break;
2039
2040 b2 = boxlist + numboxes; /* where new box will go */
2041 /* Copy the color bounds to the new box. */
2042 b2->Rmax = b1->Rmax; b2->Gmax = b1->Gmax; b2->Bmax = b1->Bmax;
2043 b2->Rmin = b1->Rmin; b2->Gmin = b1->Gmin; b2->Bmin = b1->Bmin;
2044
2045
2046 /* Choose split point along selected axis, and update box bounds.
2047 * Note that lb value is max for lower box, so must be < old max.
2048 */
2049 switch (which_axis)
2050 {
2051 case AXIS_RED:
2052 lb = b1->Rhalferror;/* *0 + (b1->Rmax + b1->Rmin) / 2; */
2053 b1->Rmax = lb;
2054 b2->Rmin = lb+1;
2055 g_return_val_if_fail (b1->Rmax >= b1->Rmin, numboxes);
2056 g_return_val_if_fail (b2->Rmax >= b2->Rmin, numboxes);
2057 break;
2058 case AXIS_GREEN:
2059 lb = b1->Ghalferror;/* *0 + (b1->Gmax + b1->Gmin) / 2; */
2060 b1->Gmax = lb;
2061 b2->Gmin = lb+1;
2062 g_return_val_if_fail (b1->Gmax >= b1->Gmin, numboxes);
2063 g_return_val_if_fail (b2->Gmax >= b2->Gmin, numboxes);
2064 break;
2065 case AXIS_BLUE:
2066 lb = b1->Bhalferror;/* *0 + (b1->Bmax + b1->Bmin) / 2; */
2067 b1->Bmax = lb;
2068 b2->Bmin = lb+1;
2069 g_return_val_if_fail (b1->Bmax >= b1->Bmin, numboxes);
2070 g_return_val_if_fail (b2->Bmax >= b2->Bmin, numboxes);
2071 break;
2072 default:
2073 g_error ("Uh-oh.");
2074 }
2075 /* Update stats for boxes */
2076 numboxes++;
2077
2078 if (progress && (numboxes % 16 == 0))
2079 gimp_progress_set_value (progress, (gdouble) numboxes / desired_colors);
2080
2081 update_box_rgb (histogram, b1, desired_colors - numboxes);
2082 update_box_rgb (histogram, b2, desired_colors - numboxes);
2083 }
2084
2085 return numboxes;
2086 }
2087
2088
2089 /* Compute representative color for a box, put it in colormap[icolor]
2090 */
2091 static void
compute_color_gray(QuantizeObj * quantobj,CFHistogram histogram,boxptr boxp,int icolor)2092 compute_color_gray (QuantizeObj *quantobj,
2093 CFHistogram histogram,
2094 boxptr boxp,
2095 int icolor)
2096 {
2097 gint i, min, max;
2098 guint64 count;
2099 guint64 total;
2100 guint64 gtotal;
2101
2102 min = boxp->Rmin;
2103 max = boxp->Rmax;
2104
2105 total = 0;
2106 gtotal = 0;
2107
2108 for (i = min; i <= max; i++)
2109 {
2110 count = histogram[i];
2111 if (count != 0)
2112 {
2113 total += count;
2114 gtotal += i * count;
2115 }
2116 }
2117
2118 if (total != 0)
2119 {
2120 quantobj->cmap[icolor].red =
2121 quantobj->cmap[icolor].green =
2122 quantobj->cmap[icolor].blue = (gtotal + (total >> 1)) / total;
2123 }
2124 else
2125 {
2126 /* The only situation where total==0 is if the image was null or
2127 * all-transparent. In that case we just put a dummy value in
2128 * the colormap.
2129 */
2130 quantobj->cmap[icolor].red =
2131 quantobj->cmap[icolor].green =
2132 quantobj->cmap[icolor].blue = 0;
2133 }
2134 }
2135
2136
2137 /* Compute representative color for a box, put it in colormap[icolor]
2138 */
2139 static void
compute_color_rgb(QuantizeObj * quantobj,CFHistogram histogram,boxptr boxp,int icolor)2140 compute_color_rgb (QuantizeObj *quantobj,
2141 CFHistogram histogram,
2142 boxptr boxp,
2143 int icolor)
2144 {
2145 /* Current algorithm: mean weighted by pixels (not colors) */
2146 /* Note it is important to get the rounding correct! */
2147 gint R, G, B;
2148 gint Rmin, Rmax;
2149 gint Gmin, Gmax;
2150 gint Bmin, Bmax;
2151 ColorFreq total = 0;
2152 ColorFreq Rtotal = 0;
2153 ColorFreq Gtotal = 0;
2154 ColorFreq Btotal = 0;
2155
2156 Rmin = boxp->Rmin; Rmax = boxp->Rmax;
2157 Gmin = boxp->Gmin; Gmax = boxp->Gmax;
2158 Bmin = boxp->Bmin; Bmax = boxp->Bmax;
2159
2160 for (R = Rmin; R <= Rmax; R++)
2161 for (G = Gmin; G <= Gmax; G++)
2162 {
2163 for (B = Bmin; B <= Bmax; B++)
2164 {
2165 ColorFreq this_freq = *HIST_LIN (histogram, R, G, B);
2166
2167 if (this_freq != 0)
2168 {
2169 total += this_freq;
2170 Rtotal += R * this_freq;
2171 Gtotal += G * this_freq;
2172 Btotal += B * this_freq;
2173 }
2174 }
2175 }
2176
2177 if (total > 0)
2178 {
2179 guchar red, green, blue;
2180
2181 lin_to_rgb (/*(Rtotal + (total>>1)) / total,
2182 (Gtotal + (total>>1)) / total,
2183 (Btotal + (total>>1)) / total,*/
2184 (double)Rtotal / (double)total,
2185 (double)Gtotal / (double)total,
2186 (double)Btotal / (double)total,
2187 &red, &green, &blue);
2188
2189 quantobj->cmap[icolor].red = red;
2190 quantobj->cmap[icolor].green = green;
2191 quantobj->cmap[icolor].blue = blue;
2192 }
2193 else
2194 {
2195 /* The only situation where total==0 is if the image was null or
2196 * all-transparent. In that case we just put a dummy value in
2197 * the colormap.
2198 */
2199 quantobj->cmap[icolor].red = 0;
2200 quantobj->cmap[icolor].green = 0;
2201 quantobj->cmap[icolor].blue = 0;
2202 }
2203 }
2204
2205
2206 /* Compute representative color for a box, put it in colormap[icolor]
2207 */
2208 static void
compute_color_lin8(QuantizeObj * quantobj,CFHistogram histogram,boxptr boxp,const gint icolor)2209 compute_color_lin8 (QuantizeObj *quantobj,
2210 CFHistogram histogram,
2211 boxptr boxp,
2212 const gint icolor)
2213 {
2214 /* Current algorithm: mean weighted by pixels (not colors) */
2215 /* Note it is important to get the rounding correct! */
2216 gint R, G, B;
2217 gint Rmin, Rmax;
2218 gint Gmin, Gmax;
2219 gint Bmin, Bmax;
2220 ColorFreq total = 0;
2221 ColorFreq Rtotal = 0;
2222 ColorFreq Gtotal = 0;
2223 ColorFreq Btotal = 0;
2224
2225 Rmin = boxp->Rmin; Rmax = boxp->Rmax;
2226 Gmin = boxp->Gmin; Gmax = boxp->Gmax;
2227 Bmin = boxp->Bmin; Bmax = boxp->Bmax;
2228
2229 for (R = Rmin; R <= Rmax; R++)
2230 for (G = Gmin; G <= Gmax; G++)
2231 {
2232 for (B = Bmin; B <= Bmax; B++)
2233 {
2234 ColorFreq this_freq = *HIST_LIN (histogram, R, G, B);
2235
2236 if (this_freq != 0)
2237 {
2238 Rtotal += R * this_freq;
2239 Gtotal += G * this_freq;
2240 Btotal += B * this_freq;
2241 total += this_freq;
2242 }
2243 }
2244 }
2245
2246 if (total != 0)
2247 {
2248 quantobj->cmap[icolor].red = ((Rtotal << R_SHIFT) + (total>>1)) / total;
2249 quantobj->cmap[icolor].green = ((Gtotal << G_SHIFT) + (total>>1)) / total;
2250 quantobj->cmap[icolor].blue = ((Btotal << B_SHIFT) + (total>>1)) / total;
2251 }
2252 else
2253 {
2254 /* The only situation where total==0 is if the image was null or
2255 * all-transparent. In that case we just put a dummy value in
2256 * the colormap.
2257 */
2258 g_warning ("eep.");
2259 quantobj->cmap[icolor].red = 0;
2260 quantobj->cmap[icolor].green = 128;
2261 quantobj->cmap[icolor].blue = 128;
2262 }
2263 }
2264
2265
2266 /* Master routine for color selection
2267 */
2268 static void
select_colors_gray(QuantizeObj * quantobj,CFHistogram histogram)2269 select_colors_gray (QuantizeObj *quantobj,
2270 CFHistogram histogram)
2271 {
2272 boxptr boxlist;
2273 gint numboxes;
2274 gint desired = quantobj->desired_number_of_colors;
2275 gint i;
2276
2277 /* Allocate workspace for box list */
2278 boxlist = g_new (box, desired);
2279
2280 /* Initialize one box containing whole space */
2281 numboxes = 1;
2282 boxlist[0].Rmin = 0;
2283 boxlist[0].Rmax = 255;
2284 /* Shrink it to actually-used volume and set its statistics */
2285 update_box_gray (histogram, boxlist);
2286 /* Perform median-cut to produce final box list */
2287 numboxes = median_cut_gray (histogram, boxlist, numboxes, desired);
2288
2289 quantobj->actual_number_of_colors = numboxes;
2290 /* Compute the representative color for each box, fill colormap */
2291 for (i = 0; i < numboxes; i++)
2292 compute_color_gray (quantobj, histogram, boxlist + i, i);
2293 }
2294
2295
2296 /* Master routine for color selection
2297 */
2298 static void
select_colors_rgb(QuantizeObj * quantobj,CFHistogram histogram)2299 select_colors_rgb (QuantizeObj *quantobj,
2300 CFHistogram histogram)
2301 {
2302 boxptr boxlist;
2303 gint numboxes;
2304 gint desired = quantobj->desired_number_of_colors;
2305 gint i;
2306
2307 /* Allocate workspace for box list */
2308 boxlist = g_new (box, desired);
2309
2310 /* Initialize one box containing whole space */
2311 numboxes = 1;
2312 boxlist[0].Rmin = 0;
2313 boxlist[0].Rmax = HIST_R_ELEMS - 1;
2314 boxlist[0].Gmin = 0;
2315 boxlist[0].Gmax = HIST_G_ELEMS - 1;
2316 boxlist[0].Bmin = 0;
2317 boxlist[0].Bmax = HIST_B_ELEMS - 1;
2318 /* Shrink it to actually-used volume and set its statistics */
2319 update_box_rgb (histogram, &boxlist[0], quantobj->desired_number_of_colors);
2320 /* Perform median-cut to produce final box list */
2321 numboxes = median_cut_rgb (histogram, boxlist, numboxes, desired,
2322 quantobj->progress);
2323
2324 quantobj->actual_number_of_colors = numboxes;
2325 /* Compute the representative color for each box, fill colormap */
2326 for (i = 0; i < numboxes; i++)
2327 {
2328 compute_color_rgb (quantobj, histogram, &boxlist[i], i);
2329 }
2330
2331 g_free (boxlist);
2332 }
2333
2334
2335 /*
2336 * These routines are concerned with the time-critical task of mapping input
2337 * colors to the nearest color in the selected colormap.
2338 *
2339 * We re-use the histogram space as an "inverse color map", essentially a
2340 * cache for the results of nearest-color searches. All colors within a
2341 * histogram cell will be mapped to the same colormap entry, namely the one
2342 * closest to the cell's center. This may not be quite the closest entry to
2343 * the actual input color, but it's almost as good. A zero in the cache
2344 * indicates we haven't found the nearest color for that cell yet; the array
2345 * is cleared to zeroes before starting the mapping pass. When we find the
2346 * nearest color for a cell, its colormap index plus one is recorded in the
2347 * cache for future use. The pass2 scanning routines call fill_inverse_cmap
2348 * when they need to use an unfilled entry in the cache.
2349 *
2350 * Our method of efficiently finding nearest colors is based on the "locally
2351 * sorted search" idea described by Heckbert and on the incremental distance
2352 * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
2353 * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that
2354 * the distances from a given colormap entry to each cell of the histogram can
2355 * be computed quickly using an incremental method: the differences between
2356 * distances to adjacent cells themselves differ by a constant. This allows a
2357 * fairly fast implementation of the "brute force" approach of computing the
2358 * distance from every colormap entry to every histogram cell. Unfortunately,
2359 * it needs a work array to hold the best-distance-so-far for each histogram
2360 * cell (because the inner loop has to be over cells, not colormap entries).
2361 * The work array elements have to be ints, so the work array would need
2362 * 256Kb at our recommended precision. This is not feasible in DOS machines.
2363 *
2364 * To get around these problems, we apply Thomas' method to compute the
2365 * nearest colors for only the cells within a small subbox of the histogram.
2366 * The work array need be only as big as the subbox, so the memory usage
2367 * problem is solved. Furthermore, we need not fill subboxes that are never
2368 * referenced in pass2; many images use only part of the color gamut, so a
2369 * fair amount of work is saved. An additional advantage of this
2370 * approach is that we can apply Heckbert's locality criterion to quickly
2371 * eliminate colormap entries that are far away from the subbox; typically
2372 * three-fourths of the colormap entries are rejected by Heckbert's criterion,
2373 * and we need not compute their distances to individual cells in the subbox.
2374 * The speed of this approach is heavily influenced by the subbox size: too
2375 * small means too much overhead, too big loses because Heckbert's criterion
2376 * can't eliminate as many colormap entries. Empirically the best subbox
2377 * size seems to be about 1/512th of the histogram (1/8th in each direction).
2378 *
2379 * Thomas' article also describes a refined method which is asymptotically
2380 * faster than the brute-force method, but it is also far more complex and
2381 * cannot efficiently be applied to small subboxes. It is therefore not
2382 * useful for programs intended to be portable to DOS machines. On machines
2383 * with plenty of memory, filling the whole histogram in one shot with Thomas'
2384 * refined method might be faster than the present code --- but then again,
2385 * it might not be any faster, and it's certainly more complicated.
2386 */
2387
2388
2389 /* log2(histogram cells in update box) for each axis; this can be adjusted */
2390 /*#define BOX_R_LOG (PRECISION_R-3)
2391 #define BOX_G_LOG (PRECISION_G-3)
2392 #define BOX_B_LOG (PRECISION_B-3)*/
2393
2394 /*adam*/
2395 #define BOX_R_LOG 0
2396 #define BOX_G_LOG 0
2397 #define BOX_B_LOG 0
2398
2399 #define BOX_R_ELEMS (1<<BOX_R_LOG) /* # of hist cells in update box */
2400 #define BOX_G_ELEMS (1<<BOX_G_LOG)
2401 #define BOX_B_ELEMS (1<<BOX_B_LOG)
2402
2403 #define BOX_R_SHIFT (R_SHIFT + BOX_R_LOG)
2404 #define BOX_G_SHIFT (G_SHIFT + BOX_G_LOG)
2405 #define BOX_B_SHIFT (B_SHIFT + BOX_B_LOG)
2406
2407
2408 /*
2409 * The next three routines implement inverse colormap filling. They
2410 * could all be folded into one big routine, but splitting them up
2411 * this way saves some stack space (the mindist[] and bestdist[]
2412 * arrays need not coexist) and may allow some compilers to produce
2413 * better code by registerizing more inner-loop variables.
2414 */
2415
2416 /* Locate the colormap entries close enough to an update box to be
2417 * candidates for the nearest entry to some cell(s) in the update box.
2418 * The update box is specified by the center coordinates of its first
2419 * cell. The number of candidate colormap entries is returned, and
2420 * their colormap indexes are placed in colorlist[].
2421 *
2422 * This routine uses Heckbert's "locally sorted search" criterion to
2423 * select the colors that need further consideration.
2424 */
2425 static gint
find_nearby_colors(QuantizeObj * quantobj,int minR,int minG,int minB,int colorlist[])2426 find_nearby_colors (QuantizeObj *quantobj,
2427 int minR,
2428 int minG,
2429 int minB,
2430 int colorlist[])
2431 {
2432 int numcolors = quantobj->actual_number_of_colors;
2433 int maxR, maxG, maxB;
2434 int centerR, centerG, centerB;
2435 int i, x, ncolors;
2436 int minmaxdist, min_dist, max_dist, tdist;
2437 int mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
2438
2439 /* Compute true coordinates of update box's upper corner and center.
2440 * Actually we compute the coordinates of the center of the upper-corner
2441 * histogram cell, which are the upper bounds of the volume we care about.
2442 * Note that since ">>" rounds down, the "center" values may be closer to
2443 * min than to max; hence comparisons to them must be "<=", not "<".
2444 */
2445 maxR = minR + ((1 << BOX_R_SHIFT) - (1 << R_SHIFT));
2446 centerR = (minR + maxR + 1) >> 1;
2447 maxG = minG + ((1 << BOX_G_SHIFT) - (1 << G_SHIFT));
2448 centerG = (minG + maxG + 1) >> 1;
2449 maxB = minB + ((1 << BOX_B_SHIFT) - (1 << B_SHIFT));
2450 centerB = (minB + maxB + 1) >> 1;
2451
2452 /* For each color in colormap, find:
2453 * 1. its minimum squared-distance to any point in the update box
2454 * (zero if color is within update box);
2455 * 2. its maximum squared-distance to any point in the update box.
2456 * Both of these can be found by considering only the corners of the box.
2457 * We save the minimum distance for each color in mindist[];
2458 * only the smallest maximum distance is of interest.
2459 */
2460 minmaxdist = 0x7FFFFFFFL;
2461
2462 for (i = 0; i < numcolors; i++)
2463 {
2464 /* We compute the squared-R-distance term, then add in the other two. */
2465 x = quantobj->clin[i].red;
2466 if (x < minR)
2467 {
2468 tdist = (x - minR) * R_SCALE;
2469 min_dist = tdist*tdist;
2470 tdist = (x - maxR) * R_SCALE;
2471 max_dist = tdist*tdist;
2472 }
2473 else if (x > maxR)
2474 {
2475 tdist = (x - maxR) * R_SCALE;
2476 min_dist = tdist*tdist;
2477 tdist = (x - minR) * R_SCALE;
2478 max_dist = tdist*tdist;
2479 }
2480 else
2481 {
2482 /* within cell range so no contribution to min_dist */
2483 min_dist = 0;
2484 if (x <= centerR)
2485 {
2486 tdist = (x - maxR) * R_SCALE;
2487 max_dist = tdist*tdist;
2488 }
2489 else
2490 {
2491 tdist = (x - minR) * R_SCALE;
2492 max_dist = tdist*tdist;
2493 }
2494 }
2495
2496 x = quantobj->clin[i].green;
2497 if (x < minG)
2498 {
2499 tdist = (x - minG) * G_SCALE;
2500 min_dist += tdist*tdist;
2501 tdist = (x - maxG) * G_SCALE;
2502 max_dist += tdist*tdist;
2503 }
2504 else if (x > maxG)
2505 {
2506 tdist = (x - maxG) * G_SCALE;
2507 min_dist += tdist*tdist;
2508 tdist = (x - minG) * G_SCALE;
2509 max_dist += tdist*tdist;
2510 }
2511 else
2512 {
2513 /* within cell range so no contribution to min_dist */
2514 if (x <= centerG)
2515 {
2516 tdist = (x - maxG) * G_SCALE;
2517 max_dist += tdist*tdist;
2518 }
2519 else
2520 {
2521 tdist = (x - minG) * G_SCALE;
2522 max_dist += tdist*tdist;
2523 }
2524 }
2525
2526 x = quantobj->clin[i].blue;
2527 if (x < minB)
2528 {
2529 tdist = (x - minB) * B_SCALE;
2530 min_dist += tdist*tdist;
2531 tdist = (x - maxB) * B_SCALE;
2532 max_dist += tdist*tdist;
2533 }
2534 else if (x > maxB)
2535 {
2536 tdist = (x - maxB) * B_SCALE;
2537 min_dist += tdist*tdist;
2538 tdist = (x - minB) * B_SCALE;
2539 max_dist += tdist*tdist;
2540 }
2541 else
2542 {
2543 /* within cell range so no contribution to min_dist */
2544 if (x <= centerB)
2545 {
2546 tdist = (x - maxB) * B_SCALE;
2547 max_dist += tdist*tdist;
2548 }
2549 else
2550 {
2551 tdist = (x - minB) * B_SCALE;
2552 max_dist += tdist*tdist;
2553 }
2554 }
2555
2556 mindist[i] = min_dist; /* save away the results */
2557 if (max_dist < minmaxdist)
2558 minmaxdist = max_dist;
2559 }
2560
2561 /* Now we know that no cell in the update box is more than minmaxdist
2562 * away from some colormap entry. Therefore, only colors that are
2563 * within minmaxdist of some part of the box need be considered.
2564 */
2565 ncolors = 0;
2566 for (i = 0; i < numcolors; i++)
2567 {
2568 if (mindist[i] <= minmaxdist)
2569 colorlist[ncolors++] = i;
2570 }
2571
2572 return ncolors;
2573 }
2574
2575
2576 /* Find the closest colormap entry for each cell in the update box,
2577 * given the list of candidate colors prepared by find_nearby_colors.
2578 * Return the indexes of the closest entries in the bestcolor[] array.
2579 * This routine uses Thomas' incremental distance calculation method
2580 * to find the distance from a colormap entry to successive cells in
2581 * the box.
2582 */
2583 static void
find_best_colors(QuantizeObj * quantobj,gint minR,gint minG,gint minB,gint numcolors,gint colorlist[],gint bestcolor[])2584 find_best_colors (QuantizeObj *quantobj,
2585 gint minR,
2586 gint minG,
2587 gint minB,
2588 gint numcolors,
2589 gint colorlist[],
2590 gint bestcolor[])
2591 {
2592 gint iR, iG, iB;
2593 gint i, icolor;
2594 gint *bptr; /* pointer into bestdist[] array */
2595 gint *cptr; /* pointer into bestcolor[] array */
2596 gint dist0, dist1; /* initial distance values */
2597 gint dist2; /* current distance in inner loop */
2598 gint xx0, xx1; /* distance increments */
2599 gint xx2;
2600 gint inR, inG, inB; /* initial values for increments */
2601
2602 /* This array holds the distance to the nearest-so-far color for each cell */
2603 gint bestdist[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS] = { 0, };
2604
2605 /* Initialize best-distance for each cell of the update box */
2606 bptr = bestdist;
2607 for (i = BOX_R_ELEMS*BOX_G_ELEMS*BOX_B_ELEMS-1; i >= 0; i--)
2608 *bptr++ = 0x7FFFFFFFL;
2609
2610 /* For each color selected by find_nearby_colors,
2611 * compute its distance to the center of each cell in the box.
2612 * If that's less than best-so-far, update best distance and color number.
2613 */
2614
2615 /* Nominal steps between cell centers ("x" in Thomas article) */
2616 #define STEP_R ((1 << R_SHIFT) * R_SCALE)
2617 #define STEP_G ((1 << G_SHIFT) * G_SCALE)
2618 #define STEP_B ((1 << B_SHIFT) * B_SCALE)
2619
2620 for (i = 0; i < numcolors; i++)
2621 {
2622 icolor = colorlist[i];
2623 /* Compute (square of) distance from minR/G/B to this color */
2624 inR = (minR - quantobj->clin[icolor].red) * R_SCALE;
2625 dist0 = inR*inR;
2626 /* special-case for L*==0: chroma diffs irrelevant */
2627 /* if (minR > 0 || quantobj->clin[icolor].red > 0) */
2628 {
2629 inG = (minG - quantobj->clin[icolor].green) * G_SCALE;
2630 dist0 += inG*inG;
2631 inB = (minB - quantobj->clin[icolor].blue) * B_SCALE;
2632 dist0 += inB*inB;
2633 }
2634 /* else
2635 {
2636 inG = 0;
2637 inB = 0;
2638 } */
2639 /* Form the initial difference increments */
2640 inR = inR * (2 * STEP_R) + STEP_R * STEP_R;
2641 inG = inG * (2 * STEP_G) + STEP_G * STEP_G;
2642 inB = inB * (2 * STEP_B) + STEP_B * STEP_B;
2643 /* Now loop over all cells in box, updating distance per Thomas method */
2644 bptr = bestdist;
2645 cptr = bestcolor;
2646 xx0 = inR;
2647 for (iR = BOX_R_ELEMS-1; iR >= 0; iR--)
2648 {
2649 dist1 = dist0;
2650 xx1 = inG;
2651 for (iG = BOX_G_ELEMS-1; iG >= 0; iG--)
2652 {
2653 dist2 = dist1;
2654 xx2 = inB;
2655 for (iB = BOX_B_ELEMS-1; iB >= 0; iB--)
2656 {
2657 if (dist2 < *bptr)
2658 {
2659 *bptr = dist2;
2660 *cptr = icolor;
2661 }
2662 dist2 += xx2;
2663 xx2 += 2 * STEP_B * STEP_B;
2664 bptr++;
2665 cptr++;
2666 }
2667 dist1 += xx1;
2668 xx1 += 2 * STEP_G * STEP_G;
2669 }
2670 dist0 += xx0;
2671 xx0 += 2 * STEP_R * STEP_R;
2672 }
2673 }
2674 }
2675
2676
2677 /* Fill the inverse-colormap entries in the update box that contains
2678 * histogram cell R/G/B. (Only that one cell MUST be filled, but we
2679 * can fill as many others as we wish.)
2680 */
2681 static void
fill_inverse_cmap_gray(QuantizeObj * quantobj,CFHistogram histogram,gint pixel)2682 fill_inverse_cmap_gray (QuantizeObj *quantobj,
2683 CFHistogram histogram,
2684 gint pixel)
2685 {
2686 Color *cmap = quantobj->cmap;
2687 gint64 mindist;
2688 gint mindisti;
2689 gint i;
2690
2691 g_return_if_fail (quantobj->actual_number_of_colors > 0);
2692
2693 mindist = G_MAXLONG;
2694 mindisti = -1;
2695
2696 for (i = 0; i < quantobj->actual_number_of_colors; i++)
2697 {
2698 gint64 dist = ABS (pixel - cmap[i].red);
2699
2700 if (dist < mindist)
2701 {
2702 mindist = dist;
2703 mindisti = i;
2704
2705 if (mindist == 0)
2706 break;
2707 }
2708 }
2709
2710 histogram[pixel] = mindisti + 1;
2711 }
2712
2713
2714 /* Fill the inverse-colormap entries in the update box that contains
2715 * histogram cell R/G/B. (Only that one cell MUST be filled, but we
2716 * can fill as many others as we wish.)
2717 */
2718 static void
fill_inverse_cmap_rgb(QuantizeObj * quantobj,CFHistogram histogram,gint R,gint G,gint B)2719 fill_inverse_cmap_rgb (QuantizeObj *quantobj,
2720 CFHistogram histogram,
2721 gint R,
2722 gint G,
2723 gint B)
2724 {
2725 gint minR, minG, minB; /* lower left corner of update box */
2726 gint iR, iG, iB;
2727 gint *cptr; /* pointer into bestcolor[] array */
2728 /* This array lists the candidate colormap indexes. */
2729 gint colorlist[MAXNUMCOLORS];
2730 gint numcolors; /* number of candidate colors */
2731 /* This array holds the actually closest colormap index for each cell. */
2732 gint bestcolor[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS] = { 0, };
2733
2734 /* Convert cell coordinates to update box id */
2735 R >>= BOX_R_LOG;
2736 G >>= BOX_G_LOG;
2737 B >>= BOX_B_LOG;
2738
2739 /* Compute true coordinates of update box's origin corner.
2740 * Actually we compute the coordinates of the center of the corner
2741 * histogram cell, which are the lower bounds of the volume we care about.
2742 */
2743 minR = (R << BOX_R_SHIFT) + ((1 << R_SHIFT) >> 1);
2744 minG = (G << BOX_G_SHIFT) + ((1 << G_SHIFT) >> 1);
2745 minB = (B << BOX_B_SHIFT) + ((1 << B_SHIFT) >> 1);
2746
2747 /* Determine which colormap entries are close enough to be candidates
2748 * for the nearest entry to some cell in the update box.
2749 */
2750 numcolors = find_nearby_colors (quantobj, minR, minG, minB, colorlist);
2751
2752 /* Determine the actually nearest colors. */
2753 find_best_colors (quantobj, minR, minG, minB, numcolors, colorlist,
2754 bestcolor);
2755
2756 /* Save the best color numbers (plus 1) in the main cache array */
2757 R <<= BOX_R_LOG; /* convert id back to base cell indexes */
2758 G <<= BOX_G_LOG;
2759 B <<= BOX_B_LOG;
2760 cptr = bestcolor;
2761 for (iR = 0; iR < BOX_R_ELEMS; iR++)
2762 {
2763 for (iG = 0; iG < BOX_G_ELEMS; iG++)
2764 {
2765 for (iB = 0; iB < BOX_B_ELEMS; iB++)
2766 {
2767 *HIST_LIN (histogram, R + iR, G + iG, B + iB) = (*cptr++) + 1;
2768 }
2769 }
2770 }
2771 }
2772
2773
2774 /* This is pass 1 */
2775
2776 static void
median_cut_pass1_gray(QuantizeObj * quantobj)2777 median_cut_pass1_gray (QuantizeObj *quantobj)
2778 {
2779 select_colors_gray (quantobj, quantobj->histogram);
2780 }
2781
2782 static void
snap_to_black_and_white(QuantizeObj * quantobj)2783 snap_to_black_and_white (QuantizeObj *quantobj)
2784 {
2785 /* find whitest and blackest colors in palette, if they are closer
2786 * than 24 units of euclidian distance in sRGB snap them to pure
2787 * black / white.
2788 */
2789 #define POW2(a) ((a)*(a))
2790 gint desired = quantobj->desired_number_of_colors;
2791 gint whitest = 0;
2792 gint blackest = 0;
2793
2794 gint64 white_dist = POW2(255) * 3;
2795 gint64 black_dist = POW2(255) * 3;
2796 gint i;
2797
2798 for (i = 0; i < desired; i ++)
2799 {
2800 int dist;
2801
2802 dist = POW2 (quantobj->cmap[i].red - 255) +
2803 POW2 (quantobj->cmap[i].green - 255) +
2804 POW2( quantobj->cmap[i].blue - 255);
2805 if (dist < white_dist)
2806 {
2807 white_dist = dist;
2808 whitest = i;
2809 }
2810
2811 dist = POW2(quantobj->cmap[i].red - 0) +
2812 POW2(quantobj->cmap[i].green - 0) +
2813 POW2(quantobj->cmap[i].blue - 0);
2814 if (dist < black_dist)
2815 {
2816 black_dist = dist;
2817 blackest = i;
2818 }
2819 }
2820
2821 if (desired > 2 &&
2822 had_white &&
2823 white_dist < POW2(128))
2824 {
2825 quantobj->cmap[whitest].red =
2826 quantobj->cmap[whitest].green =
2827 quantobj->cmap[whitest].blue = 255;
2828 }
2829 if (desired > 2 &&
2830 had_black &&
2831 black_dist < POW2(128))
2832 {
2833 quantobj->cmap[blackest].red =
2834 quantobj->cmap[blackest].green =
2835 quantobj->cmap[blackest].blue = 0;
2836 }
2837 #undef POW2
2838 }
2839
2840 static void
median_cut_pass1_rgb(QuantizeObj * quantobj)2841 median_cut_pass1_rgb (QuantizeObj *quantobj)
2842 {
2843 select_colors_rgb (quantobj, quantobj->histogram);
2844 snap_to_black_and_white (quantobj);
2845 }
2846
2847
2848 static void
monopal_pass1(QuantizeObj * quantobj)2849 monopal_pass1 (QuantizeObj *quantobj)
2850 {
2851 quantobj->actual_number_of_colors = 2;
2852
2853 quantobj->cmap[0].red = 0;
2854 quantobj->cmap[0].green = 0;
2855 quantobj->cmap[0].blue = 0;
2856 quantobj->cmap[1].red = 255;
2857 quantobj->cmap[1].green = 255;
2858 quantobj->cmap[1].blue = 255;
2859 }
2860
2861 static void
webpal_pass1(QuantizeObj * quantobj)2862 webpal_pass1 (QuantizeObj *quantobj)
2863 {
2864 int i;
2865
2866 quantobj->actual_number_of_colors = 216;
2867
2868 for (i=0; i < 216; i++)
2869 {
2870 quantobj->cmap[i].red = webpal[i * 3];
2871 quantobj->cmap[i].green = webpal[i * 3 +1];
2872 quantobj->cmap[i].blue = webpal[i * 3 +2];
2873 }
2874 }
2875
2876 static void
custompal_pass1(QuantizeObj * quantobj)2877 custompal_pass1 (QuantizeObj *quantobj)
2878 {
2879 gint i;
2880 GList *list;
2881
2882 /* fprintf(stderr,
2883 "custompal_pass1: using (theCustomPalette %s) from (file %s)\n",
2884 theCustomPalette->name, theCustomPalette->filename); */
2885
2886 for (i = 0, list = gimp_palette_get_colors (quantobj->custom_palette);
2887 list;
2888 i++, list = g_list_next (list))
2889 {
2890 GimpPaletteEntry *entry = list->data;
2891 guchar r, g, b;
2892
2893 gimp_rgb_get_uchar (&entry->color, &r, &g, &b);
2894
2895 quantobj->cmap[i].red = (gint) r;
2896 quantobj->cmap[i].green = (gint) g;
2897 quantobj->cmap[i].blue = (gint) b;
2898 }
2899
2900 quantobj -> actual_number_of_colors = i;
2901 }
2902
2903 /*
2904 * Map some rows of pixels to the output colormapped representation.
2905 */
2906
2907 static void
median_cut_pass2_no_dither_gray(QuantizeObj * quantobj,GimpLayer * layer,GeglBuffer * new_buffer)2908 median_cut_pass2_no_dither_gray (QuantizeObj *quantobj,
2909 GimpLayer *layer,
2910 GeglBuffer *new_buffer)
2911 {
2912 GeglBufferIterator *iter;
2913 CFHistogram histogram = quantobj->histogram;
2914 ColorFreq *cachep;
2915 const Babl *src_format;
2916 const Babl *dest_format;
2917 GeglRectangle *src_roi;
2918 gint src_bpp;
2919 gint dest_bpp;
2920 gint has_alpha;
2921 guint64 *index_used_count = quantobj->index_used_count;
2922 gboolean dither_alpha = quantobj->want_dither_alpha;
2923 gint offsetx, offsety;
2924
2925 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
2926
2927 src_format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
2928 dest_format = gegl_buffer_get_format (new_buffer);
2929
2930 src_bpp = babl_format_get_bytes_per_pixel (src_format);
2931 dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
2932
2933 has_alpha = babl_format_has_alpha (src_format);
2934
2935 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
2936 NULL, 0, NULL,
2937 GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 2);
2938 src_roi = &iter->items[0].roi;
2939
2940 gegl_buffer_iterator_add (iter, new_buffer,
2941 NULL, 0, NULL,
2942 GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
2943
2944 while (gegl_buffer_iterator_next (iter))
2945 {
2946 const guchar *src = iter->items[0].data;
2947 guchar *dest = iter->items[1].data;
2948 gint row;
2949
2950 for (row = 0; row < src_roi->height; row++)
2951 {
2952 gint col;
2953
2954 for (col = 0; col < src_roi->width; col++)
2955 {
2956 /* get pixel value and index into the cache */
2957 gint pixel = src[GRAY];
2958
2959 cachep = &histogram[pixel];
2960 /* If we have not seen this color before, find nearest
2961 * colormap entry and update the cache
2962 */
2963 if (*cachep == 0)
2964 fill_inverse_cmap_gray (quantobj, histogram, pixel);
2965
2966 if (has_alpha)
2967 {
2968 gboolean transparent = FALSE;
2969
2970 if (dither_alpha)
2971 {
2972 gint dither_x = (col + offsetx + src_roi->x) & DM_WIDTHMASK;
2973 gint dither_y = (row + offsety + src_roi->y) & DM_HEIGHTMASK;
2974
2975 if ((src[ALPHA_G]) < DM[dither_x][dither_y])
2976 transparent = TRUE;
2977 }
2978 else
2979 {
2980 if (src[ALPHA_G] <= 127)
2981 transparent = TRUE;
2982 }
2983
2984 if (transparent)
2985 {
2986 dest[ALPHA_I] = 0;
2987 }
2988 else
2989 {
2990 dest[ALPHA_I] = 255;
2991 index_used_count[dest[INDEXED] = *cachep - 1]++;
2992 }
2993 }
2994 else
2995 {
2996 /* Now emit the colormap index for this cell */
2997 index_used_count[dest[INDEXED] = *cachep - 1]++;
2998 }
2999
3000 src += src_bpp;
3001 dest += dest_bpp;
3002 }
3003 }
3004 }
3005 }
3006
3007 static void
median_cut_pass2_fixed_dither_gray(QuantizeObj * quantobj,GimpLayer * layer,GeglBuffer * new_buffer)3008 median_cut_pass2_fixed_dither_gray (QuantizeObj *quantobj,
3009 GimpLayer *layer,
3010 GeglBuffer *new_buffer)
3011 {
3012 GeglBufferIterator *iter;
3013 CFHistogram histogram = quantobj->histogram;
3014 ColorFreq *cachep;
3015 const Babl *src_format;
3016 const Babl *dest_format;
3017 GeglRectangle *src_roi;
3018 gint src_bpp;
3019 gint dest_bpp;
3020 gboolean has_alpha;
3021 gint pixval1 = 0;
3022 gint pixval2 = 0;
3023 gint err1;
3024 gint err2;
3025 Color *color1;
3026 Color *color2;
3027 guint64 *index_used_count = quantobj->index_used_count;
3028 gboolean dither_alpha = quantobj->want_dither_alpha;
3029 gint offsetx, offsety;
3030
3031 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
3032
3033 src_format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
3034 dest_format = gegl_buffer_get_format (new_buffer);
3035
3036 src_bpp = babl_format_get_bytes_per_pixel (src_format);
3037 dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
3038
3039 has_alpha = babl_format_has_alpha (src_format);
3040
3041 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
3042 NULL, 0, NULL,
3043 GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 2);
3044 src_roi = &iter->items[0].roi;
3045
3046 gegl_buffer_iterator_add (iter, new_buffer,
3047 NULL, 0, NULL,
3048 GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
3049
3050 while (gegl_buffer_iterator_next (iter))
3051 {
3052 const guchar *src = iter->items[0].data;
3053 guchar *dest = iter->items[1].data;
3054 gint row;
3055
3056 for (row = 0; row < src_roi->height; row++)
3057 {
3058 gint col;
3059
3060 for (col = 0; col < src_roi->width; col++)
3061 {
3062 gint pixel;
3063 const gint dmval =
3064 DM[(col + offsetx + src_roi->x) & DM_WIDTHMASK]
3065 [(row + offsety + src_roi->y) & DM_HEIGHTMASK];
3066
3067 /* get pixel value and index into the cache */
3068 pixel = src[GRAY];
3069
3070 cachep = &histogram[pixel];
3071 /* If we have not seen this color before, find nearest
3072 * colormap entry and update the cache
3073 */
3074 if (*cachep == 0)
3075 fill_inverse_cmap_gray (quantobj, histogram, pixel);
3076
3077 pixval1 = *cachep - 1;
3078 color1 = &quantobj->cmap[pixval1];
3079
3080 if (quantobj->actual_number_of_colors > 2)
3081 {
3082 const int re = src[GRAY] - (int)color1->red;
3083 int RV = src[GRAY] + re;
3084
3085 do
3086 {
3087 const gint R = CLAMP0255 (RV);
3088
3089 cachep = &histogram[R];
3090 /* If we have not seen this color before, find
3091 * nearest colormap entry and update the cache
3092 */
3093 if (*cachep == 0)
3094 fill_inverse_cmap_gray (quantobj, histogram, R);
3095
3096 pixval2 = *cachep - 1;
3097 RV += re;
3098 }
3099 while ((pixval1 == pixval2) &&
3100 (! (RV>255 || RV<0) ) &&
3101 re);
3102 }
3103 else
3104 {
3105 /* not enough colors to bother looking for an 'alternative'
3106 color (we may fail to do so anyway), so decide that
3107 the alternative color is simply the other cmap entry. */
3108 pixval2 = (pixval1 + 1) %
3109 (quantobj->actual_number_of_colors);
3110 }
3111
3112 /* always deterministically sort pixval1 and pixval2, to
3113 avoid artifacts in the dither range due to inverting our
3114 relative color viewpoint -- most obvious in 1-bit dither. */
3115 if (pixval1 > pixval2)
3116 {
3117 gint tmpval = pixval1;
3118 pixval1 = pixval2;
3119 pixval2 = tmpval;
3120 color1 = &quantobj->cmap[pixval1];
3121 }
3122
3123 color2 = &quantobj->cmap[pixval2];
3124
3125 err1 = ABS(color1->red - src[GRAY]);
3126 err2 = ABS(color2->red - src[GRAY]);
3127 if (err1 || err2)
3128 {
3129 const int proportion2 = (256 * 255 * err2) / (err1 + err2);
3130
3131 if ((dmval * 256) > proportion2)
3132 {
3133 pixval1 = pixval2; /* use color2 instead of color1*/
3134 }
3135 }
3136
3137 if (has_alpha)
3138 {
3139 gboolean transparent = FALSE;
3140
3141 if (dither_alpha)
3142 {
3143 if (src[ALPHA_G] < dmval)
3144 transparent = TRUE;
3145 }
3146 else
3147 {
3148 if (src[ALPHA_G] <= 127)
3149 transparent = TRUE;
3150 }
3151
3152 if (transparent)
3153 {
3154 dest[ALPHA_I] = 0;
3155 }
3156 else
3157 {
3158 dest[ALPHA_I] = 255;
3159 index_used_count[dest[INDEXED] = pixval1]++;
3160 }
3161 }
3162 else
3163 {
3164 /* Now emit the colormap index for this cell, barfbarf */
3165 index_used_count[dest[INDEXED] = pixval1]++;
3166 }
3167
3168 src += src_bpp;
3169 dest += dest_bpp;
3170 }
3171 }
3172 }
3173 }
3174
3175 static void
median_cut_pass2_no_dither_rgb(QuantizeObj * quantobj,GimpLayer * layer,GeglBuffer * new_buffer)3176 median_cut_pass2_no_dither_rgb (QuantizeObj *quantobj,
3177 GimpLayer *layer,
3178 GeglBuffer *new_buffer)
3179 {
3180 GeglBufferIterator *iter;
3181 CFHistogram histogram = quantobj->histogram;
3182 ColorFreq *cachep;
3183 const Babl *src_format;
3184 const Babl *dest_format;
3185 GeglRectangle *src_roi;
3186 gint src_bpp;
3187 gint dest_bpp;
3188 gint has_alpha;
3189 gint R, G, B;
3190 gint red_pix = RED;
3191 gint green_pix = GREEN;
3192 gint blue_pix = BLUE;
3193 gint alpha_pix = ALPHA;
3194 gboolean dither_alpha = quantobj->want_dither_alpha;
3195 gint offsetx, offsety;
3196 guint64 *index_used_count = quantobj->index_used_count;
3197 gint64 total_size = 0;
3198 gint64 layer_size;
3199 gint count = 0;
3200
3201 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
3202
3203 src_format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
3204 dest_format = gegl_buffer_get_format (new_buffer);
3205
3206 src_bpp = babl_format_get_bytes_per_pixel (src_format);
3207 dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
3208
3209 has_alpha = babl_format_has_alpha (src_format);
3210
3211 /* In the case of web/mono palettes, we actually force
3212 * grayscale drawables through the rgb pass2 functions
3213 */
3214 if (gimp_drawable_is_gray (GIMP_DRAWABLE (layer)))
3215 {
3216 red_pix = green_pix = blue_pix = GRAY;
3217 alpha_pix = ALPHA_G;
3218 }
3219
3220 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
3221 NULL, 0, NULL,
3222 GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 2);
3223 src_roi = &iter->items[0].roi;
3224
3225 gegl_buffer_iterator_add (iter, new_buffer,
3226 NULL, 0, NULL,
3227 GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
3228
3229 layer_size = (gimp_item_get_width (GIMP_ITEM (layer)) *
3230 gimp_item_get_height (GIMP_ITEM (layer)));
3231
3232 while (gegl_buffer_iterator_next (iter))
3233 {
3234 const guchar *src = iter->items[0].data;
3235 guchar *dest = iter->items[1].data;
3236 gint row;
3237
3238 total_size += src_roi->height * src_roi->width;
3239
3240 for (row = 0; row < src_roi->height; row++)
3241 {
3242 gint col;
3243
3244 for (col = 0; col < src_roi->width; col++)
3245 {
3246 if (has_alpha)
3247 {
3248 gboolean transparent = FALSE;
3249
3250 if (dither_alpha)
3251 {
3252 gint dither_x = (col + offsetx + src_roi->x) & DM_WIDTHMASK;
3253 gint dither_y = (row + offsety + src_roi->y) & DM_HEIGHTMASK;
3254
3255 if ((src[alpha_pix]) < DM[dither_x][dither_y])
3256 transparent = TRUE;
3257 }
3258 else
3259 {
3260 if (src[alpha_pix] <= 127)
3261 transparent = TRUE;
3262 }
3263
3264 if (transparent)
3265 {
3266 dest[ALPHA_I] = 0;
3267 goto next_pixel;
3268 }
3269 else
3270 {
3271 dest[ALPHA_I] = 255;
3272 }
3273 }
3274
3275 /* get pixel value and index into the cache */
3276 rgb_to_lin (src[red_pix], src[green_pix], src[blue_pix],
3277 &R, &G, &B);
3278
3279 cachep = HIST_LIN (histogram, R, G, B);
3280 /* If we have not seen this color before, find nearest
3281 * colormap entry and update the cache
3282 */
3283 if (*cachep == 0)
3284 fill_inverse_cmap_rgb (quantobj, histogram, R, G, B);
3285
3286 /* Now emit the colormap index for this cell, barfbarf */
3287 index_used_count[dest[INDEXED] = *cachep - 1]++;
3288
3289 next_pixel:
3290
3291 src += src_bpp;
3292 dest += dest_bpp;
3293 }
3294 }
3295
3296 if (quantobj->progress && (count % 16 == 0))
3297 gimp_progress_set_value (quantobj->progress,
3298 (gdouble) total_size / (gdouble) layer_size);
3299 }
3300 }
3301
3302 static void
median_cut_pass2_fixed_dither_rgb(QuantizeObj * quantobj,GimpLayer * layer,GeglBuffer * new_buffer)3303 median_cut_pass2_fixed_dither_rgb (QuantizeObj *quantobj,
3304 GimpLayer *layer,
3305 GeglBuffer *new_buffer)
3306 {
3307 GeglBufferIterator *iter;
3308 CFHistogram histogram = quantobj->histogram;
3309 ColorFreq *cachep;
3310 const Babl *src_format;
3311 const Babl *dest_format;
3312 GeglRectangle *src_roi;
3313 gint src_bpp;
3314 gint dest_bpp;
3315 gint has_alpha;
3316 gint pixval1 = 0;
3317 gint pixval2 = 0;
3318 Color *color1;
3319 Color *color2;
3320 gint R, G, B;
3321 gint err1;
3322 gint err2;
3323 gint red_pix = RED;
3324 gint green_pix = GREEN;
3325 gint blue_pix = BLUE;
3326 gint alpha_pix = ALPHA;
3327 gboolean dither_alpha = quantobj->want_dither_alpha;
3328 gint offsetx, offsety;
3329 guint64 *index_used_count = quantobj->index_used_count;
3330 gint64 total_size = 0;
3331 gint64 layer_size;
3332 gint count = 0;
3333
3334 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
3335
3336 src_format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
3337 dest_format = gegl_buffer_get_format (new_buffer);
3338
3339 src_bpp = babl_format_get_bytes_per_pixel (src_format);
3340 dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
3341
3342 has_alpha = babl_format_has_alpha (src_format);
3343
3344 /* In the case of web/mono palettes, we actually force
3345 * grayscale drawables through the rgb pass2 functions
3346 */
3347 if (gimp_drawable_is_gray (GIMP_DRAWABLE (layer)))
3348 {
3349 red_pix = green_pix = blue_pix = GRAY;
3350 alpha_pix = ALPHA_G;
3351 }
3352
3353 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
3354 NULL, 0, NULL,
3355 GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 2);
3356 src_roi = &iter->items[0].roi;
3357
3358 gegl_buffer_iterator_add (iter, new_buffer,
3359 NULL, 0, NULL,
3360 GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
3361
3362 layer_size = (gimp_item_get_width (GIMP_ITEM (layer)) *
3363 gimp_item_get_height (GIMP_ITEM (layer)));
3364
3365 while (gegl_buffer_iterator_next (iter))
3366 {
3367 const guchar *src = iter->items[0].data;
3368 guchar *dest = iter->items[1].data;
3369 gint row;
3370
3371 total_size += src_roi->height * src_roi->width;
3372
3373 for (row = 0; row < src_roi->height; row++)
3374 {
3375 gint col;
3376
3377 for (col = 0; col < src_roi->width; col++)
3378 {
3379 const int dmval =
3380 DM[(col + offsetx + src_roi->x) & DM_WIDTHMASK]
3381 [(row + offsety + src_roi->y) & DM_HEIGHTMASK];
3382
3383 if (has_alpha)
3384 {
3385 gboolean transparent = FALSE;
3386
3387 if (dither_alpha)
3388 {
3389 if (src[alpha_pix] < dmval)
3390 transparent = TRUE;
3391 }
3392 else
3393 {
3394 if (src[alpha_pix] <= 127)
3395 transparent = TRUE;
3396 }
3397
3398 if (transparent)
3399 {
3400 dest[ALPHA_I] = 0;
3401 goto next_pixel;
3402 }
3403 else
3404 {
3405 dest[ALPHA_I] = 255;
3406 }
3407 }
3408
3409 /* get pixel value and index into the cache */
3410 rgb_to_lin (src[red_pix], src[green_pix], src[blue_pix],
3411 &R, &G, &B);
3412
3413 cachep = HIST_LIN (histogram, R, G, B);
3414 /* If we have not seen this color before, find nearest
3415 * colormap entry and update the cache
3416 */
3417 if (*cachep == 0)
3418 fill_inverse_cmap_rgb (quantobj, histogram, R, G, B);
3419
3420 /* We now try to find a color which, when mixed in some
3421 * fashion with the closest match, yields something
3422 * closer to the desired color. We do this by
3423 * repeatedly extrapolating the color vector from one to
3424 * the other until we find another color cell. Then we
3425 * assess the distance of both mixer colors from the
3426 * intended color to determine their relative
3427 * probabilities of being chosen.
3428 */
3429 pixval1 = *cachep - 1;
3430 color1 = &quantobj->cmap[pixval1];
3431
3432 if (quantobj->actual_number_of_colors > 2)
3433 {
3434 const gint re = src[red_pix] - (gint) color1->red;
3435 const gint ge = src[green_pix] - (gint) color1->green;
3436 const gint be = src[blue_pix] - (gint) color1->blue;
3437 gint RV = src[red_pix] + re;
3438 gint GV = src[green_pix] + ge;
3439 gint BV = src[blue_pix] + be;
3440
3441 do
3442 {
3443 rgb_to_lin ((CLAMP0255(RV)),
3444 (CLAMP0255(GV)),
3445 (CLAMP0255(BV)),
3446 &R, &G, &B);
3447
3448 cachep = HIST_LIN (histogram, R, G, B);
3449 /* If we have not seen this color before, find
3450 * nearest colormap entry and update the cache
3451 */
3452 if (*cachep == 0)
3453 fill_inverse_cmap_rgb (quantobj, histogram, R, G, B);
3454
3455 pixval2 = *cachep - 1;
3456 RV += re; GV += ge; BV += be;
3457 }
3458 while ((pixval1 == pixval2) &&
3459 (!( (RV>255 || RV<0) || (GV>255 || GV<0) || (BV>255 || BV<0) )) &&
3460 (re || ge || be));
3461 }
3462
3463 if (quantobj->actual_number_of_colors <= 2
3464 /* || pixval1 == pixval2 */) {
3465 /* not enough colors to bother looking for an 'alternative'
3466 color (we may fail to do so anyway), so decide that
3467 the alternative color is simply the other cmap entry. */
3468 pixval2 = (pixval1 + 1) %
3469 (quantobj->actual_number_of_colors);
3470 }
3471
3472 /* always deterministically sort pixval1 and pixval2, to
3473 avoid artifacts in the dither range due to inverting our
3474 relative color viewpoint -- most obvious in 1-bit dither. */
3475 if (pixval1 > pixval2)
3476 {
3477 gint tmpval = pixval1;
3478 pixval1 = pixval2;
3479 pixval2 = tmpval;
3480 color1 = &quantobj->cmap[pixval1];
3481 }
3482
3483 color2 = &quantobj->cmap[pixval2];
3484
3485 /* now figure out the relative probabilites of choosing
3486 either of our candidates. */
3487 #define DISTP(R1,G1,B1,R2,G2,B2,D) do {D = sqrt( 30*SQR((R1)-(R2)) + \
3488 59*SQR((G1)-(G2)) + \
3489 11*SQR((B1)-(B2)) ); }while(0)
3490 #define LIN_DISTP(R1,G1,B1,R2,G2,B2,D) do { \
3491 int spacer1, spaceg1, spaceb1; \
3492 int spacer2, spaceg2, spaceb2; \
3493 rgb_to_unshifted_lin (R1,G1,B1, &spacer1, &spaceg1, &spaceb1); \
3494 rgb_to_unshifted_lin (R2,G2,B2, &spacer2, &spaceg2, &spaceb2); \
3495 D = sqrt(R_SCALE * SQR((spacer1)-(spacer2)) + \
3496 G_SCALE * SQR((spaceg1)-(spaceg2)) + \
3497 B_SCALE * SQR((spaceb1)-(spaceb2))); \
3498 } while(0)
3499
3500 /* although LIN_DISTP is more correct, DISTP is much faster and
3501 barely distinguishable. */
3502 DISTP (color1->red, color1->green, color1->blue,
3503 src[red_pix], src[green_pix], src[blue_pix],
3504 err1);
3505 DISTP (color2->red, color2->green, color2->blue,
3506 src[red_pix], src[green_pix], src[blue_pix],
3507 err2);
3508
3509 if (err1 || err2)
3510 {
3511 const int proportion2 = (255 * err2) / (err1 + err2);
3512 if (dmval > proportion2)
3513 {
3514 pixval1 = pixval2; /* use color2 instead of color1*/
3515 }
3516 }
3517
3518 /* Now emit the colormap index for this cell, barfbarf */
3519 index_used_count[dest[INDEXED] = pixval1]++;
3520
3521 next_pixel:
3522
3523 src += src_bpp;
3524 dest += dest_bpp;
3525 }
3526 }
3527
3528 if (quantobj->progress && (count % 16 == 0))
3529 gimp_progress_set_value (quantobj->progress,
3530 (gdouble) total_size / (gdouble) layer_size);
3531 }
3532 }
3533
3534 static void
median_cut_pass2_nodestruct_dither_rgb(QuantizeObj * quantobj,GimpLayer * layer,GeglBuffer * new_buffer)3535 median_cut_pass2_nodestruct_dither_rgb (QuantizeObj *quantobj,
3536 GimpLayer *layer,
3537 GeglBuffer *new_buffer)
3538 {
3539 GeglBufferIterator *iter;
3540 const Babl *src_format;
3541 const Babl *dest_format;
3542 GeglRectangle *src_roi;
3543 gint src_bpp;
3544 gint dest_bpp;
3545 gint has_alpha;
3546 gboolean dither_alpha = quantobj->want_dither_alpha;
3547 gint red_pix = RED;
3548 gint green_pix = GREEN;
3549 gint blue_pix = BLUE;
3550 gint alpha_pix = ALPHA;
3551 gint lastindex = 0;
3552 gint lastred = -1;
3553 gint lastgreen = -1;
3554 gint lastblue = -1;
3555 gint offsetx, offsety;
3556
3557 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
3558
3559 src_format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
3560 dest_format = gegl_buffer_get_format (new_buffer);
3561
3562 src_bpp = babl_format_get_bytes_per_pixel (src_format);
3563 dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
3564
3565 has_alpha = babl_format_has_alpha (src_format);
3566
3567 iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
3568 NULL, 0, NULL,
3569 GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 2);
3570 src_roi = &iter->items[0].roi;
3571
3572 gegl_buffer_iterator_add (iter, new_buffer,
3573 NULL, 0, NULL,
3574 GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
3575
3576 while (gegl_buffer_iterator_next (iter))
3577 {
3578 const guchar *src = iter->items[0].data;
3579 guchar *dest = iter->items[1].data;
3580 gint row;
3581
3582 for (row = 0; row < src_roi->height; row++)
3583 {
3584 gint col;
3585
3586 for (col = 0; col < src_roi->width; col++)
3587 {
3588 gboolean transparent = FALSE;
3589
3590 if (has_alpha)
3591 {
3592 if (dither_alpha)
3593 {
3594 gint dither_x = (col + src_roi->x + offsetx) & DM_WIDTHMASK;
3595 gint dither_y = (row + src_roi->y + offsety) & DM_HEIGHTMASK;
3596
3597 if ((src[alpha_pix]) < DM[dither_x][dither_y])
3598 transparent = TRUE;
3599 }
3600 else
3601 {
3602 if (src[alpha_pix] < 128)
3603 transparent = TRUE;
3604 }
3605 }
3606
3607 if (! transparent)
3608 {
3609 if ((lastred == src[red_pix]) &&
3610 (lastgreen == src[green_pix]) &&
3611 (lastblue == src[blue_pix]))
3612 {
3613 /* same pixel color as last time */
3614 dest[INDEXED] = lastindex;
3615 if (has_alpha)
3616 dest[ALPHA_I] = 255;
3617 }
3618 else
3619 {
3620 gint i;
3621
3622 for (i = 0 ;
3623 i < quantobj->actual_number_of_colors;
3624 i++)
3625 {
3626 if ((quantobj->cmap[i].green == src[green_pix]) &&
3627 (quantobj->cmap[i].red == src[red_pix]) &&
3628 (quantobj->cmap[i].blue == src[blue_pix]))
3629 {
3630 lastred = src[red_pix];
3631 lastgreen = src[green_pix];
3632 lastblue = src[blue_pix];
3633 lastindex = i;
3634
3635 goto got_color;
3636 }
3637 }
3638 g_error ("Non-existant color was expected to "
3639 "be in non-destructive colormap.");
3640 got_color:
3641 dest[INDEXED] = lastindex;
3642 if (has_alpha)
3643 dest[ALPHA_I] = 255;
3644 }
3645 }
3646 else
3647 { /* have alpha, and transparent */
3648 dest[ALPHA_I] = 0;
3649 }
3650
3651 src += src_bpp;
3652 dest += dest_bpp;
3653 }
3654 }
3655 }
3656 }
3657
3658
3659 /*
3660 * Initialize the error-limiting transfer function (lookup table).
3661 * The raw F-S error computation can potentially compute error values of up to
3662 * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be
3663 * much less, otherwise obviously wrong pixels will be created. (Typical
3664 * effects include weird fringes at color-area boundaries, isolated bright
3665 * pixels in a dark area, etc.) The standard advice for avoiding this problem
3666 * is to ensure that the "corners" of the color cube are allocated as output
3667 * colors; then repeated errors in the same direction cannot cause cascading
3668 * error buildup. However, that only prevents the error from getting
3669 * completely out of hand; Aaron Giles reports that error limiting improves
3670 * the results even with corner colors allocated.
3671 * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
3672 * well, but the smoother transfer function used below is even better. Thanks
3673 * to Aaron Giles for this idea.
3674 */
3675
3676 static gint *
init_error_limit(const int error_freedom)3677 init_error_limit (const int error_freedom)
3678 /* Allocate and fill in the error_limiter table */
3679 {
3680 gint *table;
3681 gint inp, out;
3682
3683 /* #define STEPSIZE 16 */
3684 /* #define STEPSIZE 200 */
3685
3686 table = g_new (gint, 255 * 2 + 1);
3687 table += 255; /* so we can index -255 ... +255 */
3688
3689 if (error_freedom == 0)
3690 {
3691 /* Coarse function, much bleeding. */
3692
3693 const gint STEPSIZE = 190;
3694
3695 for (inp = 0; inp < STEPSIZE; inp++)
3696 {
3697 table[inp] = inp;
3698 table[-inp] = -inp;
3699 }
3700
3701 for (; inp <= 255; inp++)
3702 {
3703 table[inp] = STEPSIZE;
3704 table[-inp] = -STEPSIZE;
3705 }
3706
3707 return (table);
3708 }
3709 else
3710 {
3711 /* Smooth function, bleeding more constrained */
3712
3713 const gint STEPSIZE = 24;
3714
3715 /* Map errors 1:1 up to +- STEPSIZE */
3716 out = 0;
3717 for (inp = 0; inp < STEPSIZE; inp++, out++)
3718 {
3719 table[inp] = out;
3720 table[-inp] = -out;
3721 }
3722
3723 /* Map errors 1:2 up to +- 3*STEPSIZE */
3724 for (; inp < STEPSIZE*3; inp++, out += (inp&1) ? 0 : 1)
3725 {
3726 table[inp] = out;
3727 table[-inp] = -out;
3728 }
3729
3730 /* Clamp the rest to final out value (which is STEPSIZE*2) */
3731 for (; inp <= 255; inp++)
3732 {
3733 table[inp] = out;
3734 table[-inp] = -out;
3735 }
3736
3737 return table;
3738 }
3739 }
3740
3741
3742 /*
3743 * Map some rows of pixels to the output colormapped representation.
3744 * Perform floyd-steinberg dithering.
3745 */
3746
3747 static void
median_cut_pass2_fs_dither_gray(QuantizeObj * quantobj,GimpLayer * layer,GeglBuffer * new_buffer)3748 median_cut_pass2_fs_dither_gray (QuantizeObj *quantobj,
3749 GimpLayer *layer,
3750 GeglBuffer *new_buffer)
3751 {
3752 GeglBuffer *src_buffer;
3753 CFHistogram histogram = quantobj->histogram;
3754 ColorFreq *cachep;
3755 Color *color;
3756 gint *error_limiter;
3757 const gshort *fs_err1, *fs_err2;
3758 const gshort *fs_err3, *fs_err4;
3759 const guchar *range_limiter;
3760 const Babl *src_format;
3761 const Babl *dest_format;
3762 gint src_bpp;
3763 gint dest_bpp;
3764 guchar *src_buf, *dest_buf;
3765 gint *next_row, *prev_row;
3766 gint *nr, *pr;
3767 gint *tmp;
3768 gint pixel;
3769 gint pixele;
3770 gint row, col;
3771 gint index;
3772 gint step_dest, step_src;
3773 gint odd_row;
3774 gboolean has_alpha;
3775 gint offsetx, offsety;
3776 gboolean dither_alpha = quantobj->want_dither_alpha;
3777 gint width, height;
3778 guint64 *index_used_count = quantobj->index_used_count;
3779
3780 src_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
3781
3782 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
3783
3784 src_format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
3785 dest_format = gegl_buffer_get_format (new_buffer);
3786
3787 src_bpp = babl_format_get_bytes_per_pixel (src_format);
3788 dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
3789
3790 has_alpha = babl_format_has_alpha (src_format);
3791
3792 width = gimp_item_get_width (GIMP_ITEM (layer));
3793 height = gimp_item_get_height (GIMP_ITEM (layer));
3794
3795 error_limiter = init_error_limit (quantobj->error_freedom);
3796 range_limiter = range_array + 256;
3797
3798 src_buf = g_malloc (width * src_bpp);
3799 dest_buf = g_malloc (width * dest_bpp);
3800
3801 next_row = g_new (gint, width + 2);
3802 prev_row = g_new0 (gint, width + 2);
3803
3804 fs_err1 = floyd_steinberg_error1 + 511;
3805 fs_err2 = floyd_steinberg_error2 + 511;
3806 fs_err3 = floyd_steinberg_error3 + 511;
3807 fs_err4 = floyd_steinberg_error4 + 511;
3808
3809 odd_row = 0;
3810
3811 for (row = 0; row < height; row++)
3812 {
3813 const guchar *src;
3814 guchar *dest;
3815
3816 gegl_buffer_get (src_buffer, GEGL_RECTANGLE (0, row, width, 1),
3817 1.0, NULL, src_buf,
3818 GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
3819
3820 src = src_buf;
3821 dest = dest_buf;
3822
3823 nr = next_row;
3824 pr = prev_row + 1;
3825
3826 if (odd_row)
3827 {
3828 step_dest = -dest_bpp;
3829 step_src = -src_bpp;
3830
3831 src += (width * src_bpp) - src_bpp;
3832 dest += (width * dest_bpp) - dest_bpp;
3833
3834 nr += width + 1;
3835 pr += width;
3836
3837 *(nr - 1) = 0;
3838 }
3839 else
3840 {
3841 step_dest = dest_bpp;
3842 step_src = src_bpp;
3843
3844 *(nr + 1) = 0;
3845 }
3846
3847 *nr = 0;
3848
3849 for (col = 0; col < width; col++)
3850 {
3851 pixel = range_limiter[src[GRAY] + error_limiter[*pr]];
3852
3853 cachep = &histogram[pixel];
3854 /* If we have not seen this color before, find nearest
3855 * colormap entry and update the cache
3856 */
3857 if (*cachep == 0)
3858 fill_inverse_cmap_gray (quantobj, histogram, pixel);
3859
3860 if (has_alpha)
3861 {
3862 gboolean transparent = FALSE;
3863
3864 if (odd_row)
3865 {
3866 if (dither_alpha)
3867 {
3868 gint dither_x = ((width-col)+offsetx-1) & DM_WIDTHMASK;
3869 gint dither_y = (row+offsety) & DM_HEIGHTMASK;
3870
3871 if ((src[ALPHA_G]) < DM[dither_x][dither_y])
3872 transparent = TRUE;
3873 }
3874 else
3875 {
3876 if (src[ALPHA_G] <= 127)
3877 transparent = TRUE;
3878 }
3879
3880 if (transparent)
3881 {
3882 dest[ALPHA_I] = 0;
3883 pr--;
3884 nr--;
3885 *(nr - 1) = 0;
3886 goto next_pixel;
3887 }
3888 else
3889 {
3890 dest[ALPHA_I] = 255;
3891 }
3892 }
3893 else
3894 {
3895 if (dither_alpha)
3896 {
3897 gint dither_x = (col + offsetx) & DM_WIDTHMASK;
3898 gint dither_y = (row + offsety) & DM_HEIGHTMASK;
3899
3900 if ((src[ALPHA_G]) < DM[dither_x][dither_y])
3901 transparent = TRUE;
3902 }
3903 else
3904 {
3905 if (src[ALPHA_G] <= 127)
3906 transparent = TRUE;
3907 }
3908
3909 if (transparent)
3910 {
3911 dest[ALPHA_I] = 0;
3912 pr++;
3913 nr++;
3914 *(nr + 1) = 0;
3915 goto next_pixel;
3916 }
3917 else
3918 {
3919 dest[ALPHA_I] = 255;
3920 }
3921 }
3922 }
3923
3924 index = *cachep - 1;
3925 index_used_count[dest[INDEXED] = index]++;
3926
3927 color = &quantobj->cmap[index];
3928 pixele = pixel - color->red;
3929
3930 if (odd_row)
3931 {
3932 *(--pr) += fs_err1[pixele];
3933 *nr-- += fs_err2[pixele];
3934 *nr += fs_err3[pixele];
3935 *(nr-1) = fs_err4[pixele];
3936 }
3937 else
3938 {
3939 *(++pr) += fs_err1[pixele];
3940 *nr++ += fs_err2[pixele];
3941 *nr += fs_err3[pixele];
3942 *(nr+1) = fs_err4[pixele];
3943 }
3944
3945 next_pixel:
3946
3947 dest += step_dest;
3948 src += step_src;
3949 }
3950
3951 tmp = next_row;
3952 next_row = prev_row;
3953 prev_row = tmp;
3954
3955 odd_row = !odd_row;
3956
3957 gegl_buffer_set (new_buffer, GEGL_RECTANGLE (0, row, width, 1),
3958 0, NULL, dest_buf,
3959 GEGL_AUTO_ROWSTRIDE);
3960 }
3961
3962 g_free (error_limiter - 255); /* good lord. */
3963 g_free (next_row);
3964 g_free (prev_row);
3965 g_free (src_buf);
3966 g_free (dest_buf);
3967 }
3968
3969 static void
median_cut_pass2_rgb_init(QuantizeObj * quantobj)3970 median_cut_pass2_rgb_init (QuantizeObj *quantobj)
3971 {
3972 int i;
3973
3974 zero_histogram_rgb (quantobj->histogram);
3975
3976 /* Mark all indices as currently unused */
3977 memset (quantobj->index_used_count, 0, 256 * sizeof (guint64));
3978
3979 /* Make a version of our discovered colormap in linear space */
3980 for (i = 0; i < quantobj->actual_number_of_colors; i++)
3981 {
3982 rgb_to_unshifted_lin (quantobj->cmap[i].red,
3983 quantobj->cmap[i].green,
3984 quantobj->cmap[i].blue,
3985 &quantobj->clin[i].red,
3986 &quantobj->clin[i].green,
3987 &quantobj->clin[i].blue);
3988 }
3989 }
3990
3991 static void
median_cut_pass2_gray_init(QuantizeObj * quantobj)3992 median_cut_pass2_gray_init (QuantizeObj *quantobj)
3993 {
3994 zero_histogram_gray (quantobj->histogram);
3995
3996 /* Mark all indices as currently unused */
3997 memset (quantobj->index_used_count, 0, 256 * sizeof (guint64));
3998 }
3999
4000 static void
median_cut_pass2_fs_dither_rgb(QuantizeObj * quantobj,GimpLayer * layer,GeglBuffer * new_buffer)4001 median_cut_pass2_fs_dither_rgb (QuantizeObj *quantobj,
4002 GimpLayer *layer,
4003 GeglBuffer *new_buffer)
4004 {
4005 GeglBuffer *src_buffer;
4006 CFHistogram histogram = quantobj->histogram;
4007 ColorFreq *cachep;
4008 Color *color;
4009 gint *error_limiter;
4010 const gshort *fs_err1, *fs_err2;
4011 const gshort *fs_err3, *fs_err4;
4012 const guchar *range_limiter;
4013 const Babl *src_format;
4014 const Babl *dest_format;
4015 gint src_bpp;
4016 gint dest_bpp;
4017 guchar *src_buf, *dest_buf;
4018 gint *red_n_row, *red_p_row;
4019 gint *grn_n_row, *grn_p_row;
4020 gint *blu_n_row, *blu_p_row;
4021 gint *rnr, *rpr;
4022 gint *gnr, *gpr;
4023 gint *bnr, *bpr;
4024 gint *tmp;
4025 gint re, ge, be;
4026 gint row, col;
4027 gint index;
4028 gint step_dest, step_src;
4029 gint odd_row;
4030 gboolean has_alpha;
4031 gint width, height;
4032 gint red_pix = RED;
4033 gint green_pix = GREEN;
4034 gint blue_pix = BLUE;
4035 gint alpha_pix = ALPHA;
4036 gint offsetx, offsety;
4037 gboolean dither_alpha = quantobj->want_dither_alpha;
4038 guint64 *index_used_count = quantobj->index_used_count;
4039 gint global_rmax = 0, global_rmin = G_MAXINT;
4040 gint global_gmax = 0, global_gmin = G_MAXINT;
4041 gint global_bmax = 0, global_bmin = G_MAXINT;
4042
4043 src_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
4044
4045 gimp_item_get_offset (GIMP_ITEM (layer), &offsetx, &offsety);
4046
4047 /* In the case of web/mono palettes, we actually force
4048 * grayscale drawables through the rgb pass2 functions
4049 */
4050 if (gimp_drawable_is_gray (GIMP_DRAWABLE (layer)))
4051 red_pix = green_pix = blue_pix = GRAY;
4052
4053 src_format = gimp_drawable_get_format (GIMP_DRAWABLE (layer));
4054 dest_format = gegl_buffer_get_format (new_buffer);
4055
4056 src_bpp = babl_format_get_bytes_per_pixel (src_format);
4057 dest_bpp = babl_format_get_bytes_per_pixel (dest_format);
4058
4059 has_alpha = babl_format_has_alpha (src_format);
4060
4061 width = gimp_item_get_width (GIMP_ITEM (layer));
4062 height = gimp_item_get_height (GIMP_ITEM (layer));
4063
4064 error_limiter = init_error_limit (quantobj->error_freedom);
4065 range_limiter = range_array + 256;
4066
4067 /* find the bounding box of the palette colors --
4068 we use this for hard-clamping our error-corrected
4069 values so that we can't continuously accelerate outside
4070 of our attainable gamut, which looks icky. */
4071 for (index = 0; index < quantobj->actual_number_of_colors; index++)
4072 {
4073 global_rmax = MAX(global_rmax, quantobj->clin[index].red);
4074 global_rmin = MIN(global_rmin, quantobj->clin[index].red);
4075 global_gmax = MAX(global_gmax, quantobj->clin[index].green);
4076 global_gmin = MIN(global_gmin, quantobj->clin[index].green);
4077 global_bmax = MAX(global_bmax, quantobj->clin[index].blue);
4078 global_bmin = MIN(global_bmin, quantobj->clin[index].blue);
4079 }
4080
4081 src_buf = g_malloc (width * src_bpp);
4082 dest_buf = g_malloc (width * dest_bpp);
4083
4084 red_n_row = g_new (gint, width + 2);
4085 red_p_row = g_new0 (gint, width + 2);
4086 grn_n_row = g_new (gint, width + 2);
4087 grn_p_row = g_new0 (gint, width + 2);
4088 blu_n_row = g_new (gint, width + 2);
4089 blu_p_row = g_new0 (gint, width + 2);
4090
4091 fs_err1 = floyd_steinberg_error1 + 511;
4092 fs_err2 = floyd_steinberg_error2 + 511;
4093 fs_err3 = floyd_steinberg_error3 + 511;
4094 fs_err4 = floyd_steinberg_error4 + 511;
4095
4096 odd_row = 0;
4097
4098 for (row = 0; row < height; row++)
4099 {
4100 const guchar *src;
4101 guchar *dest;
4102
4103 gegl_buffer_get (src_buffer, GEGL_RECTANGLE (0, row, width, 1),
4104 1.0, NULL, src_buf,
4105 GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
4106
4107 src = src_buf;
4108 dest = dest_buf;
4109
4110 rnr = red_n_row;
4111 gnr = grn_n_row;
4112 bnr = blu_n_row;
4113 rpr = red_p_row + 1;
4114 gpr = grn_p_row + 1;
4115 bpr = blu_p_row + 1;
4116
4117 if (odd_row)
4118 {
4119 step_dest = -dest_bpp;
4120 step_src = -src_bpp;
4121
4122 src += (width * src_bpp) - src_bpp;
4123 dest += (width * dest_bpp) - dest_bpp;
4124
4125 rnr += width + 1;
4126 gnr += width + 1;
4127 bnr += width + 1;
4128 rpr += width;
4129 gpr += width;
4130 bpr += width;
4131
4132 *(rnr - 1) = *(gnr - 1) = *(bnr - 1) = 0;
4133 }
4134 else
4135 {
4136 step_dest = dest_bpp;
4137 step_src = src_bpp;
4138
4139 *(rnr + 1) = *(gnr + 1) = *(bnr + 1) = 0;
4140 }
4141
4142 *rnr = *gnr = *bnr = 0;
4143
4144 for (col = 0; col < width; col++)
4145 {
4146 if (has_alpha)
4147 {
4148 gboolean transparent = FALSE;
4149
4150 if (odd_row)
4151 {
4152 if (dither_alpha)
4153 {
4154 gint dither_x = ((width-col)+offsetx-1) & DM_WIDTHMASK;
4155 gint dither_y = (row+offsety) & DM_HEIGHTMASK;
4156
4157 if ((src[alpha_pix]) < DM[dither_x][dither_y])
4158 transparent = TRUE;
4159 }
4160 else
4161 {
4162 if (src[alpha_pix] <= 127)
4163 transparent = TRUE;
4164 }
4165
4166 if (transparent)
4167 {
4168 dest[ALPHA_I] = 0;
4169 rpr--; gpr--; bpr--;
4170 rnr--; gnr--; bnr--;
4171 *(rnr - 1) = *(gnr - 1) = *(bnr - 1) = 0;
4172 goto next_pixel;
4173 }
4174 else
4175 {
4176 dest[ALPHA_I] = 255;
4177 }
4178 }
4179 else
4180 {
4181 if (dither_alpha)
4182 {
4183 gint dither_x = (col + offsetx) & DM_WIDTHMASK;
4184 gint dither_y = (row + offsety) & DM_HEIGHTMASK;
4185
4186 if ((src[alpha_pix]) < DM[dither_x][dither_y])
4187 transparent = TRUE;
4188 }
4189 else
4190 {
4191 if (src[alpha_pix] <= 127)
4192 transparent = TRUE;
4193 }
4194
4195 if (transparent)
4196 {
4197 dest[ALPHA_I] = 0;
4198 rpr++; gpr++; bpr++;
4199 rnr++; gnr++; bnr++;
4200 *(rnr + 1) = *(gnr + 1) = *(bnr + 1) = 0;
4201 goto next_pixel;
4202 }
4203 else
4204 {
4205 dest[ALPHA_I] = 255;
4206 }
4207 }
4208 }
4209
4210 #if 0
4211 /* hmm. */
4212
4213 r = range_limiter[src[red_pix] + error_limiter[*rpr]];
4214 g = range_limiter[src[green_pix] + error_limiter[*gpr]];
4215 b = range_limiter[src[blue_pix] + error_limiter[*bpr]];
4216
4217 re = r >> R_SHIFT;
4218 ge = g >> G_SHIFT;
4219 be = b >> B_SHIFT;
4220
4221 rgb_to_lin (r, g, b, &re, &ge, &be);
4222 #endif
4223 rgb_to_unshifted_lin (src[red_pix], src[green_pix], src[blue_pix],
4224 &re, &ge, &be);
4225
4226 /*
4227 re = CLAMP(re, global_rmin, global_rmax);
4228 ge = CLAMP(ge, global_gmin, global_gmax);
4229 be = CLAMP(be, global_bmin, global_bmax);*/
4230
4231 re = range_limiter[re + error_limiter[*rpr]];
4232 ge = range_limiter[ge + error_limiter[*gpr]];
4233 be = range_limiter[be + error_limiter[*bpr]];
4234
4235 cachep = HIST_LIN (histogram,
4236 RSDF (re),
4237 GSDF (ge),
4238 BSDF (be));
4239 /* If we have not seen this color before, find nearest
4240 * colormap entry and update the cache
4241 */
4242 if (*cachep == 0)
4243 fill_inverse_cmap_rgb (quantobj, histogram,
4244 RSDF (re),
4245 GSDF (ge),
4246 BSDF (be));
4247
4248 index = *cachep - 1;
4249 index_used_count[index]++;
4250 dest[INDEXED] = index;
4251
4252 /*if (re > global_rmax)
4253 re = (re + 3*global_rmax) / 4;
4254 else if (re < global_rmin)
4255 re = (re + 3*global_rmin) / 4;*/
4256
4257 /* We constrain chroma error extra-hard so that it
4258 doesn't run away and steal the thunder from the
4259 lightness error where all the detail usually is. */
4260 if (ge > global_gmax)
4261 ge = (ge + 3*global_gmax) / 4;
4262 else if (ge < global_gmin)
4263 ge = (ge + 3*global_gmin) / 4;
4264 if (be > global_bmax)
4265 be = (be + 3*global_bmax) / 4;
4266 else if (be < global_bmin)
4267 be = (be + 3*global_bmin) / 4;
4268
4269 color = &quantobj->clin[index];
4270
4271 #if 0
4272 if ((re > 0 && re < 255) /* HMM &&
4273 ge >= 0 && ge <= 255 &&
4274 be >= 0 && be <= 255*/)
4275 {
4276 ge = ge - color->green;
4277 be = be - color->blue;
4278 re = re - color->red;
4279 }
4280 else
4281 {
4282 /* color pretty much undefined now; nullify error. */
4283 re = ge = be = 0;
4284 }
4285 #endif
4286
4287 if (re <= 0 || re >= 255)
4288 re = ge = be = 0;
4289 else
4290 {
4291 re = re - color->red;
4292 ge = ge - color->green;
4293 be = be - color->blue;
4294 }
4295
4296 if (odd_row)
4297 {
4298 *(--rpr) += fs_err1[re];
4299 *(--gpr) += fs_err1[ge];
4300 *(--bpr) += fs_err1[be];
4301
4302 *rnr-- += fs_err2[re];
4303 *gnr-- += fs_err2[ge];
4304 *bnr-- += fs_err2[be];
4305
4306 *rnr += fs_err3[re];
4307 *gnr += fs_err3[ge];
4308 *bnr += fs_err3[be];
4309
4310 *(rnr-1) = fs_err4[re];
4311 *(gnr-1) = fs_err4[ge];
4312 *(bnr-1) = fs_err4[be];
4313 }
4314 else
4315 {
4316 *(++rpr) += fs_err1[re];
4317 *(++gpr) += fs_err1[ge];
4318 *(++bpr) += fs_err1[be];
4319
4320 *rnr++ += fs_err2[re];
4321 *gnr++ += fs_err2[ge];
4322 *bnr++ += fs_err2[be];
4323
4324 *rnr += fs_err3[re];
4325 *gnr += fs_err3[ge];
4326 *bnr += fs_err3[be];
4327
4328 *(rnr+1) = fs_err4[re];
4329 *(gnr+1) = fs_err4[ge];
4330 *(bnr+1) = fs_err4[be];
4331 }
4332
4333 next_pixel:
4334
4335 dest += step_dest;
4336 src += step_src;
4337 }
4338
4339 tmp = red_n_row;
4340 red_n_row = red_p_row;
4341 red_p_row = tmp;
4342
4343 tmp = grn_n_row;
4344 grn_n_row = grn_p_row;
4345 grn_p_row = tmp;
4346
4347 tmp = blu_n_row;
4348 blu_n_row = blu_p_row;
4349 blu_p_row = tmp;
4350
4351 odd_row = !odd_row;
4352
4353 gegl_buffer_set (new_buffer, GEGL_RECTANGLE (0, row, width, 1),
4354 0, NULL, dest_buf,
4355 GEGL_AUTO_ROWSTRIDE);
4356
4357 if (quantobj->progress && (row % 16 == 0))
4358 gimp_progress_set_value (quantobj->progress,
4359 (gdouble) row / (gdouble) height);
4360 }
4361
4362 g_free (error_limiter - 255);
4363 g_free (red_n_row);
4364 g_free (red_p_row);
4365 g_free (grn_n_row);
4366 g_free (grn_p_row);
4367 g_free (blu_n_row);
4368 g_free (blu_p_row);
4369 g_free (src_buf);
4370 g_free (dest_buf);
4371 }
4372
4373
4374 static void
delete_median_cut(QuantizeObj * quantobj)4375 delete_median_cut (QuantizeObj *quantobj)
4376 {
4377 g_free (quantobj->histogram);
4378 g_free (quantobj);
4379 }
4380
4381
4382 void
gimp_image_convert_indexed_set_dither_matrix(const guchar * matrix,gint width,gint height)4383 gimp_image_convert_indexed_set_dither_matrix (const guchar *matrix,
4384 gint width,
4385 gint height)
4386 {
4387 gint x;
4388 gint y;
4389
4390 /* if matrix is invalid, restore the default matrix */
4391 if (matrix == NULL || width == 0 || height == 0)
4392 {
4393 matrix = (const guchar *) DM_ORIGINAL;
4394 width = DM_WIDTH;
4395 height = DM_HEIGHT;
4396 }
4397
4398 g_return_if_fail ((DM_WIDTH % width) == 0);
4399 g_return_if_fail ((DM_HEIGHT % height) == 0);
4400
4401 for (y = 0; y < DM_HEIGHT; y++)
4402 {
4403 for (x = 0; x < DM_WIDTH; x++)
4404 {
4405 DM[x][y] = matrix[((x % width) * height) + (y % height)];
4406 }
4407 }
4408 }
4409
4410
4411 /**************************************************************/
4412 static QuantizeObj *
initialize_median_cut(GimpImageBaseType type,gint num_colors,GimpConvertDitherType dither_type,GimpConvertPaletteType palette_type,GimpPalette * custom_palette,gboolean want_dither_alpha,GimpProgress * progress)4413 initialize_median_cut (GimpImageBaseType type,
4414 gint num_colors,
4415 GimpConvertDitherType dither_type,
4416 GimpConvertPaletteType palette_type,
4417 GimpPalette *custom_palette,
4418 gboolean want_dither_alpha,
4419 GimpProgress *progress)
4420 {
4421 QuantizeObj *quantobj;
4422
4423 /* Initialize the data structures */
4424 quantobj = g_new (QuantizeObj, 1);
4425
4426 if (type == GIMP_GRAY && palette_type == GIMP_CONVERT_PALETTE_GENERATE)
4427 quantobj->histogram = g_new (ColorFreq, 256);
4428 else
4429 quantobj->histogram = g_new (ColorFreq,
4430 HIST_R_ELEMS * HIST_G_ELEMS * HIST_B_ELEMS);
4431
4432 quantobj->custom_palette = custom_palette;
4433 quantobj->desired_number_of_colors = num_colors;
4434 quantobj->want_dither_alpha = want_dither_alpha;
4435 quantobj->progress = progress;
4436
4437 switch (type)
4438 {
4439 case GIMP_GRAY:
4440 switch (palette_type)
4441 {
4442 case GIMP_CONVERT_PALETTE_GENERATE:
4443 quantobj->first_pass = median_cut_pass1_gray;
4444 break;
4445 case GIMP_CONVERT_PALETTE_WEB:
4446 quantobj->first_pass = webpal_pass1;
4447 break;
4448 case GIMP_CONVERT_PALETTE_CUSTOM:
4449 quantobj->first_pass = custompal_pass1;
4450 needs_quantize = TRUE;
4451 break;
4452 case GIMP_CONVERT_PALETTE_MONO:
4453 default:
4454 quantobj->first_pass = monopal_pass1;
4455 }
4456
4457 if (palette_type == GIMP_CONVERT_PALETTE_WEB ||
4458 palette_type == GIMP_CONVERT_PALETTE_CUSTOM)
4459 {
4460 switch (dither_type)
4461 {
4462 case GIMP_CONVERT_DITHER_NODESTRUCT:
4463 default:
4464 g_warning("Uh-oh, bad dither type, W1");
4465 case GIMP_CONVERT_DITHER_NONE:
4466 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4467 quantobj->second_pass = median_cut_pass2_no_dither_rgb;
4468 break;
4469 case GIMP_CONVERT_DITHER_FS:
4470 quantobj->error_freedom = 0;
4471 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4472 quantobj->second_pass = median_cut_pass2_fs_dither_rgb;
4473 break;
4474 case GIMP_CONVERT_DITHER_FS_LOWBLEED:
4475 quantobj->error_freedom = 1;
4476 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4477 quantobj->second_pass = median_cut_pass2_fs_dither_rgb;
4478 break;
4479 case GIMP_CONVERT_DITHER_FIXED:
4480 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4481 quantobj->second_pass = median_cut_pass2_fixed_dither_rgb;
4482 break;
4483 }
4484 }
4485 else
4486 {
4487 switch (dither_type)
4488 {
4489 case GIMP_CONVERT_DITHER_NODESTRUCT:
4490 default:
4491 g_warning("Uh-oh, bad dither type, W2");
4492 case GIMP_CONVERT_DITHER_NONE:
4493 quantobj->second_pass_init = median_cut_pass2_gray_init;
4494 quantobj->second_pass = median_cut_pass2_no_dither_gray;
4495 break;
4496 case GIMP_CONVERT_DITHER_FS:
4497 quantobj->error_freedom = 0;
4498 quantobj->second_pass_init = median_cut_pass2_gray_init;
4499 quantobj->second_pass = median_cut_pass2_fs_dither_gray;
4500 break;
4501 case GIMP_CONVERT_DITHER_FS_LOWBLEED:
4502 quantobj->error_freedom = 1;
4503 quantobj->second_pass_init = median_cut_pass2_gray_init;
4504 quantobj->second_pass = median_cut_pass2_fs_dither_gray;
4505 break;
4506 case GIMP_CONVERT_DITHER_FIXED:
4507 quantobj->second_pass_init = median_cut_pass2_gray_init;
4508 quantobj->second_pass = median_cut_pass2_fixed_dither_gray;
4509 break;
4510 }
4511 }
4512 break;
4513
4514 case GIMP_RGB:
4515 switch (palette_type)
4516 {
4517 case GIMP_CONVERT_PALETTE_GENERATE:
4518 quantobj->first_pass = median_cut_pass1_rgb;
4519 break;
4520 case GIMP_CONVERT_PALETTE_WEB:
4521 quantobj->first_pass = webpal_pass1;
4522 needs_quantize = TRUE;
4523 break;
4524 case GIMP_CONVERT_PALETTE_CUSTOM:
4525 quantobj->first_pass = custompal_pass1;
4526 needs_quantize = TRUE;
4527 break;
4528 case GIMP_CONVERT_PALETTE_MONO:
4529 default:
4530 quantobj->first_pass = monopal_pass1;
4531 }
4532
4533 switch (dither_type)
4534 {
4535 case GIMP_CONVERT_DITHER_NONE:
4536 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4537 quantobj->second_pass = median_cut_pass2_no_dither_rgb;
4538 break;
4539 case GIMP_CONVERT_DITHER_FS:
4540 quantobj->error_freedom = 0;
4541 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4542 quantobj->second_pass = median_cut_pass2_fs_dither_rgb;
4543 break;
4544 case GIMP_CONVERT_DITHER_FS_LOWBLEED:
4545 quantobj->error_freedom = 1;
4546 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4547 quantobj->second_pass = median_cut_pass2_fs_dither_rgb;
4548 break;
4549 case GIMP_CONVERT_DITHER_NODESTRUCT:
4550 quantobj->second_pass_init = NULL;
4551 quantobj->second_pass = median_cut_pass2_nodestruct_dither_rgb;
4552 break;
4553 case GIMP_CONVERT_DITHER_FIXED:
4554 quantobj->second_pass_init = median_cut_pass2_rgb_init;
4555 quantobj->second_pass = median_cut_pass2_fixed_dither_rgb;
4556 break;
4557 }
4558 break;
4559
4560 default:
4561 break;
4562 }
4563
4564 quantobj->delete_func = delete_median_cut;
4565
4566 return quantobj;
4567 }
4568