1 /*
2 ** Copyright (C) 1989, 1991 by Jef Poskanzer.
3 ** Copyright (C) 1997, 2000, 2002 by Greg Roelofs; based on an idea by
4 ** Stefan Schneider.
5 ** © 2009-2013 by Kornel Lesinski.
6 **
7 ** Permission to use, copy, modify, and distribute this software and its
8 ** documentation for any purpose and without fee is hereby granted, provided
9 ** that the above copyright notice appear in all copies and that both that
10 ** copyright notice and this permission notice appear in supporting
11 ** documentation. This software is provided "as is" without express or
12 ** implied warranty.
13 */
14
15 #include <stdlib.h>
16 #include <stddef.h>
17
18 #include "libimagequant.h"
19 #include "pam.h"
20 #include "mediancut.h"
21
22 #define index_of_channel(ch) (offsetof(f_pixel,ch)/sizeof(float))
23
24 static f_pixel averagepixels (unsigned int clrs, const hist_item achv[],
25 float min_opaque_val, const f_pixel center);
26
27 struct box
28 {
29 f_pixel color;
30 f_pixel variance;
31 double sum, total_error, max_error;
32 unsigned int ind;
33 unsigned int colors;
34 };
35
36 ALWAYS_INLINE static double variance_diff (double val,
37 const double good_enough);
38 inline static double
variance_diff(double val,const double good_enough)39 variance_diff (double val, const double good_enough)
40 {
41 val *= val;
42 if (val < good_enough * good_enough)
43 return val * 0.25;
44 return val;
45 }
46
47 /** Weighted per-channel variance of the box. It's used to decide which channel to split by */
48 static f_pixel
box_variance(const hist_item achv[],const struct box * box)49 box_variance (const hist_item achv[], const struct box *box)
50 {
51 f_pixel mean = box->color;
52 double variancea = 0, variancer = 0, varianceg = 0, varianceb = 0;
53
54 for (unsigned int i = 0; i < box->colors; ++i) {
55 f_pixel px = achv[box->ind + i].acolor;
56 double weight = achv[box->ind + i].adjusted_weight;
57 variancea += variance_diff (mean.a - px.a, 2.0 / 256.0) * weight;
58 variancer += variance_diff (mean.r - px.r, 1.0 / 256.0) * weight;
59 varianceg += variance_diff (mean.g - px.g, 1.0 / 256.0) * weight;
60 varianceb += variance_diff (mean.b - px.b, 1.0 / 256.0) * weight;
61 }
62
63 return (f_pixel) {
64 .a = variancea * (4.0 / 16.0),.r = variancer * (7.0 / 16.0),.g =
65 varianceg * (9.0 / 16.0),.b = varianceb * (5.0 / 16.0),};
66 }
67
68 static double
box_max_error(const hist_item achv[],const struct box * box)69 box_max_error (const hist_item achv[], const struct box *box)
70 {
71 f_pixel mean = box->color;
72 double max_error = 0;
73 unsigned int i;
74
75 for (i = 0; i < box->colors; ++i) {
76 const double diff = colordifference (mean, achv[box->ind + i].acolor);
77 if (diff > max_error) {
78 max_error = diff;
79 }
80 }
81 return max_error;
82 }
83
84 ALWAYS_INLINE static double color_weight (f_pixel median, hist_item h);
85
86 static inline void
hist_item_swap(hist_item * l,hist_item * r)87 hist_item_swap (hist_item * l, hist_item * r)
88 {
89 if (l != r) {
90 hist_item t = *l;
91 *l = *r;
92 *r = t;
93 }
94 }
95
96 ALWAYS_INLINE static unsigned int qsort_pivot (const hist_item * const base,
97 const unsigned int len);
98 inline static unsigned int
qsort_pivot(const hist_item * const base,const unsigned int len)99 qsort_pivot (const hist_item * const base, const unsigned int len)
100 {
101 if (len < 32) {
102 return len / 2;
103 }
104
105 {
106 const unsigned int aidx = 8, bidx = len / 2, cidx = len - 1;
107 const unsigned int a = base[aidx].tmp.sort_value, b =
108 base[bidx].tmp.sort_value, c = base[cidx].tmp.sort_value;
109 return (a < b) ? ((b < c) ? bidx : ((a < c) ? cidx : aidx))
110 : ((b > c) ? bidx : ((a < c) ? aidx : cidx));
111 }
112 }
113
114 ALWAYS_INLINE static unsigned int qsort_partition (hist_item * const base,
115 const unsigned int len);
116 inline static unsigned int
qsort_partition(hist_item * const base,const unsigned int len)117 qsort_partition (hist_item * const base, const unsigned int len)
118 {
119 unsigned int l = 1, r = len;
120 if (len >= 8) {
121 hist_item_swap (&base[0], &base[qsort_pivot (base, len)]);
122 }
123
124 {
125 const unsigned int pivot_value = base[0].tmp.sort_value;
126 while (l < r) {
127 if (base[l].tmp.sort_value >= pivot_value) {
128 l++;
129 } else {
130 while (l < --r && base[r].tmp.sort_value <= pivot_value) {
131 }
132 hist_item_swap (&base[l], &base[r]);
133 }
134 }
135 l--;
136 hist_item_swap (&base[0], &base[l]);
137 }
138
139 return l;
140 }
141
142 /** quick select algorithm */
143 static void
hist_item_sort_range(hist_item * base,unsigned int len,unsigned int sort_start)144 hist_item_sort_range (hist_item * base, unsigned int len,
145 unsigned int sort_start)
146 {
147 for (;;) {
148 const unsigned int l = qsort_partition (base, len), r = l + 1;
149
150 if (l > 0 && sort_start < l) {
151 len = l;
152 } else if (r < len && sort_start > r) {
153 base += r;
154 len -= r;
155 sort_start -= r;
156 } else
157 break;
158 }
159 }
160
161 /** sorts array to make sum of weights lower than halfvar one side, returns edge between <halfvar and >halfvar parts of the set */
162 static hist_item *
hist_item_sort_halfvar(hist_item * base,unsigned int len,double * const lowervar,const double halfvar)163 hist_item_sort_halfvar (hist_item * base, unsigned int len,
164 double *const lowervar, const double halfvar)
165 {
166 do {
167 const unsigned int l = qsort_partition (base, len), r = l + 1;
168
169 // check if sum of left side is smaller than half,
170 // if it is, then it doesn't need to be sorted
171 unsigned int t = 0;
172 double tmpsum = *lowervar;
173 while (t <= l && tmpsum < halfvar)
174 tmpsum += base[t++].color_weight;
175
176 if (tmpsum < halfvar) {
177 *lowervar = tmpsum;
178 } else {
179 if (l > 0) {
180 hist_item *res = hist_item_sort_halfvar (base, l, lowervar, halfvar);
181 if (res)
182 return res;
183 } else {
184 // End of left recursion. This will be executed in order from the first element.
185 *lowervar += base[0].color_weight;
186 if (*lowervar > halfvar)
187 return &base[0];
188 }
189 }
190
191 if (len > r) {
192 base += r;
193 len -= r; // tail-recursive "call"
194 } else {
195 *lowervar += base[r].color_weight;
196 return (*lowervar > halfvar) ? &base[r] : NULL;
197 }
198 } while (1);
199 }
200
201 static f_pixel get_median (const struct box *b, hist_item achv[]);
202
203 typedef struct
204 {
205 unsigned int chan;
206 float variance;
207 } channelvariance;
208
209 static int
comparevariance(const void * ch1,const void * ch2)210 comparevariance (const void *ch1, const void *ch2)
211 {
212 return ((const channelvariance *) ch1)->variance >
213 ((const channelvariance *) ch2)->variance ? -1 : (((const channelvariance
214 *) ch1)->variance <
215 ((const channelvariance *) ch2)->variance ? 1 : 0);
216 }
217
218 /** Finds which channels need to be sorted first and preproceses achv for fast sort */
219 static double
prepare_sort(struct box * b,hist_item achv[])220 prepare_sort (struct box *b, hist_item achv[])
221 {
222 /*
223 ** Sort dimensions by their variance, and then sort colors first by dimension with highest variance
224 */
225 double totalvar = 0;
226 channelvariance channels[4] = {
227 {index_of_channel (r), b->variance.r},
228 {index_of_channel (g), b->variance.g},
229 {index_of_channel (b), b->variance.b},
230 {index_of_channel (a), b->variance.a},
231 };
232
233 qsort (channels, 4, sizeof (channels[0]), comparevariance);
234
235 for (unsigned int i = 0; i < b->colors; i++) {
236 const float *chans = (const float *) &achv[b->ind + i].acolor;
237 // Only the first channel really matters. When trying median cut many times
238 // with different histogram weights, I don't want sort randomness to influence outcome.
239 achv[b->ind + i].tmp.sort_value =
240 ((unsigned int) (chans[channels[0].chan] *
241 65535.0) << 16) | (unsigned int) ((chans[channels[2].chan] +
242 chans[channels[1].chan] / 2.0 +
243 chans[channels[3].chan] / 4.0) * 65535.0);
244 }
245
246 {
247 const f_pixel median = get_median (b, achv);
248
249 // box will be split to make color_weight of each side even
250 const unsigned int ind = b->ind, end = ind + b->colors;
251 for (unsigned int j = ind; j < end; j++)
252 totalvar += (achv[j].color_weight = color_weight (median, achv[j]));
253 }
254 return totalvar / 2.0;
255 }
256
257 /** finds median in unsorted set by sorting only minimum required */
258 static f_pixel
get_median(const struct box * b,hist_item achv[])259 get_median (const struct box *b, hist_item achv[])
260 {
261 const unsigned int median_start = (b->colors - 1) / 2;
262
263 hist_item_sort_range (&(achv[b->ind]), b->colors, median_start);
264
265 if (b->colors & 1)
266 return achv[b->ind + median_start].acolor;
267
268 // technically the second color is not guaranteed to be sorted correctly
269 // but most of the time it is good enough to be useful
270 return averagepixels (2, &achv[b->ind + median_start], 1.0, (f_pixel) {
271 0.5, 0.5, 0.5, 0.5}
272 );
273 }
274
275 /*
276 ** Find the best splittable box. -1 if no boxes are splittable.
277 */
278 static int
best_splittable_box(struct box * bv,unsigned int boxes,const double max_mse)279 best_splittable_box (struct box *bv, unsigned int boxes, const double max_mse)
280 {
281 int bi = -1;
282 double maxsum = 0;
283 unsigned int i;
284
285 for (i = 0; i < boxes; i++) {
286 if (bv[i].colors < 2) {
287 continue;
288 }
289 // looks only at max variance, because it's only going to split by it
290 {
291 const double cv =
292 MAX (bv[i].variance.r, MAX (bv[i].variance.g, bv[i].variance.b));
293 double thissum = bv[i].sum * MAX (bv[i].variance.a, cv);
294
295 if (bv[i].max_error > max_mse) {
296 thissum = thissum * bv[i].max_error / max_mse;
297 }
298
299 if (thissum > maxsum) {
300 maxsum = thissum;
301 bi = i;
302 }
303 }
304 }
305 return bi;
306 }
307
308 inline static double
color_weight(f_pixel median,hist_item h)309 color_weight (f_pixel median, hist_item h)
310 {
311 float diff = colordifference (median, h.acolor);
312 // if color is "good enough", don't split further
313 if (diff < 2.f / 256.f / 256.f)
314 diff /= 2.f;
315 return sqrt (diff) * (sqrt (1.0 + h.adjusted_weight) - 1.0);
316 }
317
318 static void set_colormap_from_boxes (colormap * map, struct box *bv,
319 unsigned int boxes, hist_item * achv);
320 static void adjust_histogram (hist_item * achv, const colormap * map,
321 const struct box *bv, unsigned int boxes);
322
323 static double
box_error(const struct box * box,const hist_item achv[])324 box_error (const struct box *box, const hist_item achv[])
325 {
326 f_pixel avg = box->color;
327 unsigned int i;
328 double total_error = 0;
329
330 for (i = 0; i < box->colors; ++i) {
331 total_error +=
332 colordifference (avg,
333 achv[box->ind + i].acolor) * achv[box->ind + i].perceptual_weight;
334 }
335
336 return total_error;
337 }
338
339
340 static bool
total_box_error_below_target(double target_mse,struct box bv[],unsigned int boxes,const histogram * hist)341 total_box_error_below_target (double target_mse, struct box bv[],
342 unsigned int boxes, const histogram * hist)
343 {
344 double total_error = 0;
345 unsigned int i;
346
347 target_mse *= hist->total_perceptual_weight;
348
349 for (i = 0; i < boxes; i++) {
350 // error is (re)calculated lazily
351 if (bv[i].total_error >= 0) {
352 total_error += bv[i].total_error;
353 }
354 if (total_error > target_mse)
355 return false;
356 }
357
358 for (i = 0; i < boxes; i++) {
359 if (bv[i].total_error < 0) {
360 bv[i].total_error = box_error (&bv[i], hist->achv);
361 total_error += bv[i].total_error;
362 }
363 if (total_error > target_mse)
364 return false;
365 }
366
367 return true;
368 }
369
370 /*
371 ** Here is the fun part, the median-cut colormap generator. This is based
372 ** on Paul Heckbert's paper, "Color Image Quantization for Frame Buffer
373 ** Display," SIGGRAPH 1982 Proceedings, page 297.
374 */
375 LIQ_PRIVATE colormap *
mediancut(histogram * hist,const float min_opaque_val,unsigned int newcolors,const double target_mse,const double max_mse,void * (* malloc)(size_t),void (* free)(void *))376 mediancut (histogram * hist, const float min_opaque_val, unsigned int newcolors,
377 const double target_mse, const double max_mse, void *(*malloc) (size_t),
378 void (*free) (void *))
379 {
380 hist_item *achv = hist->achv;
381 struct box *bv = g_alloca (sizeof (struct box) * newcolors);
382 unsigned int i, boxes, subset_size;
383 colormap *representative_subset = NULL;
384 colormap *map;
385
386 /*
387 ** Set up the initial box.
388 */
389 bv[0].ind = 0;
390 bv[0].colors = hist->size;
391 bv[0].color =
392 averagepixels (bv[0].colors, &achv[bv[0].ind], min_opaque_val, (f_pixel) {
393 0.5, 0.5, 0.5, 0.5});
394 bv[0].variance = box_variance (achv, &bv[0]);
395 bv[0].max_error = box_max_error (achv, &bv[0]);
396 bv[0].sum = 0;
397 bv[0].total_error = -1;
398 for (i = 0; i < bv[0].colors; i++)
399 bv[0].sum += achv[i].adjusted_weight;
400
401 boxes = 1;
402
403 // remember smaller palette for fast searching
404 subset_size = ceilf (powf (newcolors, 0.7f));
405
406 /*
407 ** Main loop: split boxes until we have enough.
408 */
409 while (boxes < newcolors) {
410 unsigned int indx, clrs;
411 unsigned int break_at, i;
412 double lowervar = 0, halfvar, current_max_mse;
413 hist_item *break_p;
414 double sm, lowersum;
415 int bi;
416 f_pixel previous_center;
417
418 if (boxes == subset_size) {
419 representative_subset = pam_colormap (boxes, malloc, free);
420 set_colormap_from_boxes (representative_subset, bv, boxes, achv);
421 }
422 // first splits boxes that exceed quality limit (to have colors for things like odd green pixel),
423 // later raises the limit to allow large smooth areas/gradients get colors.
424 current_max_mse = max_mse + (boxes / (double) newcolors) * 16.0 * max_mse;
425 bi = best_splittable_box (bv, boxes, current_max_mse);
426 if (bi < 0)
427 break; /* ran out of colors! */
428
429 indx = bv[bi].ind;
430 clrs = bv[bi].colors;
431
432 /*
433 Classic implementation tries to get even number of colors or pixels in each subdivision.
434
435 Here, instead of popularity I use (sqrt(popularity)*variance) metric.
436 Each subdivision balances number of pixels (popular colors) and low variance -
437 boxes can be large if they have similar colors. Later boxes with high variance
438 will be more likely to be split.
439
440 Median used as expected value gives much better results than mean.
441 */
442 halfvar = prepare_sort (&bv[bi], achv);
443
444 // hist_item_sort_halfvar sorts and sums lowervar at the same time
445 // returns item to break at …minus one, which does smell like an off-by-one error.
446 break_p = hist_item_sort_halfvar (&achv[indx], clrs, &lowervar, halfvar);
447 break_at = MIN (clrs - 1, break_p - &achv[indx] + 1);
448
449 /*
450 ** Split the box.
451 */
452 sm = bv[bi].sum;
453 lowersum = 0;
454 for (i = 0; i < break_at; i++)
455 lowersum += achv[indx + i].adjusted_weight;
456
457 previous_center = bv[bi].color;
458 bv[bi].colors = break_at;
459 bv[bi].sum = lowersum;
460 bv[bi].color =
461 averagepixels (bv[bi].colors, &achv[bv[bi].ind], min_opaque_val,
462 previous_center);
463 bv[bi].total_error = -1;
464 bv[bi].variance = box_variance (achv, &bv[bi]);
465 bv[bi].max_error = box_max_error (achv, &bv[bi]);
466 bv[boxes].ind = indx + break_at;
467 bv[boxes].colors = clrs - break_at;
468 bv[boxes].sum = sm - lowersum;
469 bv[boxes].color =
470 averagepixels (bv[boxes].colors, &achv[bv[boxes].ind], min_opaque_val,
471 previous_center);
472 bv[boxes].total_error = -1;
473 bv[boxes].variance = box_variance (achv, &bv[boxes]);
474 bv[boxes].max_error = box_max_error (achv, &bv[boxes]);
475
476 ++boxes;
477
478 if (total_box_error_below_target (target_mse, bv, boxes, hist)) {
479 break;
480 }
481 }
482
483 map = pam_colormap (boxes, malloc, free);
484 set_colormap_from_boxes (map, bv, boxes, achv);
485
486 map->subset_palette = representative_subset;
487 adjust_histogram (achv, map, bv, boxes);
488
489 return map;
490 }
491
492 static void
set_colormap_from_boxes(colormap * map,struct box * bv,unsigned int boxes,hist_item * achv)493 set_colormap_from_boxes (colormap * map, struct box *bv, unsigned int boxes,
494 hist_item * achv)
495 {
496 /*
497 ** Ok, we've got enough boxes. Now choose a representative color for
498 ** each box. There are a number of possible ways to make this choice.
499 ** One would be to choose the center of the box; this ignores any structure
500 ** within the boxes. Another method would be to average all the colors in
501 ** the box - this is the method specified in Heckbert's paper.
502 */
503
504 for (unsigned int bi = 0; bi < boxes; ++bi) {
505 map->palette[bi].acolor = bv[bi].color;
506
507 /* store total color popularity (perceptual_weight is approximation of it) */
508 map->palette[bi].popularity = 0;
509 for (unsigned int i = bv[bi].ind; i < bv[bi].ind + bv[bi].colors; i++) {
510 map->palette[bi].popularity += achv[i].perceptual_weight;
511 }
512 }
513 }
514
515 /* increase histogram popularity by difference from the final color (this is used as part of feedback loop) */
516 static void
adjust_histogram(hist_item * achv,const colormap * map,const struct box * bv,unsigned int boxes)517 adjust_histogram (hist_item * achv, const colormap * map, const struct box *bv,
518 unsigned int boxes)
519 {
520 for (unsigned int bi = 0; bi < boxes; ++bi) {
521 for (unsigned int i = bv[bi].ind; i < bv[bi].ind + bv[bi].colors; i++) {
522 achv[i].adjusted_weight *=
523 sqrt (1.0 + colordifference (map->palette[bi].acolor,
524 achv[i].acolor) / 4.0);
525 achv[i].tmp.likely_colormap_index = bi;
526 }
527 }
528 }
529
530 static f_pixel
averagepixels(unsigned int clrs,const hist_item achv[],const float min_opaque_val,const f_pixel center)531 averagepixels (unsigned int clrs, const hist_item achv[],
532 const float min_opaque_val, const f_pixel center)
533 {
534 double r = 0, g = 0, b = 0, a = 0, new_a = 0, sum = 0;
535 float maxa = 0;
536
537 // first find final opacity in order to blend colors at that opacity
538 for (unsigned int i = 0; i < clrs; ++i) {
539 const f_pixel px = achv[i].acolor;
540 new_a += px.a * achv[i].adjusted_weight;
541 sum += achv[i].adjusted_weight;
542
543 /* find if there are opaque colors, in case we're supposed to preserve opacity exactly (ie_bug) */
544 if (px.a > maxa)
545 maxa = px.a;
546 }
547
548 if (sum)
549 new_a /= sum;
550
551 /** if there was at least one completely opaque color, "round" final color to opaque */
552 if (new_a >= min_opaque_val && maxa >= (255.0 / 256.0))
553 new_a = 1;
554
555 sum = 0;
556 // reverse iteration for cache locality with previous loop
557 for (int i = clrs - 1; i >= 0; i--) {
558 double tmp, weight = 1.0f;
559 f_pixel px = achv[i].acolor;
560
561 /* give more weight to colors that are further away from average
562 this is intended to prevent desaturation of images and fading of whites
563 */
564 tmp = (center.r - px.r);
565 weight += tmp * tmp;
566 tmp = (center.g - px.g);
567 weight += tmp * tmp;
568 tmp = (center.b - px.b);
569 weight += tmp * tmp;
570
571 weight *= achv[i].adjusted_weight;
572 sum += weight;
573
574 if (px.a) {
575 px.r /= px.a;
576 px.g /= px.a;
577 px.b /= px.a;
578 }
579
580 r += px.r * new_a * weight;
581 g += px.g * new_a * weight;
582 b += px.b * new_a * weight;
583 a += new_a * weight;
584 }
585
586 if (sum) {
587 a /= sum;
588 r /= sum;
589 g /= sum;
590 b /= sum;
591 }
592
593 assert (!isnan (r) && !isnan (g) && !isnan (b) && !isnan (a));
594
595 return (f_pixel) {
596 .r = r,.g = g,.b = b,.a = a};
597 }
598