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 void 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 translate_errdiff(quant, img, result);
151 translate_addi(quant, img, result);
158 static void translate_closest(i_quantize *quant, i_img *img, i_palidx *out) {
160 translate_addi(quant, img, out);
163 #define PWR2(x) ((x)*(x))
165 typedef int (*cmpfunc)(const void*, const void*);
188 static void prescan(i_img **im,int count, int cnum, cvec *clr, i_sample_t *line);
189 static void reorder(pbox prescan[512]);
190 static int pboxcmp(const pbox *a,const pbox *b);
191 static void boxcenter(int box,cvec *cv);
192 static float frandn(void);
193 static void boxrand(int box,cvec *cv);
194 static void bbox(int box,int *r0,int *r1,int *g0,int *g1,int *b0,int *b1);
195 static void cr_hashindex(cvec clr[256],int cnum,hashbox hb[512]);
196 static int mindist(int boxnum,cvec *cv);
197 static int maxdist(int boxnum,cvec *cv);
199 /* Some of the simpler functions are kept here to aid the compiler -
200 maybe some of them will be inlined. */
203 pixbox(i_color *ic) { return ((ic->channel[0] & 224)<<1)+ ((ic->channel[1]&224)>>2) + ((ic->channel[2] &224) >> 5); }
206 pixbox_ch(i_sample_t *chans) { return ((chans[0] & 224)<<1)+ ((chans[1]&224)>>2) + ((chans[2] &224) >> 5); }
210 if (in>255) { return 255; }
211 else if (in>0) return in;
218 return rand()/(RAND_MAX+1.0);
224 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]); }
229 eucl_d_ch(cvec* cv,i_sample_t *chans) {
230 return PWR2(cv->r - chans[0]) + PWR2(cv->g - chans[1])
231 + PWR2(cv->b - chans[2]);
235 ceucl_d(i_color *c1, i_color *c2) {
236 return PWR2(c1->channel[0]-c2->channel[0])
237 +PWR2(c1->channel[1]-c2->channel[1])
238 +PWR2(c1->channel[2]-c2->channel[2]);
242 gray_samples[] = { 0, 0, 0 };
246 This quantization algorithm and implementation routines are by Arnar
247 M. Hrafnkelson. In case any new ideas are here they are mine since
248 this was written from scratch.
250 The algorithm uses local means in the following way:
252 For each point in the colormap we find which image points
253 have that point as it's closest point. We calculate the mean
254 of those points and in the next iteration it will be the new
255 entry in the colormap.
257 In order to speed this process up (i.e. nearest neighbor problem) We
258 divied the r,g,b space up in equally large 512 boxes. The boxes are
259 numbered from 0 to 511. Their numbering is so that for a given vector
260 it is known that it belongs to the box who is formed by concatenating the
261 3 most significant bits from each component of the RGB triplet.
263 For each box we find the list of points from the colormap who might be
264 closest to any given point within the box. The exact solution
265 involves finding the Voronoi map (or the dual the Delauny
266 triangulation) and has many issues including numerical stability.
268 So we use this approximation:
270 1. Find which point has the shortest maximum distance to the box.
271 2. Find all points that have a shorter minimum distance than that to the box
273 This is a very simple task and is not computationally heavy if one
274 takes into account that the minimum distances from a pixel to a box is
275 always found by checking if it's inside the box or is closest to some
276 side or a corner. Finding the maximum distance is also either a side
279 This approach results 2-3 times more than the actual points needed but
280 is still a good gain over the complete space. Usually when one has a
281 256 Colorcolor map a search over 30 is often obtained.
283 A bit of an enhancement to this approach is to keep a seperate list
284 for each side of the cube, but this will require even more memory.
286 Arnar M. Hrafnkelsson (addi@umich.edu);
290 Extracted from gifquant.c, removed dependencies on gif_lib,
291 and added support for multiple images.
292 starting from 1nov2000 by TonyC <tony@develop-help.com>.
297 makemap_addi(i_quantize *quant, i_img **imgs, int count) {
299 int cnum, i, bst_idx=0, ld, cd, iter, currhb, img_num;
305 i_img_dim maxwidth = 0;
307 const int *sample_indices;
309 mm_log((1, "makemap_addi(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
310 quant, quant->mc_count, quant->mc_colors, imgs, count));
312 if (makemap_palette(quant, imgs, count))
317 clr = i_mempool_alloc(&mp, sizeof(cvec) * quant->mc_size);
318 hb = i_mempool_alloc(&mp, sizeof(hashbox) * 512);
319 for (i=0; i < quant->mc_count; ++i) {
320 clr[i].r = quant->mc_colors[i].rgb.r;
321 clr[i].g = quant->mc_colors[i].rgb.g;
322 clr[i].b = quant->mc_colors[i].rgb.b;
326 /* mymalloc doesn't clear memory, so I think we need this */
327 for (; i < quant->mc_size; ++i) {
328 /*clr[i].r = clr[i].g = clr[i].b = 0;*/
335 cnum = quant->mc_size;
338 for (img_num = 0; img_num < count; ++img_num) {
339 if (imgs[img_num]->xsize > maxwidth)
340 maxwidth = imgs[img_num]->xsize;
342 line = i_mempool_alloc(&mp, 3 * maxwidth * sizeof(*line));
344 prescan(imgs, count, cnum, clr, line);
345 cr_hashindex(clr, cnum, hb);
347 for(iter=0;iter<3;iter++) {
350 for (img_num = 0; img_num < count; ++img_num) {
351 i_img *im = imgs[img_num];
352 sample_indices = im->channels >= 3 ? NULL : gray_samples;
353 for(y=0;y<im->ysize;y++) {
354 i_gsamp(im, 0, im->xsize, y, line, sample_indices, 3);
356 for(x=0;x<im->xsize;x++) {
358 /*i_gpix(im,x,y,&val);*/
359 currhb=pixbox_ch(val);
360 /* printf("box = %d \n",currhb); */
361 for(i=0;i<hb[currhb].cnt;i++) {
362 /* 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); */
364 cd=eucl_d_ch(&clr[hb[currhb].vec[i]],val);
366 ld=cd; /* shortest distance yet */
367 bst_idx=hb[currhb].vec[i]; /* index of closest vector yet */
371 clr[bst_idx].mcount++;
373 clr[bst_idx].dr+=val[0];
374 clr[bst_idx].dg+=val[1];
375 clr[bst_idx].db+=val[2];
377 val += 3; /* next 3 samples (next pixel) */
384 clr[i].dr/=clr[i].mcount;
385 clr[i].dg/=clr[i].mcount;
386 clr[i].db/=clr[i].mcount;
389 /* for(i=0;i<cnum;i++) printf("vec(%d)=(%d,%d,%d) dest=(%d,%d,%d) matchcount=%d\n",
390 i,clr[i].r,clr[i].g,clr[i].b,clr[i].dr,clr[i].dg,clr[i].db,clr[i].mcount); */
392 /* printf("total error: %.2f\n",sqrt(accerr)); */
394 for(i=0;i<cnum;i++) {
395 if (clr[i].fixed) continue; /* skip reserved colors */
399 clr[i].r=clr[i].r*(1-dlt)+dlt*clr[i].dr;
400 clr[i].g=clr[i].g*(1-dlt)+dlt*clr[i].dg;
401 clr[i].b=clr[i].b*(1-dlt)+dlt*clr[i].db;
403 /* let's try something else */
415 cr_hashindex(clr,cnum,hb);
420 for(i=0;i<cnum;i++) {
421 cd=eucl_d(&clr[i],&val);
429 /* if defined, we only include colours with an mcount or that were
430 supplied in the fixed palette, giving us a smaller output palette */
431 #define ONLY_USE_USED
433 /* transfer the colors back */
435 for (i = 0; i < cnum; ++i) {
436 if (clr[i].fixed || clr[i].used) {
437 /*printf("Adding %d (%d,%d,%d)\n", i, clr[i].r, clr[i].g, clr[i].b);*/
438 quant->mc_colors[quant->mc_count].rgb.r = clr[i].r;
439 quant->mc_colors[quant->mc_count].rgb.g = clr[i].g;
440 quant->mc_colors[quant->mc_count].rgb.b = clr[i].b;
445 /* transfer the colors back */
446 for (i = 0; i < cnum; ++i) {
447 quant->mc_colors[i].rgb.r = clr[i].r;
448 quant->mc_colors[i].rgb.g = clr[i].g;
449 quant->mc_colors[i].rgb.b = clr[i].b;
451 quant->mc_count = cnum;
455 mm_log((1, "makemap_addi returns - quant.mc_count = %d\n", quant->mc_count));
456 for (i = 0; i < quant->mc_count; ++i)
457 mm_log((5, " map entry %d: (%d, %d, %d)\n", i, clr[i].r, clr[i].g, clr[i].b));
460 i_mempool_destroy(&mp);
462 mm_log((1, "makemap_addi() - %d colors\n", quant->mc_count));
470 #define MEDIAN_CUT_COLORS 32768
472 #define MED_CUT_INDEX(c) ((((c).rgb.r & 0xF8) << 7) | \
473 (((c).rgb.g & 0xF8) << 2) | (((c).rgb.b & 0xF8) >> 3))
475 #define MED_CUT_GRAY_INDEX(c) ((((c).rgb.r & 0xF8) << 7) | \
476 (((c).rgb.r & 0xF8) << 2) | (((c).rgb.r & 0xF8) >> 3))
478 /* scale these to cover the whole range */
479 #define MED_CUT_RED(index) ((((index) & 0x7C00) >> 10) * 255 / 31)
480 #define MED_CUT_GREEN(index) ((((index) & 0x3E0) >> 5) * 255 / 31)
481 #define MED_CUT_BLUE(index) (((index) & 0x1F) * 255 / 31)
484 i_sample_t min[3]; /* minimum for each channel */
485 i_sample_t max[3]; /* maximum for each channel */
486 i_sample_t width[3]; /* width for each channel */
487 int start, size; /* beginning and size of the partition */
488 i_img_dim pixels; /* number of pixels represented by this partition */
492 =item calc_part(part, colors)
494 Calculates the new color limits for the given partition.
496 Giflib assumes that the limits for the non-split channels stay the
497 same, but this strikes me as incorrect, especially if the colors tend
500 Of course this could be optimized by not recalculating the channel we
501 just sorted on, but it's not worth the effort right now.
505 static void calc_part(medcut_partition *part, quant_color_entry *colors) {
508 for (ch = 0; ch < 3; ++ch) {
512 for (i = part->start; i < part->start + part->size; ++i) {
513 for (ch = 0; ch < 3; ++ch) {
514 if (part->min[ch] > colors[i].rgb[ch])
515 part->min[ch] = colors[i].rgb[ch];
516 if (part->max[ch] < colors[i].rgb[ch])
517 part->max[ch] = colors[i].rgb[ch];
520 for (ch = 0; ch < 3; ++ch) {
521 part->width[ch] = part->max[ch] - part->min[ch];
525 /* simple functions to sort by each channel - we could use a global, but
529 color_sort_red(void const *left, void const *right) {
530 return ((quant_color_entry *)left)->rgb[0] - ((quant_color_entry *)right)->rgb[0];
534 color_sort_green(void const *left, void const *right) {
535 return ((quant_color_entry *)left)->rgb[1] - ((quant_color_entry *)right)->rgb[1];
539 color_sort_blue(void const *left, void const *right) {
540 return ((quant_color_entry *)left)->rgb[2] - ((quant_color_entry *)right)->rgb[2];
543 static int (*sorters[])(void const *, void const *) =
551 makemap_mediancut(i_quantize *quant, i_img **imgs, int count) {
552 quant_color_entry *colors;
555 i_img_dim x, y, max_width;
558 i_img_dim total_pixels;
559 medcut_partition *parts;
562 /* number of channels we search for the best channel to partition
563 this isn't terribly efficient, but it should work */
566 mm_log((1, "makemap_mediancut(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
567 quant, quant->mc_count, quant->mc_colors, imgs, count));
569 if (makemap_palette(quant, imgs, count))
574 colors = i_mempool_alloc(&mp, sizeof(*colors) * MEDIAN_CUT_COLORS);
575 for (i = 0; i < MEDIAN_CUT_COLORS; ++i) {
576 colors[i].rgb[0] = MED_CUT_RED(i);
577 colors[i].rgb[1] = MED_CUT_GREEN(i);
578 colors[i].rgb[2] = MED_CUT_BLUE(i);
583 for (imgn = 0; imgn < count; ++imgn) {
584 if (imgs[imgn]->xsize > max_width)
585 max_width = imgs[imgn]->xsize;
587 line = i_mempool_alloc(&mp, sizeof(i_color) * max_width);
589 /* build the stats */
591 chan_count = 1; /* assume we just have grayscale */
592 for (imgn = 0; imgn < count; ++imgn) {
593 total_pixels += imgs[imgn]->xsize * imgs[imgn]->ysize;
594 for (y = 0; y < imgs[imgn]->ysize; ++y) {
595 i_glin(imgs[imgn], 0, imgs[imgn]->xsize, y, line);
596 if (imgs[imgn]->channels > 2) {
598 for (x = 0; x < imgs[imgn]->xsize; ++x) {
599 ++colors[MED_CUT_INDEX(line[x])].count;
603 /* a gray-scale image, just use the first channel */
604 for (x = 0; x < imgs[imgn]->xsize; ++x) {
605 ++colors[MED_CUT_GRAY_INDEX(line[x])].count;
611 /* eliminate the empty colors */
613 for (in = 0; in < MEDIAN_CUT_COLORS; ++in) {
614 if (colors[in].count) {
615 colors[out++] = colors[in];
618 /*printf("out %d\n", out);
620 for (i = 0; i < out; ++i) {
621 if (colors[i].count) {
622 printf("%d: (%d,%d,%d) -> %d\n", i, colors[i].rgb[0], colors[i].rgb[1],
623 colors[i].rgb[2], colors[i].count);
627 if (out < quant->mc_size) {
628 /* just copy them into the color table */
629 for (i = 0; i < out; ++i) {
630 for (ch = 0; ch < 3; ++ch) {
631 quant->mc_colors[i].channel[ch] = colors[i].rgb[ch];
634 quant->mc_count = out;
637 /* build the starting partition */
638 parts = i_mempool_alloc(&mp, sizeof(*parts) * quant->mc_size);
641 parts[0].pixels = total_pixels;
642 calc_part(parts, colors);
645 while (color_count < quant->mc_size) {
646 /* initialized to avoid compiler warnings */
647 int max_index = 0, max_ch = 0; /* index/channel with biggest spread */
649 medcut_partition *workpart;
653 /* find the partition with the most biggest span with more than
656 for (i = 0; i < color_count; ++i) {
657 for (ch = 0; ch < chan_count; ++ch) {
658 if (parts[i].width[ch] > max_size
659 && parts[i].size > 1) {
662 max_size = parts[i].width[ch];
667 /* nothing else we can split */
671 workpart = parts+max_index;
672 /*printf("splitting partition %d (pixels %ld, start %d, size %d)\n", max_index, workpart->pixels, workpart->start, workpart->size);*/
673 qsort(colors + workpart->start, workpart->size, sizeof(*colors),
676 /* find the median or something like it we need to make sure both
677 sides of the split have at least one color in them, so we don't
678 test at the first or last entry */
680 cum_total = colors[i].count;
682 half = workpart->pixels / 2;
683 while (i < workpart->start + workpart->size - 1
684 && cum_total < half) {
685 cum_total += colors[i++].count;
687 /*printf("Split at %d to make %d (half %ld, cumtotal %ld)\n", i, color_count, half, cum_total);*/
689 /* found the spot to split */
690 parts[color_count].start = i;
691 parts[color_count].size = workpart->start + workpart->size - i;
692 workpart->size = i - workpart->start;
693 parts[color_count].pixels = workpart->pixels - cum_total;
694 workpart->pixels = cum_total;
696 /* recalculate the limits */
697 calc_part(workpart, colors);
698 calc_part(parts+color_count, colors);
702 /* fill in the color table - since we could still have partitions
703 that have more than one color, we need to average the colors */
704 for (part_num = 0; part_num < color_count; ++part_num) {
706 medcut_partition *workpart;
708 workpart = parts+part_num;
709 for (ch = 0; ch < 3; ++ch)
712 for (i = workpart->start; i < workpart->start + workpart->size; ++i) {
713 for (ch = 0; ch < 3; ++ch) {
714 sums[ch] += colors[i].rgb[ch] * colors[i].count;
717 for (ch = 0; ch < 3; ++ch) {
718 quant->mc_colors[part_num].channel[ch] = sums[ch] / workpart->pixels;
721 quant->mc_count = color_count;
723 /*printf("out %d colors\n", quant->mc_count);*/
724 i_mempool_destroy(&mp);
726 mm_log((1, "makemap_mediancut() - %d colors\n", quant->mc_count));
730 makemap_mono(i_quantize *quant) {
731 quant->mc_colors[0].rgba.r = 0;
732 quant->mc_colors[0].rgba.g = 0;
733 quant->mc_colors[0].rgba.b = 0;
734 quant->mc_colors[0].rgba.a = 255;
735 quant->mc_colors[1].rgba.r = 255;
736 quant->mc_colors[1].rgba.g = 255;
737 quant->mc_colors[1].rgba.b = 255;
738 quant->mc_colors[1].rgba.a = 255;
743 makemap_gray(i_quantize *quant, int step) {
748 setcol(quant->mc_colors+i, gray, gray, gray, 255);
756 makemap_webmap(i_quantize *quant) {
760 for (r = 0; r < 256; r+=0x33)
761 for (g = 0; g < 256; g+=0x33)
762 for (b = 0; b < 256; b += 0x33)
763 setcol(quant->mc_colors+i++, r, g, b, 255);
768 in_palette(i_color *c, i_quantize *quant, int size) {
771 for (i = 0; i < size; ++i) {
772 if (c->channel[0] == quant->mc_colors[i].channel[0]
773 && c->channel[1] == quant->mc_colors[i].channel[1]
774 && c->channel[2] == quant->mc_colors[i].channel[2]) {
783 =item makemap_palette(quant, imgs, count)
785 Tests if all the given images are paletted and have a common palette,
786 if they do it builds that palette.
788 A possible improvement might be to eliminate unused colors in the
795 makemap_palette(i_quantize *quant, i_img **imgs, int count) {
796 int size = quant->mc_count;
802 mm_log((1, "makemap_palette(quant %p { mc_count=%d, mc_colors=%p }, imgs %p, count %d)\n",
803 quant, quant->mc_count, quant->mc_colors, imgs, count));
804 /* we try to build a common palette here, if we can manage that, then
805 that's the palette we use */
806 for (imgn = 0; imgn < count; ++imgn) {
807 int eliminate_unused;
808 if (imgs[imgn]->type != i_palette_type) {
809 mm_log((1, "makemap_palette() -> 0 (non-palette image)\n"));
813 if (!i_tags_get_int(&imgs[imgn]->tags, "gif_eliminate_unused", 0,
814 &eliminate_unused)) {
815 eliminate_unused = 1;
818 if (eliminate_unused) {
819 i_palidx *line = mymalloc(sizeof(i_palidx) * imgs[imgn]->xsize);
821 memset(used, 0, sizeof(used));
823 for (y = 0; y < imgs[imgn]->ysize; ++y) {
824 i_gpal(imgs[imgn], 0, imgs[imgn]->xsize, y, line);
825 for (x = 0; x < imgs[imgn]->xsize; ++x)
832 /* assume all are in use */
833 memset(used, 1, sizeof(used));
836 col_count = i_colorcount(imgs[imgn]);
837 for (i = 0; i < col_count; ++i) {
840 i_getcolors(imgs[imgn], i, &c, 1);
842 if (in_palette(&c, quant, size) < 0) {
843 if (size < quant->mc_size) {
844 quant->mc_colors[size++] = c;
847 mm_log((1, "makemap_palette() -> 0 (too many colors)\n"));
855 mm_log((1, "makemap_palette() -> 1 (%d total colors)\n", size));
856 quant->mc_count = size;
863 /* Define one of the following 4 symbols to choose a colour search method
864 The idea is to try these out, including benchmarking, to see which
865 is fastest in a good spread of circumstances.
866 I'd expect IM_CFLINSEARCH to be fastest for very small palettes, and
867 IM_CFHASHBOX for large images with large palettes.
869 Some other possibilities include:
870 - search over entries sorted by luminance
872 Initially I was planning on testing using the macros and then
873 integrating the code directly into each function, but this means if
874 we find a bug at a late stage we will need to update N copies of
875 the same code. Also, keeping the code in the macros means that the
876 code in the translation functions is much more to the point,
877 there's no distracting colour search code to remove attention from
878 what makes _this_ translation function different. It may be
879 advisable to move the setup code into functions at some point, but
880 it should be possible to do this fairly transparently.
882 If IM_CF_COPTS is defined then CFLAGS must have an appropriate
885 Each option needs to define 4 macros:
886 CF_VARS - variables to define in the function
887 CF_SETUP - code to setup for the colour search, eg. allocating and
888 initializing lookup tables
889 CF_FIND - code that looks for the color in val and puts the best
890 matching index in bst_idx
891 CF_CLEANUP - code to clean up, eg. releasing memory
894 /*#define IM_CFLINSEARCH*/
896 /*#define IM_CFSORTCHAN*/
897 /*#define IM_CFRAND2DIST*/
900 /* return true if the color map contains only grays */
902 is_gray_map(const i_quantize *quant) {
905 for (i = 0; i < quant->mc_count; ++i) {
906 if (quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.g
907 || quant->mc_colors[i].rgb.r != quant->mc_colors[i].rgb.b) {
908 mm_log((1, " not a gray map\n"));
913 mm_log((1, " is a gray map\n"));
919 /* The original version I wrote for this used the sort.
920 If this is defined then we use a sort to extract the indices for
924 /* assume i is available */
925 #define CF_VARS hashbox *hb = mymalloc(sizeof(hashbox) * 512); \
931 static long *gdists; /* qsort is annoying */
932 /* int might be smaller than long, so we need to do a real compare
933 rather than a subtraction*/
934 static int distcomp(void const *a, void const *b) {
935 long ra = gdists[*(int const *)a];
936 long rb = gdists[*(int const *)b];
947 /* for each hashbox build a list of colours that are in the hb or is closer
949 This is pretty involved. The original gifquant generated the hashbox
950 as part of it's normal processing, but since the map generation is now
951 separated from the translation we need to do this on the spot.
952 Any optimizations, even if they don't produce perfect results would be
955 static void hbsetup(i_quantize *quant, hashbox *hb) {
956 long *dists, mind, maxd;
957 int cr, cb, cg, hbnum, i;
960 int *indices = mymalloc(quant->mc_count * sizeof(int));
963 dists = mymalloc(quant->mc_count * sizeof(long));
964 for (cr = 0; cr < 8; ++cr) {
965 for (cg = 0; cg < 8; ++cg) {
966 for (cb = 0; cb < 8; ++cb) {
967 /* centre of the hashbox */
968 cenc.channel[0] = cr*pboxjump+pboxjump/2;
969 cenc.channel[1] = cg*pboxjump+pboxjump/2;
970 cenc.channel[2] = cb*pboxjump+pboxjump/2;
971 hbnum = pixbox(&cenc);
973 /* order indices in the order of distance from the hashbox */
974 for (i = 0; i < quant->mc_count; ++i) {
978 dists[i] = ceucl_d(&cenc, quant->mc_colors+i);
981 /* it should be possible to do this without a sort
982 but so far I'm too lazy */
984 qsort(indices, quant->mc_count, sizeof(int), distcomp);
985 /* any colors that can match are within mind+diagonal size of
987 mind = dists[indices[0]];
989 maxd = (sqrt(mind)+pboxjump)*(sqrt(mind)+pboxjump);
990 while (i < quant->mc_count && dists[indices[i]] < maxd) {
991 hb[hbnum].vec[hb[hbnum].cnt++] = indices[i++];
994 /* work out the minimum */
996 for (i = 0; i < quant->mc_count; ++i) {
997 if (dists[i] < mind) mind = dists[i];
999 /* transfer any colours that might be closest to a colour in
1001 maxd = (sqrt(mind)+pboxjump)*(sqrt(mind)+pboxjump);
1002 for (i = 0; i < quant->mc_count; ++i) {
1003 if (dists[i] < maxd)
1004 hb[hbnum].vec[hb[hbnum].cnt++] = i;
1015 #define CF_SETUP hbsetup(quant, hb)
1018 currhb = pixbox(&val); \
1020 for (i = 0; i < hb[currhb].cnt; ++i) { \
1021 cd = ceucl_d(quant->mc_colors+hb[currhb].vec[i], &val); \
1022 if (cd < ld) { ld = cd; bst_idx = hb[currhb].vec[i]; } \
1025 #define CF_CLEANUP myfree(hb)
1029 #ifdef IM_CFLINSEARCH
1030 /* as simple as it gets */
1031 #define CF_VARS long ld, cd
1032 #define CF_SETUP /* none needed */
1035 for (i = 0; i < quant->mc_count; ++i) { \
1036 cd = ceucl_d(quant->mc_colors+i, &val); \
1037 if (cd < ld) { ld = cd; bst_idx = i; } \
1042 #ifdef IM_CFSORTCHAN
1043 static int gsortchan;
1044 static i_quantize *gquant;
1045 static int chansort(void const *a, void const *b) {
1046 return gquant->mc_colors[*(int const *)a].channel[gsortchan] -
1047 gquant->mc_colors[*(int const *)b].channel[gsortchan];
1049 #define CF_VARS int *indices, sortchan, diff; \
1051 int vindex[256] /* where to find value i of chan */
1053 static void chansetup(i_img *img, i_quantize *quant, int *csortchan,
1054 int *vindex, int **cindices) {
1055 int *indices, sortchan, chan, i, chval;
1056 int chanmins[MAXCHANNELS], chanmaxs[MAXCHANNELS], maxrange;
1058 /* find the channel with the maximum range */
1059 /* the maximum stddev would probably be better */
1060 for (chan = 0; chan < img->channels; ++chan) {
1061 chanmins[chan] = 256; chanmaxs[chan] = 0;
1062 for (i = 0; i < quant->mc_count; ++i) {
1063 if (quant->mc_colors[i].channel[chan] < chanmins[chan])
1064 chanmins[chan] = quant->mc_colors[i].channel[chan];
1065 if (quant->mc_colors[i].channel[chan] > chanmaxs[chan])
1066 chanmaxs[chan] = quant->mc_colors[i].channel[chan];
1070 for (chan = 0; chan < img->channels; ++chan) {
1071 if (chanmaxs[chan]-chanmins[chan] > maxrange) {
1072 maxrange = chanmaxs[chan]-chanmins[chan];
1076 indices = mymalloc(quant->mc_count * sizeof(int)) ;
1077 for (i = 0; i < quant->mc_count; ++i) {
1080 gsortchan = sortchan;
1082 qsort(indices, quant->mc_count, sizeof(int), chansort) ;
1083 /* now a lookup table to find entries faster */
1084 for (chval=0, i=0; i < quant->mc_count; ++i) {
1085 while (chval < 256 &&
1086 chval < quant->mc_colors[indices[i]].channel[sortchan]) {
1087 vindex[chval++] = i;
1090 while (chval < 256) {
1091 vindex[chval++] = quant->mc_count-1;
1093 *csortchan = sortchan;
1094 *cindices = indices;
1098 chansetup(img, quant, &sortchan, vindex, &indices)
1100 int chanfind(i_color val, i_quantize *quant, int *indices, int *vindex,
1102 int i, bst_idx, diff, maxdiff;
1105 i = vindex[val.channel[sortchan]];
1106 bst_idx = indices[i];
1109 maxdiff = quant->mc_count;
1110 while (diff < maxdiff) {
1111 if (i+diff < quant->mc_count) {
1112 cd = ceucl_d(&val, quant->mc_colors+indices[i+diff]);
1114 bst_idx = indices[i+diff];
1120 cd = ceucl_d(&val, quant->mc_colors+indices[i-diff]);
1122 bst_idx = indices[i-diff];
1134 bst_idx = chanfind(val, quant, indices, vindex, sortchan)
1137 #define CF_CLEANUP myfree(indices)
1141 #ifdef IM_CFRAND2DIST
1143 /* This is based on a method described by Addi in the #imager channel
1144 on the 28/2/2001. I was about 1am Sydney time at the time, so I
1145 wasn't at my most cogent. Well, that's my excuse :)
1147 <TonyC> what I have at the moment is: hashboxes, with optimum hash box
1148 filling; simple linear search; and a lookup in the widest channel
1149 (currently the channel with the maximum range)
1150 <Addi> There is one more way that might be simple to implement.
1151 <Addi> You want to hear?
1152 <TonyC> what's that?
1153 <purl> somebody said that was not true
1154 <Addi> For each of the colors in the palette start by creating a
1155 sorted list of the form:
1156 <Addi> [distance, color]
1157 <Addi> Where they are sorted by distance.
1158 <TonyC> distance to where?
1159 <Addi> Where the elements in the lists are the distances and colors of
1160 the other colors in the palette
1162 <Addi> So if you are at color 0
1163 <Addi> ok - now to search for the closest color when you are creating
1164 the final image is done like this:
1165 <Addi> a) pick a random color from the palette
1166 <Addi> b) calculate the distance to it
1167 <Addi> c) only check the vectors that are within double the distance
1168 in the list of the color you picked from the palette.
1169 <Addi> Does that seem logical?
1170 <Addi> Lets imagine that we only have grayscale to make an example:
1171 <Addi> Our palette has 1 4 10 20 as colors.
1172 <Addi> And we want to quantize the color 11
1173 <Addi> lets say we picked 10 randomly
1174 <Addi> the double distance is 2
1175 <Addi> since abs(10-11)*2 is 2
1176 <Addi> And the list at vector 10 is this:
1177 <Addi> [0, 10], [6 4], [9, 1], [10, 20]
1178 <Addi> so we look at the first one (but not the second one since 6 is
1179 at a greater distance than 2.
1180 <Addi> Any of that make sense?
1181 <TonyC> yes, though are you suggesting another random jump to one of
1182 the colours with the possible choices? or an exhaustive search?
1183 <Addi> TonyC: It's possible to come up with a recursive/iterative
1184 enhancement but this is the 'basic' version.
1185 <Addi> Which would do an iterative search.
1186 <Addi> You can come up with conditions where it pays to switch to a new one.
1187 <Addi> And the 'random' start can be switched over to a small tree.
1188 <Addi> So you would have a little index at the start.
1189 <Addi> to get you into the general direction
1190 <Addi> Perhaps just an 8 split.
1191 <Addi> that is - split each dimension in half.
1193 <TonyC> I get the idea
1194 <Addi> But this would seem to be a good approach in our case since we
1195 usually have few codevectors.
1196 <Addi> So we only need 256*256 entries in a table.
1197 <Addi> We could even only index some of them that were deemed as good
1199 <TonyC> I was considering adding paletted output support for PNG and
1200 TIFF at some point, which support 16-bit palettes
1208 typedef struct i_dists {
1216 static int dists_sort(void const *a, void const *b) {
1217 return ((i_dists *)a)->dist - ((i_dists *)b)->dist;
1220 static void rand2dist_setup(i_quantize *quant, i_dists **cdists) {
1222 mymalloc(sizeof(i_dists)*quant->mc_count*quant->mc_count);
1225 for (i = 0; i < quant->mc_count; ++i) {
1226 i_dists *ldists = dists + quant->mc_count * i;
1227 i_color val = quant->mc_colors[i];
1228 for (j = 0; j < quant->mc_count; ++j) {
1229 ldists[j].index = j;
1230 ldists[j].dist = ceucl_d(&val, quant->mc_colors+j);
1232 qsort(ldists, quant->mc_count, sizeof(i_dists), dists_sort);
1238 bst_idx = rand() % quant->mc_count; \
1239 rand2dist_setup(quant, &dists)
1241 static int rand2dist_find(i_color val, i_quantize *quant, i_dists *dists, int index) {
1248 cdists = dists + index * quant->mc_count;
1250 maxld = 8 * ceucl_d(&val, quant->mc_colors+index);
1251 for (i = 0; i < quant->mc_count && cdists[i].dist <= maxld; ++i) {
1252 cd = ceucl_d(&val, quant->mc_colors+cdists[i].index);
1254 bst_idx = cdists[i].index;
1261 #define CF_FIND bst_idx = rand2dist_find(val, quant, dists, bst_idx)
1263 #define CF_CLEANUP myfree(dists)
1268 static void translate_addi(i_quantize *quant, i_img *img, i_palidx *out) {
1272 int pixdev = quant->perturb;
1277 if (img->channels >= 3) {
1280 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1281 i_gpix(img,x,y,&val);
1282 val.channel[0]=g_sat(val.channel[0]+(int)(pixdev*frandn()));
1283 val.channel[1]=g_sat(val.channel[1]+(int)(pixdev*frandn()));
1284 val.channel[2]=g_sat(val.channel[2]+(int)(pixdev*frandn()));
1290 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1291 i_gpix(img,x,y,&val);
1300 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1301 i_gpix(img,x,y,&val);
1302 val.channel[1] = val.channel[2] =
1303 val.channel[0]=g_sat(val.channel[0]+(int)(pixdev*frandn()));
1309 for(y=0;y<img->ysize;y++) for(x=0;x<img->xsize;x++) {
1310 i_gpix(img,x,y,&val);
1311 val.channel[1] = val.channel[2] = val.channel[0];
1320 static int floyd_map[] =
1326 static int jarvis_map[] =
1333 static int stucki_map[] =
1340 struct errdiff_map {
1342 int width, height, orig;
1345 static struct errdiff_map maps[] =
1347 { floyd_map, 3, 2, 1 },
1348 { jarvis_map, 5, 3, 2 },
1349 { stucki_map, 5, 3, 2 },
1352 typedef struct errdiff_tag {
1356 /* perform an error diffusion dither */
1359 translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) {
1361 int mapw, maph, mapo;
1366 i_img_dim x, y, dx, dy;
1368 int is_gray = is_gray_map(quant);
1371 if ((quant->errdiff & ed_mask) == ed_custom) {
1372 map = quant->ed_map;
1373 mapw = quant->ed_width;
1374 maph = quant->ed_height;
1375 mapo = quant->ed_orig;
1378 int index = quant->errdiff & ed_mask;
1379 if (index >= ed_custom) index = ed_floyd;
1380 map = maps[index].map;
1381 mapw = maps[index].width;
1382 maph = maps[index].height;
1383 mapo = maps[index].orig;
1386 errw = img->xsize+mapw;
1387 err = mymalloc(sizeof(*err) * maph * errw);
1388 /*errp = err+mapo;*/
1389 memset(err, 0, sizeof(*err) * maph * errw);
1392 for (i = 0; i < maph * mapw; ++i)
1393 difftotal += map[i];
1395 for (dy = 0; dy < maph; ++dy) {
1396 for (dx = 0; dx < mapw; ++dx) {
1397 printf("%2d", map[dx+dy*mapw]);
1404 for (y = 0; y < img->ysize; ++y) {
1405 for (x = 0; x < img->xsize; ++x) {
1408 i_gpix(img, x, y, &val);
1409 if (img->channels < 3) {
1410 val.channel[1] = val.channel[2] = val.channel[0];
1413 int gray = 0.5 + color_to_grey(&val);
1414 val.channel[0] = val.channel[1] = val.channel[2] = gray;
1417 perr.r = perr.r < 0 ? -((-perr.r)/difftotal) : perr.r/difftotal;
1418 perr.g = perr.g < 0 ? -((-perr.g)/difftotal) : perr.g/difftotal;
1419 perr.b = perr.b < 0 ? -((-perr.b)/difftotal) : perr.b/difftotal;
1420 /*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);*/
1421 val.channel[0] = g_sat(val.channel[0]-perr.r);
1422 val.channel[1] = g_sat(val.channel[1]-perr.g);
1423 val.channel[2] = g_sat(val.channel[2]-perr.b);
1426 perr.r = quant->mc_colors[bst_idx].channel[0] - val.channel[0];
1427 perr.g = quant->mc_colors[bst_idx].channel[1] - val.channel[1];
1428 perr.b = quant->mc_colors[bst_idx].channel[2] - val.channel[2];
1429 /*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);*/
1430 for (dx = 0; dx < mapw; ++dx) {
1431 for (dy = 0; dy < maph; ++dy) {
1432 err[x+dx+dy*errw].r += perr.r * map[dx+mapw*dy];
1433 err[x+dx+dy*errw].g += perr.g * map[dx+mapw*dy];
1434 err[x+dx+dy*errw].b += perr.b * map[dx+mapw*dy];
1439 /* shift up the error matrix */
1440 for (dy = 0; dy < maph-1; ++dy) {
1441 memcpy(err+dy*errw, err+(dy+1)*errw, sizeof(*err)*errw);
1443 memset(err+(maph-1)*errw, 0, sizeof(*err)*errw);
1448 /* Prescan finds the boxes in the image that have the highest number of colors
1449 and that result is used as the initial value for the vectores */
1452 static void prescan(i_img **imgs,int count, int cnum, cvec *clr, i_sample_t *line) {
1459 for(i=0;i<512;i++) {
1465 /* process each image */
1466 for (i = 0; i < count; ++i) {
1467 i_img *im = imgs[i];
1468 chans = im->channels >= 3 ? NULL : gray_samples;
1469 for(y=0;y<im->ysize;y++) {
1470 i_gsamp(im, 0, im->xsize, y, line, chans, 3);
1472 for(x=0;x<im->xsize;x++) {
1473 prebox[pixbox_ch(val)].pixcnt++;
1478 for(i=0;i<512;i++) prebox[i].pdc=prebox[i].pixcnt;
1479 qsort(prebox,512,sizeof(pbox),(cmpfunc)pboxcmp);
1481 for(i=0;i<cnum;i++) {
1482 /* printf("Color %d\n",i);
1483 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); }
1488 /* 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); } */
1494 /* printf("prebox[%d].cand=%d\n",k,prebox[k].cand); */
1495 if (clr[i].fixed) { i++; continue; } /* reserved go to next */
1496 if (j>=prebox[k].cand) { k++; j=1; } else {
1497 if (prebox[k].cand == 2) boxcenter(prebox[k].boxnum,&(clr[i]));
1498 else boxrand(prebox[k].boxnum,&(clr[i]));
1499 /* 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); */
1507 static void reorder(pbox prescan[512]) {
1515 c.pdc=c.pixcnt/(c.cand*c.cand);
1516 /* c.pdc=c.pixcnt/c.cand; */
1517 while(c.pdc < prescan[nidx+1].pdc && nidx < 511) {
1518 prescan[nidx]=prescan[nidx+1];
1525 pboxcmp(const pbox *a,const pbox *b) {
1526 if (a->pixcnt > b->pixcnt) return -1;
1527 if (a->pixcnt < b->pixcnt) return 1;
1532 boxcenter(int box,cvec *cv) {
1533 cv->r=15+((box&448)>>1);
1534 cv->g=15+((box&56)<<2);
1535 cv->b=15+((box&7)<<5);
1539 bbox(int box,int *r0,int *r1,int *g0,int *g1,int *b0,int *b1) {
1549 boxrand(int box,cvec *cv) {
1550 cv->r=6+(rand()%25)+((box&448)>>1);
1551 cv->g=6+(rand()%25)+((box&56)<<2);
1552 cv->b=6+(rand()%25)+((box&7)<<5);
1562 while (w >= 1 || w == 0) {
1563 u1 = 2 * frand() - 1;
1564 u2 = 2 * frand() - 1;
1568 w = sqrt((-2*log(w))/w);
1572 /* Create hash index */
1575 cr_hashindex(cvec clr[256],int cnum,hashbox hb[512]) {
1577 int bx,mind,cd,cumcnt,bst_idx,i;
1578 /* printf("indexing... \n");*/
1581 for(bx=0; bx<512; bx++) {
1583 for(i=0; i<cnum; i++) {
1584 cd = maxdist(bx,&clr[i]);
1585 if (cd < mind) { mind=cd; bst_idx=i; }
1589 for(i=0;i<cnum;i++) if (mindist(bx,&clr[i])<mind) hb[bx].vec[hb[bx].cnt++]=i;
1590 /*printf("box %d -> approx -> %d\n",bx,hb[bx].cnt); */
1591 /* statbox(bx,cnum,clr); */
1595 /* printf("Average search space: %d\n",cumcnt/512); */
1599 maxdist(int boxnum,cvec *cv) {
1600 int r0,r1,g0,g1,b0,b1;
1607 bbox(boxnum,&r0,&r1,&g0,&g1,&b0,&b1);
1609 mr=i_max(abs(b-b0),abs(b-b1));
1610 mg=i_max(abs(g-g0),abs(g-g1));
1611 mb=i_max(abs(r-r0),abs(r-r1));
1613 return PWR2(mr)+PWR2(mg)+PWR2(mb);
1617 mindist(int boxnum,cvec *cv) {
1618 int r0,r1,g0,g1,b0,b1;
1625 bbox(boxnum,&r0,&r1,&g0,&g1,&b0,&b1);
1627 /* printf("box %d, (%d,%d,%d)-(%d,%d,%d) vec (%d,%d,%d) ",boxnum,r0,g0,b0,r1,g1,b1,r,g,b); */
1629 if (r0<=r && r<=r1 && g0<=g && g<=g1 && b0<=b && b<=b1) return 0;
1631 mr=i_min(abs(b-b0),abs(b-b1));
1632 mg=i_min(abs(g-g0),abs(g-g1));
1633 mb=i_min(abs(r-r0),abs(r-r1));
1639 if (r0<=r && r<=r1 && g0<=g && g<=g1) return mb;
1640 if (r0<=r && r<=r1 && b0<=b && b<=b1) return mg;
1641 if (b0<=b && b<=b1 && g0<=g && g<=g1) return mr;
1643 if (r0<=r && r<=r1) return mg+mb;
1644 if (g0<=g && g<=g1) return mr+mb;
1645 if (b0<=b && b<=b1) return mg+mr;
1650 static void transparent_threshold(i_quantize *, i_palidx *, i_img *, i_palidx);
1651 static void transparent_errdiff(i_quantize *, i_palidx *, i_img *, i_palidx);
1652 static void transparent_ordered(i_quantize *, i_palidx *, i_img *, i_palidx);
1655 =item i_quant_transparent(C<quant>, C<data>, C<img>, C<trans_index>)
1657 =category Image quantization
1659 Dither the alpha channel on C<img> into the palette indexes in
1660 C<data>. Pixels to be transparent are replaced with C<trans_pixel>.
1662 The method used depends on the tr_* members of C<quant>.
1668 i_quant_transparent(i_quantize *quant, i_palidx *data, i_img *img,
1669 i_palidx trans_index)
1671 switch (quant->transp) {
1676 quant->tr_threshold = 128;
1679 transparent_threshold(quant, data, img, trans_index);
1683 transparent_errdiff(quant, data, img, trans_index);
1687 transparent_ordered(quant, data, img, trans_index);
1693 transparent_threshold(i_quantize *quant, i_palidx *data, i_img *img,
1694 i_palidx trans_index)
1697 i_sample_t *line = mymalloc(img->xsize * sizeof(i_sample_t));
1698 int trans_chan = img->channels > 2 ? 3 : 1;
1700 for (y = 0; y < img->ysize; ++y) {
1701 i_gsamp(img, 0, img->xsize, y, line, &trans_chan, 1);
1702 for (x = 0; x < img->xsize; ++x) {
1703 if (line[x] < quant->tr_threshold)
1704 data[y*img->xsize+x] = trans_index;
1711 transparent_errdiff(i_quantize *quant, i_palidx *data, i_img *img,
1712 i_palidx trans_index)
1716 int mapw, maph, mapo;
1717 int errw, *err, *errp;
1718 int difftotal, out, error;
1719 i_img_dim x, y, dx, dy;
1722 int trans_chan = img->channels > 2 ? 3 : 1;
1724 /* no custom map for transparency (yet) */
1725 index = quant->tr_errdiff & ed_mask;
1726 if (index >= ed_custom) index = ed_floyd;
1727 map = maps[index].map;
1728 mapw = maps[index].width;
1729 maph = maps[index].height;
1730 mapo = maps[index].orig;
1732 errw = img->xsize+mapw-1;
1733 err = mymalloc(sizeof(*err) * maph * errw);
1735 memset(err, 0, sizeof(*err) * maph * errw);
1737 line = mymalloc(img->xsize * sizeof(i_sample_t));
1739 for (i = 0; i < maph * mapw; ++i)
1740 difftotal += map[i];
1741 for (y = 0; y < img->ysize; ++y) {
1742 i_gsamp(img, 0, img->xsize, y, line, &trans_chan, 1);
1743 for (x = 0; x < img->xsize; ++x) {
1744 line[x] = g_sat(line[x]-errp[x]/difftotal);
1745 if (line[x] < 128) {
1747 data[y*img->xsize+x] = trans_index;
1752 error = out - line[x];
1753 for (dx = 0; dx < mapw; ++dx) {
1754 for (dy = 0; dy < maph; ++dy) {
1755 errp[x+dx-mapo+dy*errw] += error * map[dx+mapw*dy];
1759 /* shift up the error matrix */
1760 for (dy = 0; dy < maph-1; ++dy)
1761 memcpy(err+dy*errw, err+(dy+1)*errw, sizeof(*err)*errw);
1762 memset(err+(maph-1)*errw, 0, sizeof(*err)*errw);
1768 /* builtin ordered dither maps */
1769 static unsigned char
1770 orddith_maps[][64] =
1773 this is purely random - it's pretty awful
1775 48, 72, 196, 252, 180, 92, 108, 52,
1776 228, 176, 64, 8, 236, 40, 20, 164,
1777 120, 128, 84, 116, 24, 28, 172, 220,
1778 68, 0, 188, 124, 184, 224, 192, 104,
1779 132, 100, 240, 200, 152, 160, 244, 44,
1780 96, 204, 144, 16, 140, 56, 232, 216,
1781 208, 4, 76, 212, 136, 248, 80, 168,
1782 156, 88, 32, 112, 148, 12, 36, 60,
1786 perl spot.perl '($x-3.5)*($x-3.5)+($y-3.5)*($y-3.5)'
1788 240, 232, 200, 136, 140, 192, 228, 248,
1789 220, 148, 100, 76, 80, 104, 152, 212,
1790 180, 116, 56, 32, 36, 60, 120, 176,
1791 156, 64, 28, 0, 8, 44, 88, 160,
1792 128, 92, 24, 12, 4, 40, 68, 132,
1793 184, 96, 48, 20, 16, 52, 108, 188,
1794 216, 144, 112, 72, 84, 124, 164, 224,
1795 244, 236, 196, 168, 172, 204, 208, 252,
1799 'min(dist(1.5, 1.5),dist(5.5,1.5),dist(1.5,5.5),dist(5.5,5.5))'
1801 196, 72, 104, 220, 200, 80, 112, 224,
1802 76, 4, 24, 136, 84, 8, 32, 144,
1803 108, 28, 52, 168, 116, 36, 56, 176,
1804 216, 140, 172, 244, 228, 148, 180, 248,
1805 204, 92, 124, 236, 192, 68, 96, 208,
1806 88, 12, 44, 156, 64, 0, 16, 128,
1807 120, 40, 60, 188, 100, 20, 48, 160,
1808 232, 152, 184, 252, 212, 132, 164, 240,
1811 perl spot.perl '$y-3'
1813 160, 164, 168, 172, 176, 180, 184, 188,
1814 128, 132, 136, 140, 144, 148, 152, 156,
1815 32, 36, 40, 44, 48, 52, 56, 60,
1816 0, 4, 8, 12, 16, 20, 24, 28,
1817 64, 68, 72, 76, 80, 84, 88, 92,
1818 96, 100, 104, 108, 112, 116, 120, 124,
1819 192, 196, 200, 204, 208, 212, 216, 220,
1820 224, 228, 232, 236, 240, 244, 248, 252,
1823 perl spot.perl '$x-3'
1825 180, 100, 40, 12, 44, 104, 184, 232,
1826 204, 148, 60, 16, 64, 128, 208, 224,
1827 212, 144, 76, 8, 80, 132, 216, 244,
1828 160, 112, 68, 20, 84, 108, 172, 236,
1829 176, 96, 72, 28, 88, 152, 188, 228,
1830 200, 124, 92, 0, 32, 116, 164, 240,
1831 168, 120, 36, 24, 48, 136, 192, 248,
1832 196, 140, 52, 4, 56, 156, 220, 252,
1835 perl spot.perl '$y+$x-7'
1837 248, 232, 224, 192, 140, 92, 52, 28,
1838 240, 220, 196, 144, 108, 60, 12, 64,
1839 216, 180, 148, 116, 76, 20, 80, 128,
1840 204, 152, 104, 44, 16, 72, 100, 160,
1841 164, 96, 68, 24, 56, 112, 168, 176,
1842 124, 40, 8, 36, 88, 136, 184, 212,
1843 84, 4, 32, 120, 156, 188, 228, 236,
1844 0, 48, 132, 172, 200, 208, 244, 252,
1847 perl spot.perl '$y-$x'
1849 0, 32, 116, 172, 184, 216, 236, 252,
1850 56, 8, 72, 132, 136, 200, 228, 240,
1851 100, 36, 12, 40, 92, 144, 204, 220,
1852 168, 120, 60, 16, 44, 96, 156, 176,
1853 180, 164, 112, 48, 28, 52, 128, 148,
1854 208, 192, 152, 88, 84, 20, 64, 104,
1855 232, 224, 196, 140, 108, 68, 24, 76,
1856 248, 244, 212, 188, 160, 124, 80, 4,
1860 good for display, bad for print
1863 0, 128, 32, 192, 8, 136, 40, 200,
1864 224, 64, 160, 112, 232, 72, 168, 120,
1865 48, 144, 16, 208, 56, 152, 24, 216,
1866 176, 96, 240, 80, 184, 104, 248, 88,
1867 12, 140, 44, 204, 4, 132, 36, 196,
1868 236, 76, 172, 124, 228, 68, 164, 116,
1869 60, 156, 28, 220, 52, 148, 20, 212,
1870 188, 108, 252, 92, 180, 100, 244, 84,
1875 transparent_ordered(i_quantize *quant, i_palidx *data, i_img *img,
1876 i_palidx trans_index)
1878 unsigned char *spot;
1881 int trans_chan = img->channels > 2 ? 3 : 1;
1882 if (quant->tr_orddith == od_custom)
1883 spot = quant->tr_custom;
1885 spot = orddith_maps[quant->tr_orddith];
1887 line = mymalloc(img->xsize * sizeof(i_sample_t));
1888 for (y = 0; y < img->ysize; ++y) {
1889 i_gsamp(img, 0, img->xsize, y, line, &trans_chan, 1);
1890 for (x = 0; x < img->xsize; ++x) {
1891 if (line[x] < spot[(x&7)+(y&7)*8])
1892 data[x+y*img->xsize] = trans_index;