pikl 0.2.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/History.txt +9 -0
  2. data/License.txt +0 -0
  3. data/Manifest.txt +17 -17
  4. data/README.txt +0 -0
  5. data/config/hoe.rb +9 -6
  6. data/config/requirements.rb +0 -0
  7. data/ext/pikl/extconf.rb +0 -0
  8. data/ext/pikl/pikl.h +617 -465
  9. data/ext/pikl/pikl_affine.c +38 -91
  10. data/ext/pikl/pikl_affine.h +0 -0
  11. data/ext/pikl/pikl_bitmap.c +0 -0
  12. data/ext/pikl/pikl_bitmap.h +0 -0
  13. data/ext/pikl/pikl_blur.c +4 -8
  14. data/ext/pikl/pikl_blur.h +0 -0
  15. data/ext/pikl/pikl_camera.c +218 -0
  16. data/ext/pikl/{pikl_effect3.h → pikl_camera.h} +2 -2
  17. data/ext/pikl/pikl_composite.c +175 -0
  18. data/ext/pikl/pikl_composite.h +12 -0
  19. data/ext/pikl/pikl_decrease.c +110 -45
  20. data/ext/pikl/pikl_decrease.h +0 -7
  21. data/ext/pikl/pikl_divide.c +116 -0
  22. data/ext/pikl/pikl_divide.h +11 -0
  23. data/ext/pikl/pikl_effect.c +583 -151
  24. data/ext/pikl/pikl_effect.h +32 -6
  25. data/ext/pikl/pikl_enhance.c +274 -0
  26. data/ext/pikl/pikl_enhance.h +20 -0
  27. data/ext/pikl/pikl_io.c +174 -23
  28. data/ext/pikl/pikl_io.h +0 -0
  29. data/ext/pikl/pikl_jpeg.c +0 -0
  30. data/ext/pikl/pikl_jpeg.h +0 -0
  31. data/ext/pikl/pikl_pattern.c +383 -357
  32. data/ext/pikl/pikl_pattern.h +0 -0
  33. data/ext/pikl/pikl_pixel.c +173 -0
  34. data/ext/pikl/{pikl_trim.h → pikl_pixel.h} +2 -2
  35. data/ext/pikl/pikl_png.c +0 -0
  36. data/ext/pikl/pikl_png.h +0 -0
  37. data/ext/pikl/pikl_private.h +12 -5
  38. data/ext/pikl/pikl_resize.c +0 -0
  39. data/ext/pikl/pikl_resize.h +0 -0
  40. data/ext/pikl/pikl_rotate.c +409 -51
  41. data/ext/pikl/pikl_rotate.h +8 -0
  42. data/ext/pikl/pikl_scrap.c +263 -483
  43. data/ext/pikl/pikl_scrap.h +0 -0
  44. data/ext/pikl/pikl_special.c +168 -0
  45. data/ext/pikl/{pikl_effect4.h → pikl_special.h} +2 -2
  46. data/ext/pikl/pikl_voronoi.c +320 -0
  47. data/ext/pikl/pikl_voronoi.h +37 -0
  48. data/lib/pikl.rb +4 -2
  49. data/lib/pikl/color.rb +47 -0
  50. data/lib/pikl/const.rb +106 -22
  51. data/lib/pikl/errors.rb +0 -0
  52. data/lib/pikl/ext.rb +115 -8
  53. data/lib/pikl/filter.rb +371 -0
  54. data/lib/pikl/image.rb +124 -117
  55. data/lib/pikl/version.rb +2 -2
  56. data/setup.rb +0 -0
  57. data/test/sample.jpg +0 -0
  58. data/test/test_helper.rb +0 -0
  59. data/test/test_pikl_image.rb +0 -14
  60. data/test/test_pikl_image2.rb +541 -0
  61. metadata +35 -23
  62. data/ext/pikl/decrease/fsdither.h +0 -554
  63. data/ext/pikl/decrease/median.c +0 -1179
  64. data/ext/pikl/decrease/median.h +0 -7
  65. data/ext/pikl/decrease/neuquan5.c +0 -563
  66. data/ext/pikl/decrease/neuquant.h +0 -62
  67. data/ext/pikl/decrease/wu.c +0 -447
  68. data/ext/pikl/decrease/wu.h +0 -7
  69. data/ext/pikl/pikl_effect2.c +0 -240
  70. data/ext/pikl/pikl_effect2.h +0 -55
  71. data/ext/pikl/pikl_effect3.c +0 -266
  72. data/ext/pikl/pikl_effect4.c +0 -495
  73. data/ext/pikl/pikl_rotate2.c +0 -312
  74. data/ext/pikl/pikl_rotate2.h +0 -19
  75. data/ext/pikl/pikl_trim.c +0 -28
@@ -1,1179 +0,0 @@
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
- /*-*/