pikl 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1179 @@
1
+ /*
2
+ Based upon a GIMP filter ("to-indexed.c"):
3
+ "The GIMP -- an image manipulation program
4
+ Copyright (C) 1995 Spencer Kimball and Peter Mattis"
5
+
6
+ "This filter takes an rgb input image and creates a new
7
+ indexed color image."
8
+
9
+ median_cut, 2-pass, floyd no/yes
10
+ char *out = to_indexed(input_image, num, dither, xsize, ysize, &colormap);
11
+
12
+ Benny:
13
+ v0.2 - Win95 GPF fixed.
14
+ v0.3 - weeded out some functions.
15
+ */
16
+
17
+ #include <stdio.h>
18
+ #include <stdlib.h>
19
+ #include <string.h>
20
+ #include <malloc.h>
21
+ //#include <mem.h>
22
+
23
+
24
+ #include "fsdither.h" // tables:
25
+ /* 'range_array' 'floyd_steinberg_error1' 'floyd_steinberg_error2'
26
+ 'floyd_steinberg_error3' 'floyd_steinberg_error4'*/
27
+
28
+ #define MAXNUMCOLORS 256
29
+
30
+ /* dither type */
31
+ #define NODITHER 0
32
+ #define FSDITHER 1
33
+
34
+ #define PRECISION_R 6
35
+ #define PRECISION_G 6
36
+ //#define PRECISION_B 6 // worse
37
+ #define PRECISION_B 5 // ori
38
+
39
+ //#if 0
40
+ #define R_SCALE
41
+ #define G_SCALE
42
+ #define B_SCALE
43
+ //#else
44
+ ///* scale RGB distances by *2,*3,*1 */
45
+ //#define R_SCALE << 1
46
+ //#define G_SCALE * 3
47
+ //#define B_SCALE
48
+ //#endif
49
+
50
+
51
+ #define HIST_R_ELEMS (1<<PRECISION_R)
52
+ #define HIST_G_ELEMS (1<<PRECISION_G)
53
+ #define HIST_B_ELEMS (1<<PRECISION_B)
54
+
55
+ #define MR HIST_G_ELEMS*HIST_B_ELEMS
56
+ #define MG HIST_B_ELEMS
57
+
58
+ #define BITS_IN_SAMPLE 8
59
+
60
+ #define R_SHIFT (BITS_IN_SAMPLE - PRECISION_R)
61
+ #define G_SHIFT (BITS_IN_SAMPLE - PRECISION_G)
62
+ #define B_SHIFT (BITS_IN_SAMPLE - PRECISION_B)
63
+
64
+ typedef struct _Color Color;
65
+ typedef struct _QuantizeObj QuantizeObj;
66
+ typedef void (*Pass_Func) (QuantizeObj *, unsigned char *, unsigned char *, long, long);
67
+ //typedef void (*Cleanup_Func) (QuantizeObj *);
68
+ typedef unsigned long ColorFreq;
69
+ typedef ColorFreq *Histogram;
70
+
71
+ struct _Color {
72
+ int red;
73
+ int green;
74
+ int blue;
75
+ };
76
+
77
+ struct _QuantizeObj {
78
+ Pass_Func first_pass; /* first pass over image data creates colormap */
79
+ Pass_Func second_pass; /* second pass maps from image data to colormap */
80
+ // Cleanup_Func delete_func; /* function to clean up data associated with private */
81
+ // int bpp; /* bytes per pixel (grayscale vs rgb) */
82
+ int desired_number_of_colors; /* Number of colors we will allow */
83
+ int actual_number_of_colors; /* Number of colors actually needed */
84
+ Color cmap[256]; /* colormap created by quantization */
85
+ Histogram histogram; /* holds the histogram */
86
+ };
87
+
88
+ typedef struct {
89
+ /* The bounds of the box (inclusive); expressed as histogram indexes */
90
+ int Rmin, Rmax;
91
+ int Gmin, Gmax;
92
+ int Bmin, Bmax;
93
+ /* The volume (actually 2-norm) of the box */
94
+ int volume;
95
+ /* The number of nonzero histogram cells within this box */
96
+ long colorcount;
97
+ } box , *boxptr;
98
+
99
+ typedef struct {
100
+ long ncolors;
101
+ long dither;
102
+ } Options;
103
+
104
+ //void error(char*);
105
+ void error(char*msg){
106
+ fprintf(stderr, "%s\n", msg);
107
+ }
108
+
109
+ /*
110
+ static void *xmalloc(unsigned long size)
111
+ {
112
+ void *p;
113
+ p = malloc(size);
114
+ if (!p) error("could not xmallocate memory");
115
+ return p;
116
+ }
117
+ */
118
+
119
+ static void xfree(void *p)
120
+ {
121
+ if (p)
122
+ free(p);
123
+ }
124
+
125
+ static void zero_histogram_rgb(Histogram histogram)
126
+ {
127
+ int r, g, b;
128
+ for (r = 0; r < HIST_R_ELEMS; r++)
129
+ for (g = 0; g < HIST_G_ELEMS; g++)
130
+ for (b = 0; b < HIST_B_ELEMS; b++)
131
+ histogram[r * MR + g * MG + b] = 0;
132
+ }
133
+
134
+ static void generate_histogram_rgb(histogram, src, width, height)
135
+ Histogram histogram;
136
+ unsigned char *src;
137
+ long width;
138
+ long height;
139
+ {
140
+ int num_elems;
141
+ ColorFreq *col;
142
+
143
+ num_elems = width * height;
144
+ zero_histogram_rgb(histogram);
145
+
146
+ while (num_elems--) {
147
+ col = &histogram[(src[0] >> R_SHIFT) * MR +
148
+ (src[1] >> G_SHIFT) * MG +
149
+ (src[2] >> B_SHIFT)];
150
+ (*col)++;
151
+ src += 3;
152
+ }
153
+ }
154
+
155
+ static boxptr
156
+ find_biggest_color_pop(boxlist, numboxes)
157
+ boxptr boxlist;
158
+ int numboxes;
159
+ /* Find the splittable box with the largest color population */
160
+ /* Returns 0 if no splittable boxes remain */
161
+ {
162
+ boxptr boxp;
163
+ int i;
164
+ long maxc = 0;
165
+ boxptr which = 0;
166
+
167
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
168
+ if (boxp->colorcount > maxc && boxp->volume > 0) {
169
+ which = boxp;
170
+ maxc = boxp->colorcount;
171
+ }
172
+ }
173
+
174
+ return which;
175
+ }
176
+
177
+
178
+ static boxptr
179
+ find_biggest_volume(boxlist, numboxes)
180
+ boxptr boxlist;
181
+ int numboxes;
182
+ /* Find the splittable box with the largest (scaled) volume */
183
+ /* Returns 0 if no splittable boxes remain */
184
+ {
185
+ boxptr boxp;
186
+ int i;
187
+ int maxv = 0;
188
+ boxptr which = 0;
189
+
190
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
191
+ if (boxp->volume > maxv) {
192
+ which = boxp;
193
+ maxv = boxp->volume;
194
+ }
195
+ }
196
+
197
+ return which;
198
+ }
199
+
200
+
201
+ static void update_box_rgb(histogram, boxp)
202
+ Histogram histogram;
203
+ boxptr boxp;
204
+ /* Shrink the min/max bounds of a box to enclose only nonzero elements, */
205
+ /* and recompute its volume and population */
206
+ {
207
+ ColorFreq *histp;
208
+ int R, G, B;
209
+ int Rmin, Rmax, Gmin, Gmax, Bmin, Bmax;
210
+ int dist0, dist1, dist2;
211
+ long ccount;
212
+
213
+ Rmin = boxp->Rmin;
214
+ Rmax = boxp->Rmax;
215
+ Gmin = boxp->Gmin;
216
+ Gmax = boxp->Gmax;
217
+ Bmin = boxp->Bmin;
218
+ Bmax = boxp->Bmax;
219
+
220
+ if (Rmax > Rmin)
221
+ for (R = Rmin; R <= Rmax; R++)
222
+ for (G = Gmin; G <= Gmax; G++) {
223
+ histp = histogram + R * MR + G * MG + Bmin;
224
+ for (B = Bmin; B <= Bmax; B++)
225
+ if (*histp++ != 0) {
226
+ boxp->Rmin = Rmin = R;
227
+ goto have_Rmin;
228
+ }
229
+ }
230
+ have_Rmin:
231
+ if (Rmax > Rmin)
232
+ for (R = Rmax; R >= Rmin; R--)
233
+ for (G = Gmin; G <= Gmax; G++) {
234
+ histp = histogram + R * MR + G * MG + Bmin;
235
+ for (B = Bmin; B <= Bmax; B++)
236
+ if (*histp++ != 0) {
237
+ boxp->Rmax = Rmax = R;
238
+ goto have_Rmax;
239
+ }
240
+ }
241
+ have_Rmax:
242
+ if (Gmax > Gmin)
243
+ for (G = Gmin; G <= Gmax; G++)
244
+ for (R = Rmin; R <= Rmax; R++) {
245
+ histp = histogram + R * MR + G * MG + Bmin;
246
+ for (B = Bmin; B <= Bmax; B++)
247
+ if (*histp++ != 0) {
248
+ boxp->Gmin = Gmin = G;
249
+ goto have_Gmin;
250
+ }
251
+ }
252
+ have_Gmin:
253
+ if (Gmax > Gmin)
254
+ for (G = Gmax; G >= Gmin; G--)
255
+ for (R = Rmin; R <= Rmax; R++) {
256
+ histp = histogram + R * MR + G * MG + Bmin;
257
+ for (B = Bmin; B <= Bmax; B++)
258
+ if (*histp++ != 0) {
259
+ boxp->Gmax = Gmax = G;
260
+ goto have_Gmax;
261
+ }
262
+ }
263
+ have_Gmax:
264
+ if (Bmax > Bmin)
265
+ for (B = Bmin; B <= Bmax; B++)
266
+ for (R = Rmin; R <= Rmax; R++) {
267
+ histp = histogram + R * MR + Gmin * MG + B;
268
+ for (G = Gmin; G <= Gmax; G++, histp += MG)
269
+ if (*histp != 0) {
270
+ boxp->Bmin = Bmin = B;
271
+ goto have_Bmin;
272
+ }
273
+ }
274
+ have_Bmin:
275
+ if (Bmax > Bmin)
276
+ for (B = Bmax; B >= Bmin; B--)
277
+ for (R = Rmin; R <= Rmax; R++) {
278
+ histp = histogram + R * MR + Gmin * MG + B;
279
+ for (G = Gmin; G <= Gmax; G++, histp += MG)
280
+ if (*histp != 0) {
281
+ boxp->Bmax = Bmax = B;
282
+ goto have_Bmax;
283
+ }
284
+ }
285
+ have_Bmax:
286
+
287
+ /* Update box volume.
288
+ * We use 2-norm rather than real volume here; this biases the method
289
+ * against making long narrow boxes, and it has the side benefit that
290
+ * a box is splittable iff norm > 0.
291
+ * Since the differences are expressed in histogram-cell units,
292
+ * we have to shift back to JSAMPLE units to get consistent distances;
293
+ * after which, we scale according to the selected distance scale factors.
294
+ */
295
+ dist0 = ((Rmax - Rmin) << R_SHIFT) R_SCALE;
296
+ dist1 = ((Gmax - Gmin) << G_SHIFT) G_SCALE;
297
+ dist2 = ((Bmax - Bmin) << B_SHIFT) B_SCALE;
298
+ boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2;
299
+
300
+ /* Now scan remaining volume of box and compute population */
301
+ ccount = 0;
302
+ for (R = Rmin; R <= Rmax; R++)
303
+ for (G = Gmin; G <= Gmax; G++) {
304
+ histp = histogram + R * MR + G * MG + Bmin;
305
+ for (B = Bmin; B <= Bmax; B++, histp++)
306
+ if (*histp != 0) {
307
+ ccount++;
308
+ }
309
+ }
310
+
311
+ boxp->colorcount = ccount;
312
+ }
313
+
314
+
315
+ static int median_cut_rgb(histogram, boxlist, numboxes, desired_colors)
316
+ Histogram histogram;
317
+ boxptr boxlist;
318
+ int numboxes;
319
+ int desired_colors;
320
+ /* Repeatedly select and split the largest box until we have enough boxes */
321
+ {
322
+ int n, lb;
323
+ int R, G, B, cmax;
324
+ boxptr b1, b2;
325
+
326
+ while (numboxes < desired_colors) {
327
+ /* Select box to split.
328
+ * Current algorithm: by population for first half, then by volume.
329
+ */
330
+ if (numboxes * 2 <= desired_colors) {
331
+ b1 = find_biggest_color_pop(boxlist, numboxes);
332
+ } else {
333
+ b1 = find_biggest_volume(boxlist, numboxes);
334
+ }
335
+
336
+ if (b1 == 0) /* no splittable boxes left! */
337
+ break;
338
+ b2 = boxlist + numboxes; /* where new box will go */
339
+ /* Copy the color bounds to the new box. */
340
+ b2->Rmax = b1->Rmax;
341
+ b2->Gmax = b1->Gmax;
342
+ b2->Bmax = b1->Bmax;
343
+ b2->Rmin = b1->Rmin;
344
+ b2->Gmin = b1->Gmin;
345
+ b2->Bmin = b1->Bmin;
346
+ /* Choose which axis to split the box on.
347
+ * Current algorithm: longest scaled axis.
348
+ * See notes in update_box about scaling distances.
349
+ */
350
+ R = ((b1->Rmax - b1->Rmin) << R_SHIFT) R_SCALE;
351
+ G = ((b1->Gmax - b1->Gmin) << G_SHIFT) G_SCALE;
352
+ B = ((b1->Bmax - b1->Bmin) << B_SHIFT) B_SCALE;
353
+ /* We want to break any ties in favor of green, then red, blue last.
354
+ */
355
+ cmax = G;
356
+ n = 1;
357
+ if (R > cmax) {
358
+ cmax = R;
359
+ n = 0;
360
+ }
361
+ if (B > cmax) {
362
+ n = 2;
363
+ }
364
+ /* Choose split point along selected axis, and update box bounds.
365
+ * Current algorithm: split at halfway point.
366
+ * (Since the box has been shrunk to minimum volume,
367
+ * any split will produce two nonempty subboxes.)
368
+ * Note that lb value is max for lower box, so must be < old max.
369
+ */
370
+ switch (n) {
371
+ case 0:
372
+ lb = (b1->Rmax + b1->Rmin) / 2;
373
+ b1->Rmax = lb;
374
+ b2->Rmin = lb + 1;
375
+ break;
376
+ case 1:
377
+ lb = (b1->Gmax + b1->Gmin) / 2;
378
+ b1->Gmax = lb;
379
+ b2->Gmin = lb + 1;
380
+ break;
381
+ case 2:
382
+ lb = (b1->Bmax + b1->Bmin) / 2;
383
+ b1->Bmax = lb;
384
+ b2->Bmin = lb + 1;
385
+ break;
386
+ }
387
+ /* Update stats for boxes */
388
+ update_box_rgb(histogram, b1);
389
+ update_box_rgb(histogram, b2);
390
+ numboxes++;
391
+ }
392
+ return numboxes;
393
+ }
394
+
395
+
396
+ static void compute_color_rgb(quantobj, histogram, boxp, icolor)
397
+ QuantizeObj *quantobj;
398
+ Histogram histogram;
399
+ boxptr boxp;
400
+ int icolor;
401
+ /* Compute representative color for a box, put it in colormap[icolor] */
402
+ {
403
+ /* Current algorithm: mean weighted by pixels (not colors) */
404
+ /* Note it is important to get the rounding correct! */
405
+ ColorFreq *histp;
406
+ int R, G, B;
407
+ int Rmin, Rmax;
408
+ int Gmin, Gmax;
409
+ int Bmin, Bmax;
410
+ long count;
411
+ long total = 0;
412
+ long Rtotal = 0;
413
+ long Gtotal = 0;
414
+ long Btotal = 0;
415
+
416
+ Rmin = boxp->Rmin;
417
+ Rmax = boxp->Rmax;
418
+ Gmin = boxp->Gmin;
419
+ Gmax = boxp->Gmax;
420
+ Bmin = boxp->Bmin;
421
+ Bmax = boxp->Bmax;
422
+
423
+ for (R = Rmin; R <= Rmax; R++)
424
+ for (G = Gmin; G <= Gmax; G++) {
425
+ histp = histogram + R * MR + G * MG + Bmin;
426
+ for (B = Bmin; B <= Bmax; B++) {
427
+ if ((count = *histp++) != 0) {
428
+ total += count;
429
+ Rtotal += ((R << R_SHIFT) + ((1 << R_SHIFT) >> 1)) * count;
430
+ Gtotal += ((G << G_SHIFT) + ((1 << G_SHIFT) >> 1)) * count;
431
+ Btotal += ((B << B_SHIFT) + ((1 << B_SHIFT) >> 1)) * count;
432
+ }
433
+ }
434
+ }
435
+
436
+ quantobj->cmap[icolor].red = (Rtotal + (total >> 1)) / total;
437
+ quantobj->cmap[icolor].green = (Gtotal + (total >> 1)) / total;
438
+ quantobj->cmap[icolor].blue = (Btotal + (total >> 1)) / total;
439
+ }
440
+
441
+
442
+ static void select_colors_rgb(quantobj, histogram)
443
+ QuantizeObj *quantobj;
444
+ Histogram histogram;
445
+ /* Master routine for color selection */
446
+ {
447
+ boxptr boxlist;
448
+ int numboxes;
449
+ int desired = quantobj->desired_number_of_colors;
450
+ int i;
451
+
452
+ /* Allocate workspace for box list */
453
+ boxlist = (boxptr) malloc(desired * sizeof(box));
454
+ if (!boxlist) error("could not alloc mem");
455
+
456
+ /* Initialize one box containing whole space */
457
+ numboxes = 1;
458
+ boxlist[0].Rmin = 0;
459
+ boxlist[0].Rmax = (1 << PRECISION_R) - 1;
460
+ boxlist[0].Gmin = 0;
461
+ boxlist[0].Gmax = (1 << PRECISION_G) - 1;
462
+ boxlist[0].Bmin = 0;
463
+ boxlist[0].Bmax = (1 << PRECISION_B) - 1;
464
+ /* Shrink it to actually-used volume and set its statistics */
465
+ update_box_rgb(histogram, boxlist);
466
+ /* Perform median-cut to produce final box list */
467
+ numboxes = median_cut_rgb(histogram, boxlist, numboxes, desired);
468
+ quantobj->actual_number_of_colors = numboxes;
469
+ /* Compute the representative color for each box, fill colormap */
470
+ for (i = 0; i < numboxes; i++)
471
+ compute_color_rgb(quantobj, histogram, boxlist + i, i);
472
+
473
+ //add by soezimaster
474
+ free(boxlist);
475
+ }
476
+
477
+
478
+ /*
479
+ * These routines are concerned with the time-critical task of mapping input
480
+ * colors to the nearest color in the selected colormap.
481
+ *
482
+ * We re-use the histogram space as an "inverse color map", essentially a
483
+ * cache for the results of nearest-color searches. All colors within a
484
+ * histogram cell will be mapped to the same colormap entry, namely the one
485
+ * closest to the cell's center. This may not be quite the closest entry to
486
+ * the actual input color, but it's almost as good. A zero in the cache
487
+ * indicates we haven't found the nearest color for that cell yet; the array
488
+ * is cleared to zeroes before starting the mapping pass. When we find the
489
+ * nearest color for a cell, its colormap index plus one is recorded in the
490
+ * cache for future use. The pass2 scanning routines call fill_inverse_cmap
491
+ * when they need to use an unfilled entry in the cache.
492
+ *
493
+ * Our method of efficiently finding nearest colors is based on the "locally
494
+ * sorted search" idea described by Heckbert and on the incremental distance
495
+ * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
496
+ * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that
497
+ * the distances from a given colormap entry to each cell of the histogram can
498
+ * be computed quickly using an incremental method: the differences between
499
+ * distances to adjacent cells themselves differ by a constant. This allows a
500
+ * fairly fast implementation of the "brute force" approach of computing the
501
+ * distance from every colormap entry to every histogram cell. Unfortunately,
502
+ * it needs a work array to hold the best-distance-so-far for each histogram
503
+ * cell (because the inner loop has to be over cells, not colormap entries).
504
+ * The work array elements have to be ints, so the work array would need
505
+ * 256Kb at our recommended precision. This is not feasible in DOS machines.
506
+
507
+ [ 256*1024/4 = 65,536 ]
508
+
509
+ * To get around these problems, we apply Thomas' method to compute the
510
+ * nearest colors for only the cells within a small subbox of the histogram.
511
+ * The work array need be only as big as the subbox, so the memory usage
512
+ * problem is solved. Furthermore, we need not fill subboxes that are never
513
+ * referenced in pass2; many images use only part of the color gamut, so a
514
+ * fair amount of work is saved. An additional advantage of this
515
+ * approach is that we can apply Heckbert's locality criterion to quickly
516
+ * eliminate colormap entries that are far away from the subbox; typically
517
+ * three-fourths of the colormap entries are rejected by Heckbert's criterion,
518
+ * and we need not compute their distances to individual cells in the subbox.
519
+ * The speed of this approach is heavily influenced by the subbox size: too
520
+ * small means too much overhead, too big loses because Heckbert's criterion
521
+ * can't eliminate as many colormap entries. Empirically the best subbox
522
+ * size seems to be about 1/512th of the histogram (1/8th in each direction).
523
+ *
524
+ * Thomas' article also describes a refined method which is asymptotically
525
+ * faster than the brute-force method, but it is also far more complex and
526
+ * cannot efficiently be applied to small subboxes. It is therefore not
527
+ * useful for programs intended to be portable to DOS machines. On machines
528
+ * with plenty of memory, filling the whole histogram in one shot with Thomas'
529
+ * refined method might be faster than the present code --- but then again,
530
+ * it might not be any faster, and it's certainly more complicated.
531
+ */
532
+
533
+ /* log2(histogram cells in update box) for each axis; this can be adjusted */
534
+ #define BOX_R_LOG (PRECISION_R-3)
535
+ #define BOX_G_LOG (PRECISION_G-3)
536
+ #define BOX_B_LOG (PRECISION_B-3)
537
+
538
+ #define BOX_R_ELEMS (1<<BOX_R_LOG) /* # of hist cells in update box */
539
+ #define BOX_G_ELEMS (1<<BOX_G_LOG)
540
+ #define BOX_B_ELEMS (1<<BOX_B_LOG)
541
+
542
+ #define BOX_R_SHIFT (R_SHIFT + BOX_R_LOG)
543
+ #define BOX_G_SHIFT (G_SHIFT + BOX_G_LOG)
544
+ #define BOX_B_SHIFT (B_SHIFT + BOX_B_LOG)
545
+
546
+ /*
547
+ * The next three routines implement inverse colormap filling. They could
548
+ * all be folded into one big routine, but splitting them up this way saves
549
+ * some stack space (the mindist[] and bestdist[] arrays need not coexist)
550
+ * and may allow some compilers to produce better code by registerizing more
551
+ * inner-loop variables.
552
+ */
553
+
554
+ static int find_nearby_colors(quantobj, minR, minG, minB, colorlist)
555
+ QuantizeObj *quantobj;
556
+ int minR;
557
+ int minG;
558
+ int minB;
559
+ int colorlist[];
560
+ /* Locate the colormap entries close enough to an update box to be candidates
561
+ * for the nearest entry to some cell(s) in the update box. The update box
562
+ * is specified by the center coordinates of its first cell. The number of
563
+ * candidate colormap entries is returned, and their colormap indexes are
564
+ * placed in colorlist[].
565
+ * This routine uses Heckbert's "locally sorted search" criterion to select
566
+ * the colors that need further consideration.
567
+ */
568
+ {
569
+ int numcolors = quantobj->actual_number_of_colors;
570
+ int maxR, maxG, maxB;
571
+ int centerR, centerG, centerB;
572
+ int i, x, ncolors;
573
+ int minmaxdist, min_dist, max_dist, tdist;
574
+ int mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
575
+
576
+ /* Compute true coordinates of update box's upper corner and center.
577
+ * Actually we compute the coordinates of the center of the upper-corner
578
+ * histogram cell, which are the upper bounds of the volume we care about.
579
+ * Note that since ">>" rounds down, the "center" values may be closer to
580
+ * min than to max; hence comparisons to them must be "<=", not "<".
581
+ */
582
+ maxR = minR + ((1 << BOX_R_SHIFT) - (1 << R_SHIFT));
583
+ centerR = (minR + maxR) >> 1;
584
+ maxG = minG + ((1 << BOX_G_SHIFT) - (1 << G_SHIFT));
585
+ centerG = (minG + maxG) >> 1;
586
+ maxB = minB + ((1 << BOX_B_SHIFT) - (1 << B_SHIFT));
587
+ centerB = (minB + maxB) >> 1;
588
+
589
+ /* For each color in colormap, find:
590
+ * 1. its minimum squared-distance to any point in the update box
591
+ * (zero if color is within update box);
592
+ * 2. its maximum squared-distance to any point in the update box.
593
+ * Both of these can be found by considering only the corners of the box.
594
+ * We save the minimum distance for each color in mindist[];
595
+ * only the smallest maximum distance is of interest.
596
+ */
597
+ minmaxdist = 0x7FFFFFFFL;
598
+
599
+ for (i = 0; i < numcolors; i++) {
600
+ /* We compute the squared-R-distance term, then add in the other two. */
601
+ x = quantobj->cmap[i].red;
602
+ if (x < minR) {
603
+ tdist = (x - minR) R_SCALE;
604
+ min_dist = tdist * tdist;
605
+ tdist = (x - maxR) R_SCALE;
606
+ max_dist = tdist * tdist;
607
+ } else if (x > maxR) {
608
+ tdist = (x - maxR) R_SCALE;
609
+ min_dist = tdist * tdist;
610
+ tdist = (x - minR) R_SCALE;
611
+ max_dist = tdist * tdist;
612
+ } else {
613
+ /* within cell range so no contribution to min_dist */
614
+ min_dist = 0;
615
+ if (x <= centerR) {
616
+ tdist = (x - maxR) R_SCALE;
617
+ max_dist = tdist * tdist;
618
+ } else {
619
+ tdist = (x - minR) R_SCALE;
620
+ max_dist = tdist * tdist;
621
+ }
622
+ }
623
+
624
+ x = quantobj->cmap[i].green;
625
+ if (x < minG) {
626
+ tdist = (x - minG) G_SCALE;
627
+ min_dist += tdist * tdist;
628
+ tdist = (x - maxG) G_SCALE;
629
+ max_dist += tdist * tdist;
630
+ } else if (x > maxG) {
631
+ tdist = (x - maxG) G_SCALE;
632
+ min_dist += tdist * tdist;
633
+ tdist = (x - minG) G_SCALE;
634
+ max_dist += tdist * tdist;
635
+ } else {
636
+ /* within cell range so no contribution to min_dist */
637
+ if (x <= centerG) {
638
+ tdist = (x - maxG) G_SCALE;
639
+ max_dist += tdist * tdist;
640
+ } else {
641
+ tdist = (x - minG) G_SCALE;
642
+ max_dist += tdist * tdist;
643
+ }
644
+ }
645
+
646
+ x = quantobj->cmap[i].blue;
647
+ if (x < minB) {
648
+ tdist = (x - minB) B_SCALE;
649
+ min_dist += tdist * tdist;
650
+ tdist = (x - maxB) B_SCALE;
651
+ max_dist += tdist * tdist;
652
+ } else if (x > maxB) {
653
+ tdist = (x - maxB) B_SCALE;
654
+ min_dist += tdist * tdist;
655
+ tdist = (x - minB) B_SCALE;
656
+ max_dist += tdist * tdist;
657
+ } else {
658
+ /* within cell range so no contribution to min_dist */
659
+ if (x <= centerB) {
660
+ tdist = (x - maxB) B_SCALE;
661
+ max_dist += tdist * tdist;
662
+ } else {
663
+ tdist = (x - minB) B_SCALE;
664
+ max_dist += tdist * tdist;
665
+ }
666
+ }
667
+
668
+ mindist[i] = min_dist; /* save away the results */
669
+ if (max_dist < minmaxdist)
670
+ minmaxdist = max_dist;
671
+ }
672
+
673
+ /* Now we know that no cell in the update box is more than minmaxdist
674
+ * away from some colormap entry. Therefore, only colors that are
675
+ * within minmaxdist of some part of the box need be considered.
676
+ */
677
+ ncolors = 0;
678
+ for (i = 0; i < numcolors; i++) {
679
+ if (mindist[i] <= minmaxdist)
680
+ colorlist[ncolors++] = i;
681
+ }
682
+ return ncolors;
683
+ }
684
+
685
+
686
+ static void find_best_colors(quantobj, minR, minG, minB, numcolors, colorlist, bestcolor)
687
+ QuantizeObj *quantobj;
688
+ int minR;
689
+ int minG;
690
+ int minB;
691
+ int numcolors;
692
+ int colorlist[];
693
+ int bestcolor[];
694
+ /* Find the closest colormap entry for each cell in the update box,
695
+ given the list of candidate colors prepared by find_nearby_colors.
696
+ Return the indexes of the closest entries in the bestcolor[] array.
697
+ This routine uses Thomas' incremental distance calculation method to
698
+ find the distance from a colormap entry to successive cells in the box.
699
+ */
700
+ {
701
+ int iR, iG, iB;
702
+ int i, icolor;
703
+ int *bptr; /* pointer into bestdist[] array */
704
+ int *cptr; /* pointer into bestcolor[] array */
705
+ int dist0, dist1; /* initial distance values */
706
+ int dist2; /* current distance in inner loop */
707
+ int xx0, xx1; /* distance increments */
708
+ int xx2;
709
+ int inR, inG, inB; /* initial values for increments */
710
+
711
+ /* This array holds the distance to the nearest-so-far color for each cell */
712
+ int bestdist[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS];
713
+
714
+ /* Initialize best-distance for each cell of the update box */
715
+ bptr = bestdist;
716
+ for (i = BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS - 1; i >= 0; i--)
717
+ *bptr++ = 0x7FFFFFFFL;
718
+
719
+ /* For each color selected by find_nearby_colors,
720
+ * compute its distance to the center of each cell in the box.
721
+ * If that's less than best-so-far, update best distance and color number.
722
+ */
723
+
724
+ /* Nominal steps between cell centers ("x" in Thomas article) */
725
+ #define STEP_R ((1 << R_SHIFT) R_SCALE)
726
+ #define STEP_G ((1 << G_SHIFT) G_SCALE)
727
+ #define STEP_B ((1 << B_SHIFT) B_SCALE)
728
+
729
+ for (i = 0; i < numcolors; i++) {
730
+ icolor = colorlist[i];
731
+ /* Compute (square of) distance from minR/G/B to this color */
732
+ inR = (minR - quantobj->cmap[icolor].red) R_SCALE;
733
+ dist0 = inR * inR;
734
+ inG = (minG - quantobj->cmap[icolor].green) G_SCALE;
735
+ dist0 += inG * inG;
736
+ inB = (minB - quantobj->cmap[icolor].blue) B_SCALE;
737
+ dist0 += inB * inB;
738
+ /* Form the initial difference increments */
739
+ inR = inR * (2 * STEP_R) + STEP_R * STEP_R;
740
+ inG = inG * (2 * STEP_G) + STEP_G * STEP_G;
741
+ inB = inB * (2 * STEP_B) + STEP_B * STEP_B;
742
+ /* Now loop over all cells in box, updating distance per Thomas method */
743
+ bptr = bestdist;
744
+ cptr = bestcolor;
745
+ xx0 = inR;
746
+ for (iR = BOX_R_ELEMS - 1; iR >= 0; iR--) {
747
+ dist1 = dist0;
748
+ xx1 = inG;
749
+ for (iG = BOX_G_ELEMS - 1; iG >= 0; iG--) {
750
+ dist2 = dist1;
751
+ xx2 = inB;
752
+ for (iB = BOX_B_ELEMS - 1; iB >= 0; iB--) {
753
+ if (dist2 < *bptr) {
754
+ *bptr = dist2;
755
+ *cptr = icolor;
756
+ }
757
+ dist2 += xx2;
758
+ xx2 += 2 * STEP_B * STEP_B;
759
+ bptr++;
760
+ cptr++;
761
+ }
762
+ dist1 += xx1;
763
+ xx1 += 2 * STEP_G * STEP_G;
764
+ }
765
+ dist0 += xx0;
766
+ xx0 += 2 * STEP_R * STEP_R;
767
+ }
768
+ }
769
+ }
770
+
771
+ static void fill_inverse_cmap_rgb(quantobj, histogram, R, G, B)
772
+ QuantizeObj *quantobj;
773
+ Histogram histogram;
774
+ int R;
775
+ int G;
776
+ int B;
777
+ /* Fill the inverse-colormap entries in the update box that contains
778
+ histogram cell R/G/B. (Only that one cell MUST be filled, but
779
+ we can fill as many others as we wish.) */
780
+ {
781
+ int minR, minG, minB; /* lower left corner of update box */
782
+ int iR, iG, iB;
783
+ int *cptr; /* pointer into bestcolor[] array */
784
+ ColorFreq *cachep; /* pointer into main cache array */
785
+ /* This array lists the candidate colormap indexes. */
786
+ int colorlist[MAXNUMCOLORS];
787
+ int numcolors; /* number of candidate colors */
788
+ /* This array holds the actually closest colormap index for each cell. */
789
+ int bestcolor[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS];
790
+
791
+ /* Convert cell coordinates to update box ID */
792
+ R >>= BOX_R_LOG;
793
+ G >>= BOX_G_LOG;
794
+ B >>= BOX_B_LOG;
795
+
796
+ /* Compute true coordinates of update box's origin corner.
797
+ * Actually we compute the coordinates of the center of the corner
798
+ * histogram cell, which are the lower bounds of the volume we care about.
799
+ */
800
+ minR = (R << BOX_R_SHIFT) + ((1 << R_SHIFT) >> 1);
801
+ minG = (G << BOX_G_SHIFT) + ((1 << G_SHIFT) >> 1);
802
+ minB = (B << BOX_B_SHIFT) + ((1 << B_SHIFT) >> 1);
803
+
804
+ /* Determine which colormap entries are close enough to be candidates
805
+ * for the nearest entry to some cell in the update box.
806
+ */
807
+ numcolors = find_nearby_colors(quantobj, minR, minG, minB, colorlist);
808
+
809
+ /* Determine the actually nearest colors. */
810
+ find_best_colors(quantobj, minR, minG, minB, numcolors, colorlist,
811
+ bestcolor);
812
+
813
+ /* Save the best color numbers (plus 1) in the main cache array */
814
+ R <<= BOX_R_LOG; /* convert ID back to base cell indexes */
815
+ G <<= BOX_G_LOG;
816
+ B <<= BOX_B_LOG;
817
+ cptr = bestcolor;
818
+ for (iR = 0; iR < BOX_R_ELEMS; iR++) {
819
+ for (iG = 0; iG < BOX_G_ELEMS; iG++) {
820
+ cachep = &histogram[(R + iR) * MR + (G + iG) * MG + B];
821
+ for (iB = 0; iB < BOX_B_ELEMS; iB++) {
822
+ *cachep++ = (*cptr++) + 1;
823
+ }
824
+ }
825
+ }
826
+ }
827
+
828
+ /* This is pass 1 */
829
+ static void median_cut_pass1_rgb(quantobj, src, dest, width, height)
830
+ QuantizeObj *quantobj;
831
+ unsigned char *src;
832
+ unsigned char *dest;
833
+ long width;
834
+ long height;
835
+ {
836
+ generate_histogram_rgb(quantobj->histogram, src, width, height);
837
+ select_colors_rgb(quantobj, quantobj->histogram);
838
+ }
839
+
840
+
841
+ /* Map some rows of pixels to the output colormapped representation. */
842
+ static void median_cut_pass2_no_dither_rgb(quantobj, src, dest, width, height)
843
+ QuantizeObj *quantobj;
844
+ unsigned char *src;
845
+ unsigned char *dest;
846
+ long width;
847
+ long height;
848
+ /* This version performs no dithering */
849
+ {
850
+ Histogram histogram = quantobj->histogram;
851
+ ColorFreq *cachep;
852
+ int R, G, B;
853
+ int row, col;
854
+
855
+ zero_histogram_rgb(histogram);
856
+ for (row = 0; row < height; row++) {
857
+ for (col = 0; col < width; col++) {
858
+ /* get pixel value and index into the cache */
859
+ R = (*src++) >> R_SHIFT;
860
+ G = (*src++) >> G_SHIFT;
861
+ B = (*src++) >> B_SHIFT;
862
+ cachep = &histogram[R * MR + G * MG + B];
863
+ /* If we have not seen this color before, find nearest colormap entry
864
+ and update the cache */
865
+ if (*cachep == 0)
866
+ fill_inverse_cmap_rgb(quantobj, histogram, R, G, B);
867
+ /* Now emit the colormap index for this cell */
868
+ *dest++ = *cachep - 1;
869
+ }
870
+
871
+ }
872
+ }
873
+
874
+ /*
875
+ Initialize the error-limiting transfer function (lookup table).
876
+ The raw F-S error computation can potentially compute error values of up to
877
+ +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be
878
+ much less, otherwise obviously wrong pixels will be created. (Typical
879
+ effects include weird fringes at color-area boundaries, isolated bright
880
+ pixels in a dark area, etc.) The standard advice for avoiding this problem
881
+ is to ensure that the "corners" of the color cube are allocated as output
882
+ colors; then repeated errors in the same direction cannot cause cascading
883
+ error buildup. However, that only prevents the error from getting
884
+ completely out of hand; Aaron Giles reports that error limiting improves
885
+ the results even with corner colors allocated.
886
+
887
+ A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
888
+ well, but the smoother transfer function used below is even better. Thanks
889
+ to Aaron Giles for this idea.
890
+ */
891
+
892
+ static int *init_error_limit()
893
+ /* Allocate and fill in the error_limiter table */
894
+ {
895
+ int *table;
896
+ int in, out;
897
+
898
+ table = malloc((255 * 2 + 1) * sizeof(int));
899
+ if (!table) error("could not alloc mem");
900
+ table += 255; /* so we can index -255 ... +255 */
901
+
902
+ #define STEPSIZE 16
903
+
904
+ /* Map errors 1:1 up to +- 16 */
905
+ out = 0;
906
+ for (in = 0; in < STEPSIZE; in++, out++) {
907
+ table[in] = out;
908
+ table[-in] = -out;
909
+ }
910
+
911
+ /* Map errors 1:2 up to +- 3*16 */
912
+ for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) {
913
+ table[in] = out;
914
+ table[-in] = -out;
915
+ }
916
+
917
+ /* Clamp the rest to final out value (which is 32) */
918
+ for (; in <= 255; in++) {
919
+ table[in] = out;
920
+ table[-in] = -out;
921
+ }
922
+
923
+ #undef STEPSIZE
924
+
925
+ return table;
926
+ }
927
+
928
+
929
+ /* Map some rows of pixels to the output colormapped representation.
930
+ Perform floyd-steinberg dithering. */
931
+ static void median_cut_pass2_fs_dither_rgb(quantobj, src, dest, width, height)
932
+ QuantizeObj *quantobj;
933
+ unsigned char *src;
934
+ unsigned char *dest;
935
+ long width;
936
+ long height;
937
+ {
938
+ Histogram histogram = quantobj->histogram;
939
+ ColorFreq *cachep;
940
+ Color *color;
941
+ unsigned char *src_row;
942
+ unsigned char *dest_row;
943
+ int *error_limiter;
944
+ short *fs_err1, *fs_err2;
945
+ short *fs_err3, *fs_err4;
946
+ int *red_n_row, *red_p_row;
947
+ int *grn_n_row, *grn_p_row;
948
+ int *blu_n_row, *blu_p_row;
949
+ int *rnr, *rpr;
950
+ int *gnr, *gpr;
951
+ int *bnr, *bpr;
952
+ int *tmp;
953
+ int r, g, b;
954
+ int re, ge, be;
955
+ int row, col;
956
+ int index;
957
+ int rowstride;
958
+ int step_dest, step_src;
959
+ int odd_row;
960
+ // short *range_limiter;
961
+ unsigned char *range_limiter;
962
+
963
+ zero_histogram_rgb(histogram);
964
+
965
+ error_limiter = init_error_limit();
966
+ range_limiter = range_array + 256;
967
+
968
+ red_n_row = malloc(sizeof(int) * (width + 2));
969
+ if (!red_n_row) error("could not alloc mem");
970
+ red_p_row = malloc(sizeof(int) * (width + 2));
971
+ if (!red_p_row) error("could not alloc mem");
972
+ grn_n_row = malloc(sizeof(int) * (width + 2));
973
+ if (!grn_n_row) error("could not alloc mem");
974
+ grn_p_row = malloc(sizeof(int) * (width + 2));
975
+ if (!grn_p_row) error("could not alloc mem");
976
+ blu_n_row = malloc(sizeof(int) * (width + 2));
977
+ if (!blu_n_row) error("could not alloc mem");
978
+ blu_p_row = malloc(sizeof(int) * (width + 2));
979
+ if (!blu_p_row) error("could not alloc mem");
980
+
981
+ memset(red_p_row, 0, sizeof(int) * (width + 2) );
982
+ memset(grn_p_row, 0, sizeof(int) * (width + 2));
983
+ memset(blu_p_row, 0, sizeof(int) * (width + 2));
984
+
985
+ fs_err1 = floyd_steinberg_error1 + 511;
986
+ fs_err2 = floyd_steinberg_error2 + 511;
987
+ fs_err3 = floyd_steinberg_error3 + 511;
988
+ fs_err4 = floyd_steinberg_error4 + 511;
989
+
990
+ src_row = src;
991
+ dest_row = dest;
992
+ rowstride = width * 3;
993
+ odd_row = 0;
994
+
995
+ for (row = 0; row < height; row++) {
996
+ src = src_row;
997
+ dest = dest_row;
998
+
999
+ src_row += rowstride;
1000
+ dest_row += width;
1001
+
1002
+ rnr = red_n_row;
1003
+ gnr = grn_n_row;
1004
+ bnr = blu_n_row;
1005
+ rpr = red_p_row + 1;
1006
+ gpr = grn_p_row + 1;
1007
+ bpr = blu_p_row + 1;
1008
+
1009
+ if (odd_row) {
1010
+ step_dest = -1;
1011
+ step_src = -3;
1012
+
1013
+ src += rowstride - 3;
1014
+ dest += width - 1;
1015
+
1016
+ rnr += width + 1;
1017
+ gnr += width + 1;
1018
+ bnr += width + 1;
1019
+ rpr += width;
1020
+ gpr += width;
1021
+ bpr += width;
1022
+
1023
+ *(rnr - 1) = *(gnr - 1) = *(bnr - 1) = 0;
1024
+ } else {
1025
+ step_dest = 1;
1026
+ step_src = 3;
1027
+
1028
+ *(rnr + 1) = *(gnr + 1) = *(bnr + 1) = 0;
1029
+ }
1030
+
1031
+ *rnr = *gnr = *bnr = 0;
1032
+
1033
+ for (col = 0; col < width; col++) {
1034
+ r = range_limiter[src[0] + error_limiter[*rpr]];
1035
+ g = range_limiter[src[1] + error_limiter[*gpr]];
1036
+ b = range_limiter[src[2] + error_limiter[*bpr]];
1037
+
1038
+ re = r >> R_SHIFT;
1039
+ ge = g >> G_SHIFT;
1040
+ be = b >> B_SHIFT;
1041
+
1042
+ cachep = &histogram[re * MR + ge * MG + be];
1043
+ /* If we have not seen this color before,
1044
+ find nearest colormap entry
1045
+ and update the cache */
1046
+ if (*cachep == 0)
1047
+ fill_inverse_cmap_rgb(quantobj, histogram, re, ge, be);
1048
+
1049
+ index = *cachep - 1;
1050
+ *dest = index;
1051
+
1052
+ color = &quantobj->cmap[index];
1053
+ re = r - color->red;
1054
+ ge = g - color->green;
1055
+ be = b - color->blue;
1056
+
1057
+ if (odd_row) {
1058
+ *(--rpr) += fs_err1[re];
1059
+ *(--gpr) += fs_err1[ge];
1060
+ *(--bpr) += fs_err1[be];
1061
+
1062
+ *rnr-- += fs_err2[re];
1063
+ *gnr-- += fs_err2[ge];
1064
+ *bnr-- += fs_err2[be];
1065
+
1066
+ *rnr += fs_err3[re];
1067
+ *gnr += fs_err3[ge];
1068
+ *bnr += fs_err3[be];
1069
+
1070
+ *(rnr - 1) = fs_err4[re];
1071
+ *(gnr - 1) = fs_err4[ge];
1072
+ *(bnr - 1) = fs_err4[be];
1073
+ } else {
1074
+ *(++rpr) += fs_err1[re];
1075
+ *(++gpr) += fs_err1[ge];
1076
+ *(++bpr) += fs_err1[be];
1077
+
1078
+ *rnr++ += fs_err2[re];
1079
+ *gnr++ += fs_err2[ge];
1080
+ *bnr++ += fs_err2[be];
1081
+
1082
+ *rnr += fs_err3[re];
1083
+ *gnr += fs_err3[ge];
1084
+ *bnr += fs_err3[be];
1085
+
1086
+ *(rnr + 1) = fs_err4[re];
1087
+ *(gnr + 1) = fs_err4[ge];
1088
+ *(bnr + 1) = fs_err4[be];
1089
+ }
1090
+
1091
+ dest += step_dest;
1092
+ src += step_src;
1093
+ }
1094
+
1095
+ tmp = red_n_row;
1096
+ red_n_row = red_p_row;
1097
+ red_p_row = tmp;
1098
+
1099
+ tmp = grn_n_row;
1100
+ grn_n_row = grn_p_row;
1101
+ grn_p_row = tmp;
1102
+
1103
+ tmp = blu_n_row;
1104
+ blu_n_row = blu_p_row;
1105
+ blu_p_row = tmp;
1106
+
1107
+ odd_row = !odd_row;
1108
+
1109
+ }
1110
+
1111
+ xfree(error_limiter - 255);
1112
+ xfree(red_n_row);
1113
+ xfree(red_p_row);
1114
+ xfree(grn_n_row);
1115
+ xfree(grn_p_row);
1116
+ xfree(blu_n_row);
1117
+ xfree(blu_p_row);
1118
+ }
1119
+
1120
+ static QuantizeObj *initialize_median_cut(int num_colors, int dither_type)
1121
+ {
1122
+ QuantizeObj *quantobj;
1123
+
1124
+ /* Initialize the data structures */
1125
+ quantobj = malloc(sizeof(QuantizeObj));
1126
+ if (!quantobj) error("could not alloc mem");
1127
+
1128
+ quantobj->histogram = malloc(sizeof(ColorFreq) *
1129
+ HIST_R_ELEMS *
1130
+ HIST_G_ELEMS *
1131
+ HIST_B_ELEMS);
1132
+ if (!quantobj->histogram) error("could not alloc mem");
1133
+
1134
+ quantobj->desired_number_of_colors = num_colors;
1135
+ quantobj->first_pass = median_cut_pass1_rgb;
1136
+
1137
+ switch (dither_type) {
1138
+ case NODITHER:
1139
+ quantobj->second_pass = median_cut_pass2_no_dither_rgb;
1140
+ break;
1141
+ case FSDITHER:
1142
+ quantobj->second_pass = median_cut_pass2_fs_dither_rgb;
1143
+ break;
1144
+ }
1145
+
1146
+ return quantobj;
1147
+ }
1148
+
1149
+ ///* Externs: */
1150
+ //extern unsigned char *Picture256;
1151
+ //extern unsigned char QuantizedPalette[768];
1152
+
1153
+ //void to_indexed(char*input,long ncolors,long dither,int width,int height)
1154
+ void to_indexed(char*input,long ncolors,long dither,int width,int height,
1155
+ unsigned char *Picture256, unsigned char *QuantizedPalette)
1156
+ {
1157
+ QuantizeObj *quantobj;
1158
+ int i, j;
1159
+
1160
+ quantobj = initialize_median_cut(ncolors, dither ? FSDITHER : NODITHER);
1161
+ (*quantobj->first_pass) (quantobj, input, Picture256, width, height);
1162
+ (*quantobj->second_pass) (quantobj, input, Picture256, width, height);
1163
+ for (i = 0, j = 0; i < quantobj->actual_number_of_colors; i++) {
1164
+ //#if 0
1165
+ // rgb
1166
+ QuantizedPalette[j++] = quantobj->cmap[i].red;
1167
+ QuantizedPalette[j++] = quantobj->cmap[i].green;
1168
+ QuantizedPalette[j++] = quantobj->cmap[i].blue;
1169
+ //#else
1170
+ // bgr
1171
+ // QuantizedPalette[j++] = quantobj->cmap[i].blue;
1172
+ // QuantizedPalette[j++] = quantobj->cmap[i].green;
1173
+ // QuantizedPalette[j++] = quantobj->cmap[i].red;
1174
+ //#endif
1175
+ }
1176
+ xfree(quantobj->histogram);
1177
+ xfree(quantobj);
1178
+ }
1179
+ /*-*/