1 /* quant.c - provides general image quantization
2 currently only used by gif.c, but maybe we'll support producing
3 8-bit (or bigger indexed) png files at some point
8 static void makemap_webmap(i_quantize *);
9 static void makemap_addi(i_quantize *, i_img **imgs, int count);
10 static void makemap_mediancut(i_quantize *, i_img **imgs, int count);
11 static void makemap_mono(i_quantize *);
12 static void makemap_gray(i_quantize *, int step);
14 static int makemap_palette(i_quantize *, i_img **imgs, int count);
18 setcol(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
27 /* make a colour map overwrites mc_existing/mc_count in quant Note
28 that i_makemap will be called once for each image if mc_perimage is
29 set and the format support multiple colour maps per image.
31 This means we don't need any special processing at this level to
32 handle multiple colour maps.
36 =item i_quant_makemap(C<quant>, C<imgs>, C<count>)
38 =category Image quantization
40 Analyzes the C<count> images in C<imgs> according to the rules in
41 C<quant> to build a color map (optimal or not depending on
42 C<< quant->make_colors >>).
48 i_quant_makemap(i_quantize *quant, i_img **imgs, int count) {
50 if (quant->translate == pt_giflib) {
51 /* giflib does it's own color table generation */
52 /* previously we used giflib's quantizer, but it didn't handle multiple
53 images, which made it hard to build a global color map
54 We've implemented our own median cut code so we can ignore
56 makemap_mediancut(quant, imgs, count);
60 switch (quant->make_colors & mc_mask) {
62 /* use user's specified map */
65 makemap_webmap(quant);
69 makemap_mediancut(quant, imgs, count);
77 makemap_gray(quant, 1);
81 makemap_gray(quant, 85);
85 makemap_gray(quant, 17);
90 makemap_addi(quant, imgs, count);
95 static void translate_closest(i_quantize *, i_img *, i_palidx *);
96 static int translate_errdiff(i_quantize *, i_img *, i_palidx *);
97 static void translate_addi(i_quantize *, i_img *, i_palidx *);
100 =item i_quant_translate(C<quant>, C<img>)
102 =category Image quantization
104 Quantize the image given the palette in C<quant>.
106 On success returns a pointer to a memory block of C<< img->xsize *
107 img->ysize >> C<i_palidx> entries.
109 On failure returns NULL.
111 You should call myfree() on the returned block when you're done with
114 This function will fail if the supplied palette contains no colors.
119 i_quant_translate(i_quantize *quant, i_img *img) {
123 mm_log((1, "quant_translate(quant %p, img %p)\n", quant, img));
125 /* there must be at least one color in the paletted (though even that
127 if (quant->mc_count == 0) {
128 i_push_error(0, "no colors available for translation");
132 bytes = img->xsize * img->ysize;
133 if (bytes / img->ysize != img->xsize) {
134 i_push_error(0, "integer overflow calculating memory allocation");
137 result = mymalloc(bytes);
139 switch (quant->translate) {
142 translate_closest(quant, img, result);
146 if (!translate_errdiff(quant, img, result)) {
154 translate_addi(quant, img, result);
161 static void translate_closest(i_quantize *quant, i_img *img, i_palidx *out) {
163 translate_addi(quant, img, out);
166 #define PWR2(x) ((x)*(x))
168 typedef int (*cmpfunc)(const void*, const void*);
191 static void prescan(i_img **im,int count, int cnum, cvec *clr, i_sample_t *line);
192 static void reorder(pbox prescan[512]);
193 static int pboxcmp(const pbox *a,const pbox *b);
194 static void boxcenter(int box,cvec *cv);
195 static float frandn(void);
196 static void boxrand(int box,cvec *cv);
197 static void bbox(int box,int *r0,int *r1,int *g0,int *g1,int *b0,int *b1);
198 static void cr_hashindex(cvec clr[256],int cnum,hashbox hb[512]);
199 static int mindist(int boxnum,cvec *cv);
200 static int maxdist(int boxnum,cvec *cv);
202 /* Some of the simpler functions are kept here to aid the compiler -
203 maybe some of them will be inlined. */
206 pixbox(i_color *ic) { return ((ic->channel[0] & 224)<<1)+ ((ic->channel[1]&224)>>2) + ((ic->channel[2] &224) >> 5); }
209 pixbox_ch(i_sample_t *chans) { return ((chans[0] & 224)<<1)+ ((chans[1]&224)>>2) + ((chans[2] &224) >> 5); }
213 if (in>255) { return 255; }
214 else if (in>0) return in;
221 return rand()/(RAND_MAX+1.0);
227 eucl_d(cvec* cv,i_color *cl) { return PWR2(cv->r-cl->channel[0])+PWR2(cv->g-cl->channel[1])+PWR2(cv->b-cl->channel[2]); }
232 eucl_d_ch(cvec* cv,i_sample_t *chans) {
233 return PWR2(cv->r - chans[0]) + PWR2(cv->g - chans[1])
234 + PWR2(cv->b - chans[2]);
238 ceucl_d(i_color *c1, i_color *c2) {
239 return PWR2(c1->channel[0]-c2->channel[0])
240 +PWR2(c1->channel[1]-c2->channel[1])
241 +PWR2(c1->channel[2]-c2->channel[2]);
245 gray_samples[] = { 0, 0, 0 };
249 This quantization algorithm and implementation routines are by Arnar
250 M. Hrafnkelson. In case any new ideas are here they are mine since
251 this was written from scratch.
253 The algorithm uses local means in the following way:
255 For each point in the colormap we find which image points
256 have that point as it's closest point. We calculate the mean
257 of those points and in the next iteration it will be the new
258 entry in the colormap.
260 In order to speed this process up (i.e. nearest neighbor problem) We
261 divied the r,g,b space up in equally large 512 boxes. The boxes are
262 numbered from 0 to 511. Their numbering is so that for a given vector
263 it is known that it belongs to the box who is formed by concatenating the
264 3 most significant bits from each component of the RGB triplet.
266 For each box we find the list of points from the colormap who might be
267 closest to any given point within the box. The exact solution
268 involves finding the Voronoi map (or the dual the Delauny
269 triangulation) and has many issues including numerical stability.
271 So we use this approximation:
273 1. Find which point has the shortest maximum distance to the box.
274 2. Find all points that have a shorter minimum distance than that to the box
276 This is a very simple task and is not computationally heavy if one
277 takes into account that the minimum distances from a pixel to a box is
278 always found by checking if it's inside the box or is closest to some
279 side or a corner. Finding the maximum distance is also either a side
282 This approach results 2-3 times more than the actual points needed but
283 is still a good gain over the complete space. Usually when one has a
284 256 Colorcolor map a search over 30 is often obtained.
286 A bit of an enhancement to this approach is to keep a seperate list
287 for each side of the cube, but this will require even more memory.
289 Arnar M. Hrafnkelsson (addi@umich.edu);
293 Extracted from gifquant.c, removed dependencies on gif_lib,
294 and added support for multiple images.
295 starting from 1nov2000 by TonyC <tony@develop-help.com>.
300 makemap_addi(i_quantize *quant, i_img **imgs, int count) {
302 int cnum, i, bst_idx=0, ld, cd, iter, currhb, img_num;
308 i_img_dim maxwidth = 0;
310 const int *sample_indices;
312 mm_log((1, "makemap_addi(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
313 quant, quant->mc_count, quant->mc_colors, imgs, count));
315 if (makemap_palette(quant, imgs, count))
320 clr = i_mempool_alloc(&mp, sizeof(cvec) * quant->mc_size);
321 hb = i_mempool_alloc(&mp, sizeof(hashbox) * 512);
322 for (i=0; i < quant->mc_count; ++i) {
323 clr[i].r = quant->mc_colors[i].rgb.r;
324 clr[i].g = quant->mc_colors[i].rgb.g;
325 clr[i].b = quant->mc_colors[i].rgb.b;
329 /* mymalloc doesn't clear memory, so I think we need this */
330 for (; i < quant->mc_size; ++i) {
331 /*clr[i].r = clr[i].g = clr[i].b = 0;*/
338 cnum = quant->mc_size;
341 for (img_num = 0; img_num < count; ++img_num) {
342 if (imgs[img_num]->xsize > maxwidth)
343 maxwidth = imgs[img_num]->xsize;
345 line = i_mempool_alloc(&mp, 3 * maxwidth * sizeof(*line));
347 prescan(imgs, count, cnum, clr, line);
348 cr_hashindex(clr, cnum, hb);
350 for(iter=0;iter<3;iter++) {
353 for (img_num = 0; img_num < count; ++img_num) {
354 i_img *im = imgs[img_num];
355 sample_indices = im->channels >= 3 ? NULL : gray_samples;
356 for(y=0;y<im->ysize;y++) {
357 i_gsamp(im, 0, im->xsize, y, line, sample_indices, 3);
359 for(x=0;x<im->xsize;x++) {
361 /*i_gpix(im,x,y,&val);*/
362 currhb=pixbox_ch(val);
363 /* printf("box = %d \n",currhb); */
364 for(i=0;i<hb[currhb].cnt;i++) {
365 /* printf("comparing: pix (%d,%d,%d) vec (%d,%d,%d)\n",val.channel[0],val.channel[1],val.channel[2],clr[hb[currhb].vec[i]].r,clr[hb[currhb].vec[i]].g,clr[hb[currhb].vec[i]].b); */
367 cd=eucl_d_ch(&clr[hb[currhb].vec[i]],val);
369 ld=cd; /* shortest distance yet */
370 bst_idx=hb[currhb].vec[i]; /* index of closest vector yet */
374 clr[bst_idx].mcount++;
376 clr[bst_idx].dr+=val[0];
377 clr[bst_idx].dg+=val[1];
378 clr[bst_idx].db+=val[2];
380 val += 3; /* next 3 samples (next pixel) */
387 clr[i].dr/=clr[i].mcount;
388 clr[i].dg/=clr[i].mcount;
389 clr[i].db/=clr[i].mcount;
392 /* for(i=0;i<cnum;i++) printf("vec(%d)=(%d,%d,%d) dest=(%d,%d,%d) matchcount=%d\n",
393 i,clr[i].r,clr[i].g,clr[i].b,clr[i].dr,clr[i].dg,clr[i].db,clr[i].mcount); */
395 /* printf("total error: %.2f\n",sqrt(accerr)); */
397 for(i=0;i<cnum;i++) {
398 if (clr[i].fixed) continue; /* skip reserved colors */
402 clr[i].r=clr[i].r*(1-dlt)+dlt*clr[i].dr;
403 clr[i].g=clr[i].g*(1-dlt)+dlt*clr[i].dg;
404 clr[i].b=clr[i].b*(1-dlt)+dlt*clr[i].db;
406 /* let's try something else */
418 cr_hashindex(clr,cnum,hb);
423 for(i=0;i<cnum;i++) {
424 cd=eucl_d(&clr[i],&val);
432 /* if defined, we only include colours with an mcount or that were
433 supplied in the fixed palette, giving us a smaller output palette */
434 #define ONLY_USE_USED
436 /* transfer the colors back */
438 for (i = 0; i < cnum; ++i) {
439 if (clr[i].fixed || clr[i].used) {
440 /*printf("Adding %d (%d,%d,%d)\n", i, clr[i].r, clr[i].g, clr[i].b);*/
441 quant->mc_colors[quant->mc_count].rgb.r = clr[i].r;
442 quant->mc_colors[quant->mc_count].rgb.g = clr[i].g;
443 quant->mc_colors[quant->mc_count].rgb.b = clr[i].b;
448 /* transfer the colors back */
449 for (i = 0; i < cnum; ++i) {
450 quant->mc_colors[i].rgb.r = clr[i].r;
451 quant->mc_colors[i].rgb.g = clr[i].g;
452 quant->mc_colors[i].rgb.b = clr[i].b;
454 quant->mc_count = cnum;
458 mm_log((1, "makemap_addi returns - quant.mc_count = %d\n", quant->mc_count));
459 for (i = 0; i < quant->mc_count; ++i)
460 mm_log((5, " map entry %d: (%d, %d, %d)\n", i, clr[i].r, clr[i].g, clr[i].b));
463 i_mempool_destroy(&mp);
465 mm_log((1, "makemap_addi() - %d colors\n", quant->mc_count));
473 #define MEDIAN_CUT_COLORS 32768
475 #define MED_CUT_INDEX(c) ((((c).rgb.r & 0xF8) << 7) | \
476 (((c).rgb.g & 0xF8) << 2) | (((c).rgb.b & 0xF8) >> 3))
478 #define MED_CUT_GRAY_INDEX(c) ((((c).rgb.r & 0xF8) << 7) | \
479 (((c).rgb.r & 0xF8) << 2) | (((c).rgb.r & 0xF8) >> 3))
481 /* scale these to cover the whole range */
482 #define MED_CUT_RED(index) ((((index) & 0x7C00) >> 10) * 255 / 31)
483 #define MED_CUT_GREEN(index) ((((index) & 0x3E0) >> 5) * 255 / 31)
484 #define MED_CUT_BLUE(index) (((index) & 0x1F) * 255 / 31)
487 i_sample_t min[3]; /* minimum for each channel */
488 i_sample_t max[3]; /* maximum for each channel */
489 i_sample_t width[3]; /* width for each channel */
490 int start, size; /* beginning and size of the partition */
491 i_img_dim pixels; /* number of pixels represented by this partition */
495 =item calc_part(part, colors)
497 Calculates the new color limits for the given partition.
499 Giflib assumes that the limits for the non-split channels stay the
500 same, but this strikes me as incorrect, especially if the colors tend
503 Of course this could be optimized by not recalculating the channel we
504 just sorted on, but it's not worth the effort right now.
508 static void calc_part(medcut_partition *part, quant_color_entry *colors) {
511 for (ch = 0; ch < 3; ++ch) {
515 for (i = part->start; i < part->start + part->size; ++i) {
516 for (ch = 0; ch < 3; ++ch) {
517 if (part->min[ch] > colors[i].rgb[ch])
518 part->min[ch] = colors[i].rgb[ch];
519 if (part->max[ch] < colors[i].rgb[ch])
520 part->max[ch] = colors[i].rgb[ch];
523 for (ch = 0; ch < 3; ++ch) {
524 part->width[ch] = part->max[ch] - part->min[ch];
528 /* simple functions to sort by each channel - we could use a global, but
532 color_sort_red(void const *left, void const *right) {
533 return ((quant_color_entry *)left)->rgb[0] - ((quant_color_entry *)right)->rgb[0];
537 color_sort_green(void const *left, void const *right) {
538 return ((quant_color_entry *)left)->rgb[1] - ((quant_color_entry *)right)->rgb[1];
542 color_sort_blue(void const *left, void const *right) {
543 return ((quant_color_entry *)left)->rgb[2] - ((quant_color_entry *)right)->rgb[2];
546 static int (*sorters[])(void const *, void const *) =
554 makemap_mediancut(i_quantize *quant, i_img **imgs, int count) {
555 quant_color_entry *colors;
558 i_img_dim x, y, max_width;
561 i_img_dim total_pixels;
562 medcut_partition *parts;
565 /* number of channels we search for the best channel to partition
566 this isn't terribly efficient, but it should work */
569 mm_log((1, "makemap_mediancut(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
570 quant, quant->mc_count, quant->mc_colors, imgs, count));
572 if (makemap_palette(quant, imgs, count))
577 colors = i_mempool_alloc(&mp, sizeof(*colors) * MEDIAN_CUT_COLORS);
578 for (i = 0; i < MEDIAN_CUT_COLORS; ++i) {
579 colors[i].rgb[0] = MED_CUT_RED(i);
580 colors[i].rgb[1] = MED_CUT_GREEN(i);
581 colors[i].rgb[2] = MED_CUT_BLUE(i);
586 for (imgn = 0; imgn < count; ++imgn) {
587 if (imgs[imgn]->xsize > max_width)
588 max_width = imgs[imgn]->xsize;
590 line = i_mempool_alloc(&mp, sizeof(i_color) * max_width);
592 /* build the stats */
594 chan_count = 1; /* assume we just have grayscale */
595 for (imgn = 0; imgn < count; ++imgn) {
596 total_pixels += imgs[imgn]->xsize * imgs[imgn]->ysize;
597 for (y = 0; y < imgs[imgn]->ysize; ++y) {
598 i_glin(imgs[imgn], 0, imgs[imgn]->xsize, y, line);
599 if (imgs[imgn]->channels > 2) {
601 for (x = 0; x < imgs[imgn]->xsize; ++x) {
602 ++colors[MED_CUT_INDEX(line[x])].count;
606 /* a gray-scale image, just use the first channel */
607 for (x = 0; x < imgs[imgn]->xsize; ++x) {
608 ++colors[MED_CUT_GRAY_INDEX(line[x])].count;
614 /* eliminate the empty colors */
616 for (in = 0; in < MEDIAN_CUT_COLORS; ++in) {
617 if (colors[in].count) {
618 colors[out++] = colors[in];
621 /*printf("out %d\n", out);
623 for (i = 0; i < out; ++i) {
624 if (colors[i].count) {
625 printf("%d: (%d,%d,%d) -> %d\n", i, colors[i].rgb[0], colors[i].rgb[1],
626 colors[i].rgb[2], colors[i].count);
630 if (out < quant->mc_size) {
631 /* just copy them into the color table */
632 for (i = 0; i < out; ++i) {
633 for (ch = 0; ch < 3; ++ch) {
634 quant->mc_colors[i].channel[ch] = colors[i].rgb[ch];
637 quant->mc_count = out;
640 /* build the starting partition */
641 parts = i_mempool_alloc(&mp, sizeof(*parts) * quant->mc_size);
644 parts[0].pixels = total_pixels;
645 calc_part(parts, colors);
648 while (color_count < quant->mc_size) {
649 /* initialized to avoid compiler warnings */
650 int max_index = 0, max_ch = 0; /* index/channel with biggest spread */
652 medcut_partition *workpart;
656 /* find the partition with the most biggest span with more than
659 for (i = 0; i < color_count; ++i) {
660 for (ch = 0; ch < chan_count; ++ch) {
661 if (parts[i].width[ch] > max_size
662 && parts[i].size > 1) {
665 max_size = parts[i].width[ch];
670 /* nothing else we can split */
674 workpart = parts+max_index;
675 /*printf("splitting partition %d (pixels %ld, start %d, size %d)\n", max_index, workpart->pixels, workpart->start, workpart->size);*/
676 qsort(colors + workpart->start, workpart->size, sizeof(*colors),
679 /* find the median or something like it we need to make sure both
680 sides of the split have at least one color in them, so we don't
681 test at the first or last entry */
683 cum_total = colors[i].count;
685 half = workpart->pixels / 2;
686 while (i < workpart->start + workpart->size - 1
687 && cum_total < half) {
688 cum_total += colors[i++].count;
690 /*printf("Split at %d to make %d (half %ld, cumtotal %ld)\n", i, color_count, half, cum_total);*/
692 /* found the spot to split */
693 parts[color_count].start = i;
694 parts[color_count].size = workpart->start + workpart->size - i;
695 workpart->size = i - workpart->start;
696 parts[color_count].pixels = workpart->pixels - cum_total;
697 workpart->pixels = cum_total;
699 /* recalculate the limits */
700 calc_part(workpart, colors);
701 calc_part(parts+color_count, colors);
705 /* fill in the color table - since we could still have partitions
706 that have more than one color, we need to average the colors */
707 for (part_num = 0; part_num < color_count; ++part_num) {
709 medcut_partition *workpart;
711 workpart = parts+part_num;
712 for (ch = 0; ch < 3; ++ch)
715 for (i = workpart->start; i < workpart->start + workpart->size; ++i) {
716 for (ch = 0; ch < 3; ++ch) {
717 sums[ch] += (int)(colors[i].rgb[ch]) * colors[i].count;
720 for (ch = 0; ch < 3; ++ch) {
721 quant->mc_colors[part_num].channel[ch] = sums[ch] / workpart->pixels;
724 quant->mc_count = color_count;
726 /*printf("out %d colors\n", quant->mc_count);*/
727 i_mempool_destroy(&mp);
729 mm_log((1, "makemap_mediancut() - %d colors\n", quant->mc_count));
733 makemap_mono(i_quantize *quant) {
734 quant->mc_colors[0].rgba.r = 0;
735 quant->mc_colors[0].rgba.g = 0;
736 quant->mc_colors[0].rgba.b = 0;
737 quant->mc_colors[0].rgba.a = 255;
738 quant->mc_colors[1].rgba.r = 255;
739 quant->mc_colors[1].rgba.g = 255;
740 quant->mc_colors[1].rgba.b = 255;
741 quant->mc_colors[1].rgba.a = 255;
746 makemap_gray(i_quantize *quant, int step) {
751 setcol(quant->mc_colors+i, gray, gray, gray, 255);
759 makemap_webmap(i_quantize *quant) {
763 for (r = 0; r < 256; r+=0x33)
764 for (g = 0; g < 256; g+=0x33)
765 for (b = 0; b < 256; b += 0x33)
766 setcol(quant->mc_colors+i++, r, g, b, 255);
771 in_palette(i_color *c, i_quantize *quant, int size) {
774 for (i = 0; i < size; ++i) {
775 if (c->channel[0] == quant->mc_colors[i].channel[0]
776 && c->channel[1] == quant->mc_colors[i].channel[1]
777 && c->channel[2] == quant->mc_colors[i].channel[2]) {
786 =item makemap_palette(quant, imgs, count)
788 Tests if all the given images are paletted and have a common palette,
789 if they do it builds that palette.
791 A possible improvement might be to eliminate unused colors in the
798 makemap_palette(i_quantize *quant, i_img **imgs, int count) {
799 int size = quant->mc_count;
805 mm_log((1, "makemap_palette(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
806 quant, quant->mc_count, quant->mc_colors, imgs, count));
807 /* we try to build a common palette here, if we can manage that, then
808 that's the palette we use */
809 for (imgn = 0; imgn < count; ++imgn) {
810 int eliminate_unused;
811 if (imgs[imgn]->type != i_palette_type) {
812 mm_log((1, "makemap_palette() -> 0 (non-palette image)\n"));
816 if (!i_tags_get_int(&imgs[imgn]->tags, "gif_eliminate_unused", 0,
817 &eliminate_unused)) {
818 eliminate_unused = 1;
821 if (eliminate_unused) {
822 i_palidx *line = mymalloc(sizeof(i_palidx) * imgs[imgn]->xsize);
824 memset(used, 0, sizeof(used));
826 for (y = 0; y < imgs[imgn]->ysize; ++y) {
827 i_gpal(imgs[imgn], 0, imgs[imgn]->xsize, y, line);
828 for (x = 0; x < imgs[imgn]->xsize; ++x)
835 /* assume all are in use */
836 memset(used, 1, sizeof(used));
839 col_count = i_colorcount(imgs[imgn]);
840 for (i = 0; i < col_count; ++i) {
843 i_getcolors(imgs[imgn], i, &c, 1);
845 if (in_palette(&c, quant, size) < 0) {
846 if (size < quant->mc_size) {
847 quant->mc_colors[size++] = c;
850 mm_log((1, "makemap_palette() -> 0 (too many colors)\n"));
858 mm_log((1, "makemap_palette() -> 1 (%d total colors)\n", size));
859 quant->mc_count = size;
866 /* Define one of the following 4 symbols to choose a colour search method
867 The idea is to try these out, including benchmarking, to see which
868 is fastest in a good spread of circumstances.
869 I'd expect IM_CFLINSEARCH to be fastest for very small palettes, and
870 IM_CFHASHBOX for large images with large palettes.
872 Some other possibilities include:
873 - search over entries sorted by luminance
875 Initially I was planning on testing using the macros and then
876 integrating the code directly into each function, but this means if
877 we find a bug at a late stage we will need to update N copies of
878 the same code. Also, keeping the code in the macros means that the
879 code in the translation functions is much more to the point,
880 there's no distracting colour search code to remove attention from
881 what makes _this_ translation function different. It may be
882 advisable to move the setup code into functions at some point, but
883 it should be possible to do this fairly transparently.
885 If IM_CF_COPTS is defined then CFLAGS must have an appropriate
888 Each option needs to define 4 macros:
889 CF_VARS - variables to define in the function
890 CF_SETUP - code to setup for the colour search, eg. allocating and
891 initializing lookup tables
892 CF_FIND - code that looks for the color in val and puts the best
893 matching index in bst_idx
894 CF_CLEANUP - code to clean up, eg. releasing memory
897 /*#define IM_CFLINSEARCH*/
899 /*#define IM_CFSORTCHAN*/
900 /*#define IM_CFRAND2DIST*/
903 /* return true if the color map contains only grays */
905 is_gray_map(const i_quantize *quant) {
908 for (i = 0; i < quant->mc_count; ++i) {
909 if (quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.g
910 || quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.b) {
911 mm_log((1, " not a gray map\n"));
916 mm_log((1, " is a gray map\n"));
922 /* The original version I wrote for this used the sort.
923 If this is defined then we use a sort to extract the indices for
927 /* assume i is available */
928 #define CF_VARS hashbox *hb = mymalloc(sizeof(hashbox) * 512); \
934 static long *gdists; /* qsort is annoying */
935 /* int might be smaller than long, so we need to do a real compare
936 rather than a subtraction*/
937 static int distcomp(void const *a, void const *b) {
938 long ra = gdists[*(int const *)a];
939 long rb = gdists[*(int const *)b];
950 /* for each hashbox build a list of colours that are in the hb or is closer
952 This is pretty involved. The original gifquant generated the hashbox
953 as part of it's normal processing, but since the map generation is now
954 separated from the translation we need to do this on the spot.
955 Any optimizations, even if they don't produce perfect results would be
958 static void hbsetup(i_quantize *quant, hashbox *hb) {
959 long *dists, mind, maxd;
960 int cr, cb, cg, hbnum, i;
963 int *indices = mymalloc(quant->mc_count * sizeof(int));
966 dists = mymalloc(quant->mc_count * sizeof(long));
967 for (cr = 0; cr < 8; ++cr) {
968 for (cg = 0; cg < 8; ++cg) {
969 for (cb = 0; cb < 8; ++cb) {
970 /* centre of the hashbox */
971 cenc.channel[0] = cr*pboxjump+pboxjump/2;
972 cenc.channel[1] = cg*pboxjump+pboxjump/2;
973 cenc.channel[2] = cb*pboxjump+pboxjump/2;
974 hbnum = pixbox(&cenc);
976 /* order indices in the order of distance from the hashbox */
977 for (i = 0; i < quant->mc_count; ++i) {
981 dists[i] = ceucl_d(&cenc, quant->mc_colors+i);
984 /* it should be possible to do this without a sort
985 but so far I'm too lazy */
987 qsort(indices, quant->mc_count, sizeof(int), distcomp);
988 /* any colors that can match are within mind+diagonal size of
990 mind = dists[indices[0]];
992 maxd = (sqrt(mind)+pboxjump)*(sqrt(mind)+pboxjump);
993 while (i < quant->mc_count && dists[indices[i]] < maxd) {
994 hb[hbnum].vec[hb[hbnum].cnt++] = indices[i++];
997 /* work out the minimum */
999 for (i = 0; i < quant->mc_count; ++i) {
1000 if (dists[i] < mind) mind = dists[i];
1002 /* transfer any colours that might be closest to a colour in
1004 maxd = (sqrt(mind)+pboxjump)*(sqrt(mind)+pboxjump);
1005 for (i = 0; i < quant->mc_count; ++i) {
1006 if (dists[i] < maxd)
1007 hb[hbnum].vec[hb[hbnum].cnt++] = i;
1018 #define CF_SETUP hbsetup(quant, hb)
1021 currhb = pixbox(&val); \
1023 for (i = 0; i < hb[currhb].cnt; ++i) { \
1024 cd = ceucl_d(quant->mc_colors+hb[currhb].vec[i], &val); \
1025 if (cd < ld) { ld = cd; bst_idx = hb[currhb].vec[i]; } \
1028 #define CF_CLEANUP myfree(hb)
1032 #ifdef IM_CFLINSEARCH
1033 /* as simple as it gets */
1034 #define CF_VARS long ld, cd
1035 #define CF_SETUP /* none needed */
1038 for (i = 0; i < quant->mc_count; ++i) { \
1039 cd = ceucl_d(quant->mc_colors+i, &val); \
1040 if (cd < ld) { ld = cd; bst_idx = i; } \
1045 #ifdef IM_CFSORTCHAN
1046 static int gsortchan;
1047 static i_quantize *gquant;
1048 static int chansort(void const *a, void const *b) {
1049 return gquant->mc_colors[*(int const *)a].channel[gsortchan] -
1050 gquant->mc_colors[*(int const *)b].channel[gsortchan];
1052 #define CF_VARS int *indices, sortchan, diff; \
1054 int vindex[256] /* where to find value i of chan */
1056 static void chansetup(i_img *img, i_quantize *quant, int *csortchan,
1057 int *vindex, int **cindices) {
1058 int *indices, sortchan, chan, i, chval;
1059 int chanmins[MAXCHANNELS], chanmaxs[MAXCHANNELS], maxrange;
1061 /* find the channel with the maximum range */
1062 /* the maximum stddev would probably be better */
1063 for (chan = 0; chan < img->channels; ++chan) {
1064 chanmins[chan] = 256; chanmaxs[chan] = 0;
1065 for (i = 0; i < quant->mc_count; ++i) {
1066 if (quant->mc_colors[i].channel[chan] < chanmins[chan])
1067 chanmins[chan] = quant->mc_colors[i].channel[chan];
1068 if (quant->mc_colors[i].channel[chan] > chanmaxs[chan])
1069 chanmaxs[chan] = quant->mc_colors[i].channel[chan];
1073 for (chan = 0; chan < img->channels; ++chan) {
1074 if (chanmaxs[chan]-chanmins[chan] > maxrange) {
1075 maxrange = chanmaxs[chan]-chanmins[chan];
1079 indices = mymalloc(quant->mc_count * sizeof(int)) ;
1080 for (i = 0; i < quant->mc_count; ++i) {
1083 gsortchan = sortchan;
1085 qsort(indices, quant->mc_count, sizeof(int), chansort) ;
1086 /* now a lookup table to find entries faster */
1087 for (chval=0, i=0; i < quant->mc_count; ++i) {
1088 while (chval < 256 &&
1089 chval < quant->mc_colors[indices[i]].channel[sortchan]) {
1090 vindex[chval++] = i;
1093 while (chval < 256) {
1094 vindex[chval++] = quant->mc_count-1;
1096 *csortchan = sortchan;
1097 *cindices = indices;
1101 chansetup(img, quant, &sortchan, vindex, &indices)
1103 int chanfind(i_color val, i_quantize *quant, int *indices, int *vindex,
1105 int i, bst_idx, diff, maxdiff;
1108 i = vindex[val.channel[sortchan]];
1109 bst_idx = indices[i];
1112 maxdiff = quant->mc_count;
1113 while (diff < maxdiff) {
1114 if (i+diff < quant->mc_count) {
1115 cd = ceucl_d(&val, quant->mc_colors+indices[i+diff]);
1117 bst_idx = indices[i+diff];
1123 cd = ceucl_d(&val, quant->mc_colors+indices[i-diff]);
1125 bst_idx = indices[i-diff];
1137 bst_idx = chanfind(val, quant, indices, vindex, sortchan)
1140 #define CF_CLEANUP myfree(indices)
1144 #ifdef IM_CFRAND2DIST
1146 /* This is based on a method described by Addi in the #imager channel
1147 on the 28/2/2001. I was about 1am Sydney time at the time, so I
1148 wasn't at my most cogent. Well, that's my excuse :)
1150 <TonyC> what I have at the moment is: hashboxes, with optimum hash box
1151 filling; simple linear search; and a lookup in the widest channel
1152 (currently the channel with the maximum range)
1153 <Addi> There is one more way that might be simple to implement.
1154 <Addi> You want to hear?
1155 <TonyC> what's that?
1156 <purl> somebody said that was not true
1157 <Addi> For each of the colors in the palette start by creating a
1158 sorted list of the form:
1159 <Addi> [distance, color]
1160 <Addi> Where they are sorted by distance.
1161 <TonyC> distance to where?
1162 <Addi> Where the elements in the lists are the distances and colors of
1163 the other colors in the palette
1165 <Addi> So if you are at color 0
1166 <Addi> ok - now to search for the closest color when you are creating
1167 the final image is done like this:
1168 <Addi> a) pick a random color from the palette
1169 <Addi> b) calculate the distance to it
1170 <Addi> c) only check the vectors that are within double the distance
1171 in the list of the color you picked from the palette.
1172 <Addi> Does that seem logical?
1173 <Addi> Lets imagine that we only have grayscale to make an example:
1174 <Addi> Our palette has 1 4 10 20 as colors.
1175 <Addi> And we want to quantize the color 11
1176 <Addi> lets say we picked 10 randomly
1177 <Addi> the double distance is 2
1178 <Addi> since abs(10-11)*2 is 2
1179 <Addi> And the list at vector 10 is this:
1180 <Addi> [0, 10], [6 4], [9, 1], [10, 20]
1181 <Addi> so we look at the first one (but not the second one since 6 is
1182 at a greater distance than 2.
1183 <Addi> Any of that make sense?
1184 <TonyC> yes, though are you suggesting another random jump to one of
1185 the colours with the possible choices? or an exhaustive search?
1186 <Addi> TonyC: It's possible to come up with a recursive/iterative
1187 enhancement but this is the 'basic' version.
1188 <Addi> Which would do an iterative search.
1189 <Addi> You can come up with conditions where it pays to switch to a new one.
1190 <Addi> And the 'random' start can be switched over to a small tree.
1191 <Addi> So you would have a little index at the start.
1192 <Addi> to get you into the general direction
1193 <Addi> Perhaps just an 8 split.
1194 <Addi> that is - split each dimension in half.
1196 <TonyC> I get the idea
1197 <Addi> But this would seem to be a good approach in our case since we
1198 usually have few codevectors.
1199 <Addi> So we only need 256*256 entries in a table.
1200 <Addi> We could even only index some of them that were deemed as good
1202 <TonyC> I was considering adding paletted output support for PNG and
1203 TIFF at some point, which support 16-bit palettes
1211 typedef struct i_dists {
1219 static int dists_sort(void const *a, void const *b) {
1220 return ((i_dists *)a)->dist - ((i_dists *)b)->dist;
1223 static void rand2dist_setup(i_quantize *quant, i_dists **cdists) {
1225 mymalloc(sizeof(i_dists)*quant->mc_count*quant->mc_count);
1228 for (i = 0; i < quant->mc_count; ++i) {
1229 i_dists *ldists = dists + quant->mc_count * i;
1230 i_color val = quant->mc_colors[i];
1231 for (j = 0; j < quant->mc_count; ++j) {
1232 ldists[j].index = j;
1233 ldists[j].dist = ceucl_d(&val, quant->mc_colors+j);
1235 qsort(ldists, quant->mc_count, sizeof(i_dists), dists_sort);
1241 bst_idx = rand() % quant->mc_count; \
1242 rand2dist_setup(quant, &dists)
1244 static int rand2dist_find(i_color val, i_quantize *quant, i_dists *dists, int index) {
1251 cdists = dists + index * quant->mc_count;
1253 maxld = 8 * ceucl_d(&val, quant->mc_colors+index);
1254 for (i = 0; i < quant->mc_count && cdists[i].dist <= maxld; ++i) {
1255 cd = ceucl_d(&val, quant->mc_colors+cdists[i].index);
1257 bst_idx = cdists[i].index;
1264 #define CF_FIND bst_idx = rand2dist_find(val, quant, dists, bst_idx)
1266 #define CF_CLEANUP myfree(dists)
1271 static void translate_addi(i_quantize *quant, i_img *img, i_palidx *out) {
1275 int pixdev = quant->perturb;
1280 if (img->channels >= 3) {
1283 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1284 i_gpix(img,x,y,&val);
1285 val.channel[0]=g_sat(val.channel[0]+(int)(pixdev*frandn()));
1286 val.channel[1]=g_sat(val.channel[1]+(int)(pixdev*frandn()));
1287 val.channel[2]=g_sat(val.channel[2]+(int)(pixdev*frandn()));
1293 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1294 i_gpix(img,x,y,&val);
1303 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1304 i_gpix(img,x,y,&val);
1305 val.channel[1] = val.channel[2] =
1306 val.channel[0]=g_sat(val.channel[0]+(int)(pixdev*frandn()));
1312 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1313 i_gpix(img,x,y,&val);
1314 val.channel[1] = val.channel[2] = val.channel[0];
1323 static int floyd_map[] =
1329 static int jarvis_map[] =
1336 static int stucki_map[] =
1343 struct errdiff_map {
1345 int width, height, orig;
1348 static struct errdiff_map maps[] =
1350 { floyd_map, 3, 2, 1 },
1351 { jarvis_map, 5, 3, 2 },
1352 { stucki_map, 5, 3, 2 },
1355 typedef struct errdiff_tag {
1359 /* perform an error diffusion dither */
1361 translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) {
1363 int mapw, maph, mapo;
1368 i_img_dim x, y, dx, dy;
1370 int is_gray = is_gray_map(quant);
1373 if ((quant->errdiff & ed_mask) == ed_custom) {
1374 map = quant->ed_map;
1375 mapw = quant->ed_width;
1376 maph = quant->ed_height;
1377 mapo = quant->ed_orig;
1380 int index = quant->errdiff & ed_mask;
1381 if (index >= ed_custom) index = ed_floyd;
1382 map = maps[index].map;
1383 mapw = maps[index].width;
1384 maph = maps[index].height;
1385 mapo = maps[index].orig;
1389 for (i = 0; i < maph * mapw; ++i) {
1391 i_push_errorf(0, "errdiff_map values must be non-negative, errdiff[%d] is negative", i);
1394 difftotal += map[i];
1398 i_push_error(0, "error diffusion map must contain some non-zero values");
1402 errw = img->xsize+mapw;
1403 err = mymalloc(sizeof(*err) * maph * errw);
1404 /*errp = err+mapo;*/
1405 memset(err, 0, sizeof(*err) * maph * errw);
1408 for (dy = 0; dy < maph; ++dy) {
1409 for (dx = 0; dx < mapw; ++dx) {
1410 printf("%2d", map[dx+dy*mapw]);
1417 for (y = 0; y < img->ysize; ++y) {
1418 for (x = 0; x < img->xsize; ++x) {
1421 i_gpix(img, x, y, &val);
1422 if (img->channels < 3) {
1423 val.channel[1] = val.channel[2] = val.channel[0];
1426 int gray = 0.5 + color_to_grey(&val);
1427 val.channel[0] = val.channel[1] = val.channel[2] = gray;
1430 perr.r = perr.r < 0 ? -((-perr.r)/difftotal) : perr.r/difftotal;
1431 perr.g = perr.g < 0 ? -((-perr.g)/difftotal) : perr.g/difftotal;
1432 perr.b = perr.b < 0 ? -((-perr.b)/difftotal) : perr.b/difftotal;
1433 /*printf("x %3d y %3d in(%3d, %3d, %3d) di(%4d,%4d,%4d)\n", x, y, val.channel[0], val.channel[1], val.channel[2], perr.r, perr.g, perr.b);*/
1434 val.channel[0] = g_sat(val.channel[0]-perr.r);
1435 val.channel[1] = g_sat(val.channel[1]-perr.g);
1436 val.channel[2] = g_sat(val.channel[2]-perr.b);
1439 perr.r = quant->mc_colors[bst_idx].channel[0] - val.channel[0];
1440 perr.g = quant->mc_colors[bst_idx].channel[1] - val.channel[1];
1441 perr.b = quant->mc_colors[bst_idx].channel[2] - val.channel[2];
1442 /*printf(" out(%3d, %3d, %3d) er(%4d, %4d, %4d)\n", quant->mc_colors[bst_idx].channel[0], quant->mc_colors[bst_idx].channel[1], quant->mc_colors[bst_idx].channel[2], perr.r, perr.g, perr.b);*/
1443 for (dx = 0; dx < mapw; ++dx) {
1444 for (dy = 0; dy < maph; ++dy) {
1445 err[x+dx+dy*errw].r += perr.r * map[dx+mapw*dy];
1446 err[x+dx+dy*errw].g += perr.g * map[dx+mapw*dy];
1447 err[x+dx+dy*errw].b += perr.b * map[dx+mapw*dy];
1452 /* shift up the error matrix */
1453 for (dy = 0; dy < maph-1; ++dy) {
1454 memcpy(err+dy*errw, err+(dy+1)*errw, sizeof(*err)*errw);
1456 memset(err+(maph-1)*errw, 0, sizeof(*err)*errw);
1463 /* Prescan finds the boxes in the image that have the highest number of colors
1464 and that result is used as the initial value for the vectores */
1467 static void prescan(i_img **imgs,int count, int cnum, cvec *clr, i_sample_t *line) {
1474 for(i=0;i<512;i++) {
1480 /* process each image */
1481 for (i = 0; i < count; ++i) {
1482 i_img *im = imgs[i];
1483 chans = im->channels >= 3 ? NULL : gray_samples;
1484 for(y=0;y<im->ysize;y++) {
1485 i_gsamp(im, 0, im->xsize, y, line, chans, 3);
1487 for(x=0;x<im->xsize;x++) {
1488 prebox[pixbox_ch(val)].pixcnt++;
1493 for(i=0;i<512;i++) prebox[i].pdc=prebox[i].pixcnt;
1494 qsort(prebox,512,sizeof(pbox),(cmpfunc)pboxcmp);
1496 for(i=0;i<cnum;i++) {
1497 /* printf("Color %d\n",i);
1498 for(k=0;k<10;k++) { printf("box=%03d %04d %d %04d \n",prebox[k].boxnum,prebox[k].pixcnt,prebox[k].cand,prebox[k].pdc); }
1503 /* for(k=0;k<cnum;k++) { printf("box=%03d %04d %d %04d \n",prebox[k].boxnum,prebox[k].pixcnt,prebox[k].cand,prebox[k].pdc); } */
1509 /* printf("prebox[%d].cand=%d\n",k,prebox[k].cand); */
1510 if (clr[i].fixed) { i++; continue; } /* reserved go to next */
1511 if (j>=prebox[k].cand) { k++; j=1; } else {
1512 if (prebox[k].cand == 2) boxcenter(prebox[k].boxnum,&(clr[i]));
1513 else boxrand(prebox[k].boxnum,&(clr[i]));
1514 /* printf("(%d,%d) %d %d -> (%d,%d,%d)\n",k,j,prebox[k].boxnum,prebox[k].pixcnt,clr[i].r,clr[i].g,clr[i].b); */
1522 static void reorder(pbox prescan[512]) {
1530 c.pdc=c.pixcnt/(c.cand*c.cand);
1531 /* c.pdc=c.pixcnt/c.cand; */
1532 while(nidx < 511 && c.pdc < prescan[nidx+1].pdc) {
1533 prescan[nidx]=prescan[nidx+1];
1540 pboxcmp(const pbox *a,const pbox *b) {
1541 if (a->pixcnt > b->pixcnt) return -1;
1542 if (a->pixcnt < b->pixcnt) return 1;
1547 boxcenter(int box,cvec *cv) {
1548 cv->r=15+((box&448)>>1);
1549 cv->g=15+((box&56)<<2);
1550 cv->b=15+((box&7)<<5);
1554 bbox(int box,int *r0,int *r1,int *g0,int *g1,int *b0,int *b1) {
1564 boxrand(int box,cvec *cv) {
1565 cv->r=6+(rand()%25)+((box&448)>>1);
1566 cv->g=6+(rand()%25)+((box&56)<<2);
1567 cv->b=6+(rand()%25)+((box&7)<<5);
1577 while (w >= 1 || w == 0) {
1578 u1 = 2 * frand() - 1;
1579 u2 = 2 * frand() - 1;
1583 w = sqrt((-2*log(w))/w);
1587 /* Create hash index */
1590 cr_hashindex(cvec clr[256],int cnum,hashbox hb[512]) {
1592 int bx,mind,cd,cumcnt,i;
1593 /* printf("indexing... \n");*/
1596 for(bx=0; bx<512; bx++) {
1598 for(i=0; i<cnum; i++) {
1599 cd = maxdist(bx,&clr[i]);
1600 if (cd < mind) { mind=cd; }
1604 for(i=0;i<cnum;i++) if (mindist(bx,&clr[i])<mind) hb[bx].vec[hb[bx].cnt++]=i;
1605 /*printf("box %d -> approx -> %d\n",bx,hb[bx].cnt); */
1606 /* statbox(bx,cnum,clr); */
1610 /* printf("Average search space: %d\n",cumcnt/512); */
1614 maxdist(int boxnum,cvec *cv) {
1615 int r0,r1,g0,g1,b0,b1;
1622 bbox(boxnum,&r0,&r1,&g0,&g1,&b0,&b1);
1624 mr=i_max(abs(b-b0),abs(b-b1));
1625 mg=i_max(abs(g-g0),abs(g-g1));
1626 mb=i_max(abs(r-r0),abs(r-r1));
1628 return PWR2(mr)+PWR2(mg)+PWR2(mb);
1632 mindist(int boxnum,cvec *cv) {
1633 int r0,r1,g0,g1,b0,b1;
1640 bbox(boxnum,&r0,&r1,&g0,&g1,&b0,&b1);
1642 /* printf("box %d, (%d,%d,%d)-(%d,%d,%d) vec (%d,%d,%d) ",boxnum,r0,g0,b0,r1,g1,b1,r,g,b); */
1644 if (r0<=r && r<=r1 && g0<=g && g<=g1 && b0<=b && b<=b1) return 0;
1646 mr=i_min(abs(b-b0),abs(b-b1));
1647 mg=i_min(abs(g-g0),abs(g-g1));
1648 mb=i_min(abs(r-r0),abs(r-r1));
1654 if (r0<=r && r<=r1 && g0<=g && g<=g1) return mb;
1655 if (r0<=r && r<=r1 && b0<=b && b<=b1) return mg;
1656 if (b0<=b && b<=b1 && g0<=g && g<=g1) return mr;
1658 if (r0<=r && r<=r1) return mg+mb;
1659 if (g0<=g && g<=g1) return mr+mb;
1660 if (b0<=b && b<=b1) return mg+mr;
1665 static void transparent_threshold(i_quantize *, i_palidx *, i_img *, i_palidx);
1666 static void transparent_errdiff(i_quantize *, i_palidx *, i_img *, i_palidx);
1667 static void transparent_ordered(i_quantize *, i_palidx *, i_img *, i_palidx);
1670 =item i_quant_transparent(C<quant>, C<data>, C<img>, C<trans_index>)
1672 =category Image quantization
1674 Dither the alpha channel on C<img> into the palette indexes in
1675 C<data>. Pixels to be transparent are replaced with C<trans_pixel>.
1677 The method used depends on the tr_* members of C<quant>.
1683 i_quant_transparent(i_quantize *quant, i_palidx *data, i_img *img,
1684 i_palidx trans_index)
1686 switch (quant->transp) {
1691 quant->tr_threshold = 128;
1694 transparent_threshold(quant, data, img, trans_index);
1698 transparent_errdiff(quant, data, img, trans_index);
1702 transparent_ordered(quant, data, img, trans_index);
1708 transparent_threshold(i_quantize *quant, i_palidx *data, i_img *img,
1709 i_palidx trans_index)
1712 i_sample_t *line = mymalloc(img->xsize * sizeof(i_sample_t));
1713 int trans_chan = img->channels > 2 ? 3 : 1;
1715 for (y = 0; y < img->ysize; ++y) {
1716 i_gsamp(img, 0, img->xsize, y, line, &trans_chan, 1);
1717 for (x = 0; x < img->xsize; ++x) {
1718 if (line[x] < quant->tr_threshold)
1719 data[y*img->xsize+x] = trans_index;
1726 transparent_errdiff(i_quantize *quant, i_palidx *data, i_img *img,
1727 i_palidx trans_index)
1731 int mapw, maph, mapo;
1732 int errw, *err, *errp;
1733 int difftotal, out, error;
1734 i_img_dim x, y, dx, dy;
1737 int trans_chan = img->channels > 2 ? 3 : 1;
1739 /* no custom map for transparency (yet) */
1740 index = quant->tr_errdiff & ed_mask;
1741 if (index >= ed_custom) index = ed_floyd;
1742 map = maps[index].map;
1743 mapw = maps[index].width;
1744 maph = maps[index].height;
1745 mapo = maps[index].orig;
1747 errw = img->xsize+mapw-1;
1748 err = mymalloc(sizeof(*err) * maph * errw);
1750 memset(err, 0, sizeof(*err) * maph * errw);
1752 line = mymalloc(img->xsize * sizeof(i_sample_t));
1754 for (i = 0; i < maph * mapw; ++i)
1755 difftotal += map[i];
1756 for (y = 0; y < img->ysize; ++y) {
1757 i_gsamp(img, 0, img->xsize, y, line, &trans_chan, 1);
1758 for (x = 0; x < img->xsize; ++x) {
1759 line[x] = g_sat(line[x]-errp[x]/difftotal);
1760 if (line[x] < 128) {
1762 data[y*img->xsize+x] = trans_index;
1767 error = out - line[x];
1768 for (dx = 0; dx < mapw; ++dx) {
1769 for (dy = 0; dy < maph; ++dy) {
1770 errp[x+dx-mapo+dy*errw] += error * map[dx+mapw*dy];
1774 /* shift up the error matrix */
1775 for (dy = 0; dy < maph-1; ++dy)
1776 memcpy(err+dy*errw, err+(dy+1)*errw, sizeof(*err)*errw);
1777 memset(err+(maph-1)*errw, 0, sizeof(*err)*errw);
1783 /* builtin ordered dither maps */
1784 static unsigned char
1785 orddith_maps[][64] =
1788 this is purely random - it's pretty awful
1790 48, 72, 196, 252, 180, 92, 108, 52,
1791 228, 176, 64, 8, 236, 40, 20, 164,
1792 120, 128, 84, 116, 24, 28, 172, 220,
1793 68, 0, 188, 124, 184, 224, 192, 104,
1794 132, 100, 240, 200, 152, 160, 244, 44,
1795 96, 204, 144, 16, 140, 56, 232, 216,
1796 208, 4, 76, 212, 136, 248, 80, 168,
1797 156, 88, 32, 112, 148, 12, 36, 60,
1801 perl spot.perl '($x-3.5)*($x-3.5)+($y-3.5)*($y-3.5)'
1803 240, 232, 200, 136, 140, 192, 228, 248,
1804 220, 148, 100, 76, 80, 104, 152, 212,
1805 180, 116, 56, 32, 36, 60, 120, 176,
1806 156, 64, 28, 0, 8, 44, 88, 160,
1807 128, 92, 24, 12, 4, 40, 68, 132,
1808 184, 96, 48, 20, 16, 52, 108, 188,
1809 216, 144, 112, 72, 84, 124, 164, 224,
1810 244, 236, 196, 168, 172, 204, 208, 252,
1814 'min(dist(1.5, 1.5),dist(5.5,1.5),dist(1.5,5.5),dist(5.5,5.5))'
1816 196, 72, 104, 220, 200, 80, 112, 224,
1817 76, 4, 24, 136, 84, 8, 32, 144,
1818 108, 28, 52, 168, 116, 36, 56, 176,
1819 216, 140, 172, 244, 228, 148, 180, 248,
1820 204, 92, 124, 236, 192, 68, 96, 208,
1821 88, 12, 44, 156, 64, 0, 16, 128,
1822 120, 40, 60, 188, 100, 20, 48, 160,
1823 232, 152, 184, 252, 212, 132, 164, 240,
1826 perl spot.perl '$y-3'
1828 160, 164, 168, 172, 176, 180, 184, 188,
1829 128, 132, 136, 140, 144, 148, 152, 156,
1830 32, 36, 40, 44, 48, 52, 56, 60,
1831 0, 4, 8, 12, 16, 20, 24, 28,
1832 64, 68, 72, 76, 80, 84, 88, 92,
1833 96, 100, 104, 108, 112, 116, 120, 124,
1834 192, 196, 200, 204, 208, 212, 216, 220,
1835 224, 228, 232, 236, 240, 244, 248, 252,
1838 perl spot.perl '$x-3'
1840 180, 100, 40, 12, 44, 104, 184, 232,
1841 204, 148, 60, 16, 64, 128, 208, 224,
1842 212, 144, 76, 8, 80, 132, 216, 244,
1843 160, 112, 68, 20, 84, 108, 172, 236,
1844 176, 96, 72, 28, 88, 152, 188, 228,
1845 200, 124, 92, 0, 32, 116, 164, 240,
1846 168, 120, 36, 24, 48, 136, 192, 248,
1847 196, 140, 52, 4, 56, 156, 220, 252,
1850 perl spot.perl '$y+$x-7'
1852 248, 232, 224, 192, 140, 92, 52, 28,
1853 240, 220, 196, 144, 108, 60, 12, 64,
1854 216, 180, 148, 116, 76, 20, 80, 128,
1855 204, 152, 104, 44, 16, 72, 100, 160,
1856 164, 96, 68, 24, 56, 112, 168, 176,
1857 124, 40, 8, 36, 88, 136, 184, 212,
1858 84, 4, 32, 120, 156, 188, 228, 236,
1859 0, 48, 132, 172, 200, 208, 244, 252,
1862 perl spot.perl '$y-$x'
1864 0, 32, 116, 172, 184, 216, 236, 252,
1865 56, 8, 72, 132, 136, 200, 228, 240,
1866 100, 36, 12, 40, 92, 144, 204, 220,
1867 168, 120, 60, 16, 44, 96, 156, 176,
1868 180, 164, 112, 48, 28, 52, 128, 148,
1869 208, 192, 152, 88, 84, 20, 64, 104,
1870 232, 224, 196, 140, 108, 68, 24, 76,
1871 248, 244, 212, 188, 160, 124, 80, 4,
1875 good for display, bad for print
1878 0, 128, 32, 192, 8, 136, 40, 200,
1879 224, 64, 160, 112, 232, 72, 168, 120,
1880 48, 144, 16, 208, 56, 152, 24, 216,
1881 176, 96, 240, 80, 184, 104, 248, 88,
1882 12, 140, 44, 204, 4, 132, 36, 196,
1883 236, 76, 172, 124, 228, 68, 164, 116,
1884 60, 156, 28, 220, 52, 148, 20, 212,
1885 188, 108, 252, 92, 180, 100, 244, 84,
1890 transparent_ordered(i_quantize *quant, i_palidx *data, i_img *img,
1891 i_palidx trans_index)
1893 unsigned char *spot;
1896 int trans_chan = img->channels > 2 ? 3 : 1;
1897 if (quant->tr_orddith == od_custom)
1898 spot = quant->tr_custom;
1900 spot = orddith_maps[quant->tr_orddith];
1902 line = mymalloc(img->xsize * sizeof(i_sample_t));
1903 for (y = 0; y < img->ysize; ++y) {
1904 i_gsamp(img, 0, img->xsize, y, line, &trans_chan, 1);
1905 for (x = 0; x < img->xsize; ++x) {
1906 if (line[x] < spot[(x&7)+(y&7)*8])
1907 data[x+y*img->xsize] = trans_index;