Pillow
1876 строк · 49.4 Кб
1/*
2* The Python Imaging Library
3* $Id$
4*
5* image quantizer
6*
7* history:
8* 1998-09-10 tjs Contributed
9* 1998-12-29 fl Added to PIL 1.0b1
10* 2004-02-21 fl Fixed bogus free() on quantization error
11* 2005-02-07 fl Limit number of colors to 256
12*
13* Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
14*
15* Copyright (c) 1998 by Toby J Sargeant
16* Copyright (c) 1998-2004 by Secret Labs AB. All rights reserved.
17*
18* See the README file for information on usage and redistribution.
19*/
20
21#include "Imaging.h"
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <memory.h>
26#include <time.h>
27
28#include "QuantTypes.h"
29#include "QuantOctree.h"
30#include "QuantPngQuant.h"
31#include "QuantHash.h"
32#include "QuantHeap.h"
33
34/* MSVC9.0 */
35#ifndef UINT32_MAX
36#define UINT32_MAX 0xffffffff
37#endif
38
39// #define DEBUG
40// #define TEST_NEAREST_NEIGHBOUR
41
42typedef struct {
43uint32_t scale;
44} PixelHashData;
45
46typedef struct _PixelList {
47struct _PixelList *next[3], *prev[3];
48Pixel p;
49unsigned int flag : 1;
50int count;
51} PixelList;
52
53typedef struct _BoxNode {
54struct _BoxNode *l, *r;
55PixelList *head[3], *tail[3];
56int axis;
57int volume;
58uint32_t pixelCount;
59} BoxNode;
60
61#define _SQR(x) ((x) * (x))
62#define _DISTSQR(p1, p2) \
63_SQR((int)((p1)->c.r) - (int)((p2)->c.r)) + \
64_SQR((int)((p1)->c.g) - (int)((p2)->c.g)) + \
65_SQR((int)((p1)->c.b) - (int)((p2)->c.b))
66
67#define MAX_HASH_ENTRIES 65536
68
69#define PIXEL_HASH(r, g, b) \
70(((unsigned int)(r)) * 463 ^ ((unsigned int)(g) << 8) * 10069 ^ \
71((unsigned int)(b) << 16) * 64997)
72
73#define PIXEL_UNSCALE(p, q, s) \
74((q)->c.r = (p)->c.r << (s)), ((q)->c.g = (p)->c.g << (s)), \
75((q)->c.b = (p)->c.b << (s))
76
77#define PIXEL_SCALE(p, q, s) \
78((q)->c.r = (p)->c.r >> (s)), ((q)->c.g = (p)->c.g >> (s)), \
79((q)->c.b = (p)->c.b >> (s))
80
81static uint32_t
82unshifted_pixel_hash(const HashTable *h, const Pixel pixel) {
83return PIXEL_HASH(pixel.c.r, pixel.c.g, pixel.c.b);
84}
85
86static int
87unshifted_pixel_cmp(const HashTable *h, const Pixel pixel1, const Pixel pixel2) {
88if (pixel1.c.r == pixel2.c.r) {
89if (pixel1.c.g == pixel2.c.g) {
90if (pixel1.c.b == pixel2.c.b) {
91return 0;
92} else {
93return (int)(pixel1.c.b) - (int)(pixel2.c.b);
94}
95} else {
96return (int)(pixel1.c.g) - (int)(pixel2.c.g);
97}
98} else {
99return (int)(pixel1.c.r) - (int)(pixel2.c.r);
100}
101}
102
103static uint32_t
104pixel_hash(const HashTable *h, const Pixel pixel) {
105PixelHashData *d = (PixelHashData *)hashtable_get_user_data(h);
106return PIXEL_HASH(
107pixel.c.r >> d->scale, pixel.c.g >> d->scale, pixel.c.b >> d->scale
108);
109}
110
111static int
112pixel_cmp(const HashTable *h, const Pixel pixel1, const Pixel pixel2) {
113PixelHashData *d = (PixelHashData *)hashtable_get_user_data(h);
114uint32_t A, B;
115A = PIXEL_HASH(
116pixel1.c.r >> d->scale, pixel1.c.g >> d->scale, pixel1.c.b >> d->scale
117);
118B = PIXEL_HASH(
119pixel2.c.r >> d->scale, pixel2.c.g >> d->scale, pixel2.c.b >> d->scale
120);
121return (A == B) ? 0 : ((A < B) ? -1 : 1);
122}
123
124static void
125exists_count_func(const HashTable *h, const Pixel key, uint32_t *val) {
126*val += 1;
127}
128
129static void
130new_count_func(const HashTable *h, const Pixel key, uint32_t *val) {
131*val = 1;
132}
133
134static void
135rehash_collide(
136const HashTable *h, Pixel *keyp, uint32_t *valp, Pixel newkey, uint32_t newval
137) {
138*valp += newval;
139}
140
141/* %% */
142
143static HashTable *
144create_pixel_hash(Pixel *pixelData, uint32_t nPixels) {
145PixelHashData *d;
146HashTable *hash;
147uint32_t i;
148#ifdef DEBUG
149uint32_t timer, timer2, timer3;
150#endif
151
152/* malloc check ok, small constant allocation */
153d = malloc(sizeof(PixelHashData));
154if (!d) {
155return NULL;
156}
157hash = hashtable_new(pixel_hash, pixel_cmp);
158hashtable_set_user_data(hash, d);
159d->scale = 0;
160#ifdef DEBUG
161timer = timer3 = clock();
162#endif
163for (i = 0; i < nPixels; i++) {
164if (!hashtable_insert_or_update_computed(
165hash, pixelData[i], new_count_func, exists_count_func
166)) {
167;
168}
169while (hashtable_get_count(hash) > MAX_HASH_ENTRIES) {
170d->scale++;
171#ifdef DEBUG
172printf("rehashing - new scale: %d\n", (int)d->scale);
173timer2 = clock();
174#endif
175hashtable_rehash_compute(hash, rehash_collide);
176#ifdef DEBUG
177timer2 = clock() - timer2;
178printf("rehash took %f sec\n", timer2 / (double)CLOCKS_PER_SEC);
179timer += timer2;
180#endif
181}
182}
183#ifdef DEBUG
184printf("inserts took %f sec\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
185#endif
186#ifdef DEBUG
187printf("total %f sec\n", (clock() - timer3) / (double)CLOCKS_PER_SEC);
188#endif
189return hash;
190}
191
192static void
193destroy_pixel_hash(HashTable *hash) {
194PixelHashData *d = (PixelHashData *)hashtable_get_user_data(hash);
195if (d) {
196free(d);
197}
198hashtable_free(hash);
199}
200
201/* 1. hash quantized pixels. */
202/* 2. create R,G,B lists of sorted quantized pixels. */
203/* 3. median cut. */
204/* 4. build hash table from median cut boxes. */
205/* 5. for each pixel, compute entry in hash table, and hence median cut box. */
206/* 6. compute median cut box pixel averages. */
207/* 7. map each pixel to nearest average. */
208
209static int
210compute_box_volume(BoxNode *b) {
211unsigned char rl, rh, gl, gh, bl, bh;
212if (b->volume >= 0) {
213return b->volume;
214}
215if (!b->head[0]) {
216b->volume = 0;
217} else {
218rh = b->head[0]->p.c.r;
219rl = b->tail[0]->p.c.r;
220gh = b->head[1]->p.c.g;
221gl = b->tail[1]->p.c.g;
222bh = b->head[2]->p.c.b;
223bl = b->tail[2]->p.c.b;
224b->volume = (rh - rl + 1) * (gh - gl + 1) * (bh - bl + 1);
225}
226return b->volume;
227}
228
229static void
230hash_to_list(const HashTable *h, const Pixel pixel, const uint32_t count, void *u) {
231PixelHashData *d = (PixelHashData *)hashtable_get_user_data(h);
232PixelList **pl = (PixelList **)u;
233PixelList *p;
234int i;
235Pixel q;
236
237PIXEL_SCALE(&pixel, &q, d->scale);
238
239/* malloc check ok, small constant allocation */
240p = malloc(sizeof(PixelList));
241if (!p) {
242return;
243}
244
245p->flag = 0;
246p->p = q;
247p->count = count;
248for (i = 0; i < 3; i++) {
249p->next[i] = pl[i];
250p->prev[i] = NULL;
251if (pl[i]) {
252pl[i]->prev[i] = p;
253}
254pl[i] = p;
255}
256}
257
258static PixelList *
259mergesort_pixels(PixelList *head, int i) {
260PixelList *c, *t, *a, *b, *p;
261if (!head || !head->next[i]) {
262if (head) {
263head->next[i] = NULL;
264head->prev[i] = NULL;
265}
266return head;
267}
268for (c = t = head; c && t;
269c = c->next[i], t = (t->next[i]) ? t->next[i]->next[i] : NULL);
270if (c) {
271if (c->prev[i]) {
272c->prev[i]->next[i] = NULL;
273}
274c->prev[i] = NULL;
275}
276a = mergesort_pixels(head, i);
277b = mergesort_pixels(c, i);
278head = NULL;
279p = NULL;
280while (a && b) {
281if (a->p.a.v[i] > b->p.a.v[i]) {
282c = a;
283a = a->next[i];
284} else {
285c = b;
286b = b->next[i];
287}
288c->prev[i] = p;
289c->next[i] = NULL;
290if (p) {
291p->next[i] = c;
292}
293p = c;
294if (!head) {
295head = c;
296}
297}
298if (a) {
299c->next[i] = a;
300a->prev[i] = c;
301} else if (b) {
302c->next[i] = b;
303b->prev[i] = c;
304}
305return head;
306}
307
308#ifdef DEBUG
309static int
310test_sorted(PixelList *pl[3]) {
311int i, l;
312PixelList *t;
313
314for (i = 0; i < 3; i++) {
315l = 256;
316for (t = pl[i]; t; t = t->next[i]) {
317if (l < t->p.a.v[i]) {
318return 0;
319}
320l = t->p.a.v[i];
321}
322}
323return 1;
324}
325#endif
326
327static int
328box_heap_cmp(const Heap *h, const void *A, const void *B) {
329BoxNode *a = (BoxNode *)A;
330BoxNode *b = (BoxNode *)B;
331return (int)a->pixelCount - (int)b->pixelCount;
332}
333
334#define LUMINANCE(p) (77 * (p)->c.r + 150 * (p)->c.g + 29 * (p)->c.b)
335
336static int
337splitlists(
338PixelList *h[3],
339PixelList *t[3],
340PixelList *nh[2][3],
341PixelList *nt[2][3],
342uint32_t nCount[2],
343int axis,
344uint32_t pixelCount
345) {
346uint32_t left;
347
348PixelList *l, *r, *c, *n;
349int i;
350int nRight;
351#ifdef DEBUG
352int nLeft;
353#endif
354int splitColourVal;
355
356#ifdef DEBUG
357{
358PixelList *_prevTest, *_nextTest;
359int _i, _nextCount[3], _prevCount[3];
360for (_i = 0; _i < 3; _i++) {
361for (_nextCount[_i] = 0, _nextTest = h[_i];
362_nextTest && _nextTest->next[_i];
363_nextTest = _nextTest->next[_i], _nextCount[_i]++);
364for (_prevCount[_i] = 0, _prevTest = t[_i];
365_prevTest && _prevTest->prev[_i];
366_prevTest = _prevTest->prev[_i], _prevCount[_i]++);
367if (_nextTest != t[_i]) {
368printf("next-list of axis %d does not end at tail\n", _i);
369exit(1);
370}
371if (_prevTest != h[_i]) {
372printf("prev-list of axis %d does not end at head\n", _i);
373exit(1);
374}
375for (; _nextTest && _nextTest->prev[_i]; _nextTest = _nextTest->prev[_i]);
376for (; _prevTest && _prevTest->next[_i]; _prevTest = _prevTest->next[_i]);
377if (_nextTest != h[_i]) {
378printf("next-list of axis %d does not loop back to head\n", _i);
379exit(1);
380}
381if (_prevTest != t[_i]) {
382printf("prev-list of axis %d does not loop back to tail\n", _i);
383exit(1);
384}
385}
386for (_i = 1; _i < 3; _i++) {
387if (_prevCount[_i] != _prevCount[_i - 1] ||
388_nextCount[_i] != _nextCount[_i - 1] ||
389_prevCount[_i] != _nextCount[_i]) {
390printf(
391"{%d %d %d} {%d %d %d}\n",
392_prevCount[0],
393_prevCount[1],
394_prevCount[2],
395_nextCount[0],
396_nextCount[1],
397_nextCount[2]
398);
399exit(1);
400}
401}
402}
403#endif
404nCount[0] = nCount[1] = 0;
405nRight = 0;
406#ifdef DEBUG
407nLeft = 0;
408#endif
409for (left = 0, c = h[axis]; c;) {
410left = left + c->count;
411nCount[0] += c->count;
412c->flag = 0;
413#ifdef DEBUG
414nLeft++;
415#endif
416c = c->next[axis];
417if (left * 2 > pixelCount) {
418break;
419}
420}
421if (c) {
422splitColourVal = c->prev[axis]->p.a.v[axis];
423for (; c; c = c->next[axis]) {
424if (splitColourVal != c->p.a.v[axis]) {
425break;
426}
427c->flag = 0;
428#ifdef DEBUG
429nLeft++;
430#endif
431nCount[0] += c->count;
432}
433}
434for (; c; c = c->next[axis]) {
435c->flag = 1;
436nRight++;
437nCount[1] += c->count;
438}
439if (!nRight) {
440for (c = t[axis], splitColourVal = t[axis]->p.a.v[axis]; c; c = c->prev[axis]) {
441if (splitColourVal != c->p.a.v[axis]) {
442break;
443}
444c->flag = 1;
445nRight++;
446#ifdef DEBUG
447nLeft--;
448#endif
449nCount[0] -= c->count;
450nCount[1] += c->count;
451}
452}
453#ifdef DEBUG
454if (!nLeft) {
455for (c = h[axis]; c; c = c->next[axis]) {
456printf("[%d %d %d]\n", c->p.c.r, c->p.c.g, c->p.c.b);
457}
458printf("warning... trivial split\n");
459}
460#endif
461
462for (i = 0; i < 3; i++) {
463l = r = NULL;
464nh[0][i] = nt[0][i] = NULL;
465nh[1][i] = nt[1][i] = NULL;
466for (c = h[i]; c; c = n) {
467n = c->next[i];
468if (c->flag) { /* move pixel to right list*/
469if (r) {
470r->next[i] = c;
471} else {
472nh[1][i] = c;
473}
474c->prev[i] = r;
475r = c;
476} else { /* move pixel to left list */
477if (l) {
478l->next[i] = c;
479} else {
480nh[0][i] = c;
481}
482c->prev[i] = l;
483l = c;
484}
485}
486if (l) {
487l->next[i] = NULL;
488}
489if (r) {
490r->next[i] = NULL;
491}
492nt[0][i] = l;
493nt[1][i] = r;
494}
495return 1;
496}
497
498static int
499split(BoxNode *node) {
500unsigned char rl, rh, gl, gh, bl, bh;
501int f[3];
502int best, axis;
503int i;
504PixelList *heads[2][3];
505PixelList *tails[2][3];
506uint32_t newCounts[2];
507BoxNode *left, *right;
508
509rh = node->head[0]->p.c.r;
510rl = node->tail[0]->p.c.r;
511gh = node->head[1]->p.c.g;
512gl = node->tail[1]->p.c.g;
513bh = node->head[2]->p.c.b;
514bl = node->tail[2]->p.c.b;
515#ifdef DEBUG
516printf("splitting node [%d %d %d] [%d %d %d] ", rl, gl, bl, rh, gh, bh);
517#endif
518f[0] = (rh - rl) * 77;
519f[1] = (gh - gl) * 150;
520f[2] = (bh - bl) * 29;
521
522best = f[0];
523axis = 0;
524for (i = 1; i < 3; i++) {
525if (best < f[i]) {
526best = f[i];
527axis = i;
528}
529}
530#ifdef DEBUG
531printf("along axis %d\n", axis + 1);
532{
533PixelList *_prevTest, *_nextTest;
534int _i, _nextCount[3], _prevCount[3];
535for (_i = 0; _i < 3; _i++) {
536if (node->tail[_i]->next[_i]) {
537printf("tail is not tail\n");
538printf(
539"node->tail[%d]->next[%d]=%p\n", _i, _i, node->tail[_i]->next[_i]
540);
541}
542if (node->head[_i]->prev[_i]) {
543printf("head is not head\n");
544printf(
545"node->head[%d]->prev[%d]=%p\n", _i, _i, node->head[_i]->prev[_i]
546);
547}
548}
549
550for (_i = 0; _i < 3; _i++) {
551for (_nextCount[_i] = 0, _nextTest = node->head[_i];
552_nextTest && _nextTest->next[_i];
553_nextTest = _nextTest->next[_i], _nextCount[_i]++);
554for (_prevCount[_i] = 0, _prevTest = node->tail[_i];
555_prevTest && _prevTest->prev[_i];
556_prevTest = _prevTest->prev[_i], _prevCount[_i]++);
557if (_nextTest != node->tail[_i]) {
558printf("next-list of axis %d does not end at tail\n", _i);
559}
560if (_prevTest != node->head[_i]) {
561printf("prev-list of axis %d does not end at head\n", _i);
562}
563for (; _nextTest && _nextTest->prev[_i]; _nextTest = _nextTest->prev[_i]);
564for (; _prevTest && _prevTest->next[_i]; _prevTest = _prevTest->next[_i]);
565if (_nextTest != node->head[_i]) {
566printf("next-list of axis %d does not loop back to head\n", _i);
567}
568if (_prevTest != node->tail[_i]) {
569printf("prev-list of axis %d does not loop back to tail\n", _i);
570}
571}
572for (_i = 1; _i < 3; _i++) {
573if (_prevCount[_i] != _prevCount[_i - 1] ||
574_nextCount[_i] != _nextCount[_i - 1] ||
575_prevCount[_i] != _nextCount[_i]) {
576printf(
577"{%d %d %d} {%d %d %d}\n",
578_prevCount[0],
579_prevCount[1],
580_prevCount[2],
581_nextCount[0],
582_nextCount[1],
583_nextCount[2]
584);
585}
586}
587}
588#endif
589node->axis = axis;
590if (!splitlists(
591node->head, node->tail, heads, tails, newCounts, axis, node->pixelCount
592)) {
593#ifdef DEBUG
594printf("list split failed.\n");
595#endif
596return 0;
597}
598#ifdef DEBUG
599if (!test_sorted(heads[0])) {
600printf("bug in split");
601exit(1);
602}
603if (!test_sorted(heads[1])) {
604printf("bug in split");
605exit(1);
606}
607#endif
608/* malloc check ok, small constant allocation */
609left = malloc(sizeof(BoxNode));
610right = malloc(sizeof(BoxNode));
611if (!left || !right) {
612free(left);
613free(right);
614return 0;
615}
616for (i = 0; i < 3; i++) {
617left->head[i] = heads[0][i];
618left->tail[i] = tails[0][i];
619right->head[i] = heads[1][i];
620right->tail[i] = tails[1][i];
621node->head[i] = NULL;
622node->tail[i] = NULL;
623}
624#ifdef DEBUG
625if (left->head[0]) {
626rh = left->head[0]->p.c.r;
627rl = left->tail[0]->p.c.r;
628gh = left->head[1]->p.c.g;
629gl = left->tail[1]->p.c.g;
630bh = left->head[2]->p.c.b;
631bl = left->tail[2]->p.c.b;
632printf(" left node [%3d %3d %3d] [%3d %3d %3d]\n", rl, gl, bl, rh, gh, bh);
633}
634if (right->head[0]) {
635rh = right->head[0]->p.c.r;
636rl = right->tail[0]->p.c.r;
637gh = right->head[1]->p.c.g;
638gl = right->tail[1]->p.c.g;
639bh = right->head[2]->p.c.b;
640bl = right->tail[2]->p.c.b;
641printf(" right node [%3d %3d %3d] [%3d %3d %3d]\n", rl, gl, bl, rh, gh, bh);
642}
643#endif
644left->l = left->r = NULL;
645right->l = right->r = NULL;
646left->axis = right->axis = -1;
647left->volume = right->volume = -1;
648left->pixelCount = newCounts[0];
649right->pixelCount = newCounts[1];
650node->l = left;
651node->r = right;
652return 1;
653}
654
655static BoxNode *
656median_cut(PixelList *hl[3], uint32_t imPixelCount, int nPixels) {
657PixelList *tl[3];
658int i;
659BoxNode *root;
660Heap *h;
661BoxNode *thisNode;
662
663h = ImagingQuantHeapNew(box_heap_cmp);
664/* malloc check ok, small constant allocation */
665root = malloc(sizeof(BoxNode));
666if (!root) {
667ImagingQuantHeapFree(h);
668return NULL;
669}
670for (i = 0; i < 3; i++) {
671for (tl[i] = hl[i]; tl[i] && tl[i]->next[i]; tl[i] = tl[i]->next[i]);
672root->head[i] = hl[i];
673root->tail[i] = tl[i];
674}
675root->l = root->r = NULL;
676root->axis = -1;
677root->volume = -1;
678root->pixelCount = imPixelCount;
679
680ImagingQuantHeapAdd(h, (void *)root);
681while (--nPixels) {
682do {
683if (!ImagingQuantHeapRemove(h, (void **)&thisNode)) {
684goto done;
685}
686} while (compute_box_volume(thisNode) == 1);
687if (!split(thisNode)) {
688#ifdef DEBUG
689printf("Oops, split failed...\n");
690#endif
691exit(1);
692}
693ImagingQuantHeapAdd(h, (void *)(thisNode->l));
694ImagingQuantHeapAdd(h, (void *)(thisNode->r));
695}
696done:
697ImagingQuantHeapFree(h);
698return root;
699}
700
701static void
702free_box_tree(BoxNode *n) {
703PixelList *p, *pp;
704if (n->l) {
705free_box_tree(n->l);
706}
707if (n->r) {
708free_box_tree(n->r);
709}
710for (p = n->head[0]; p; p = pp) {
711pp = p->next[0];
712free(p);
713}
714free(n);
715}
716
717#ifdef DEBUG
718static int
719checkContained(BoxNode *n, Pixel *pp) {
720if (n->l && n->r) {
721return checkContained(n->l, pp) + checkContained(n->r, pp);
722}
723if (n->l || n->r) {
724printf("box tree is dead\n");
725return 0;
726}
727if (pp->c.r <= n->head[0]->p.c.r && pp->c.r >= n->tail[0]->p.c.r &&
728pp->c.g <= n->head[1]->p.c.g && pp->c.g >= n->tail[1]->p.c.g &&
729pp->c.b <= n->head[2]->p.c.b && pp->c.b >= n->tail[2]->p.c.b) {
730return 1;
731}
732return 0;
733}
734#endif
735
736static int
737annotate_hash_table(BoxNode *n, HashTable *h, uint32_t *box) {
738PixelList *p;
739PixelHashData *d = (PixelHashData *)hashtable_get_user_data(h);
740Pixel q;
741if (n->l && n->r) {
742return annotate_hash_table(n->l, h, box) && annotate_hash_table(n->r, h, box);
743}
744if (n->l || n->r) {
745#ifdef DEBUG
746printf("box tree is dead\n");
747#endif
748return 0;
749}
750for (p = n->head[0]; p; p = p->next[0]) {
751PIXEL_UNSCALE(&(p->p), &q, d->scale);
752if (!hashtable_insert(h, q, *box)) {
753#ifdef DEBUG
754printf("hashtable insert failed\n");
755#endif
756return 0;
757}
758}
759if (n->head[0]) {
760(*box)++;
761}
762return 1;
763}
764
765typedef struct {
766uint32_t *distance;
767uint32_t index;
768} DistanceWithIndex;
769
770static int
771_distance_index_cmp(const void *a, const void *b) {
772DistanceWithIndex *A = (DistanceWithIndex *)a;
773DistanceWithIndex *B = (DistanceWithIndex *)b;
774if (*A->distance == *B->distance) {
775return A->index < B->index ? -1 : +1;
776}
777return *A->distance < *B->distance ? -1 : +1;
778}
779
780static int
781resort_distance_tables(
782uint32_t *avgDist, uint32_t **avgDistSortKey, Pixel *p, uint32_t nEntries
783) {
784uint32_t i, j, k;
785uint32_t **skRow;
786uint32_t *skElt;
787
788for (i = 0; i < nEntries; i++) {
789avgDist[i * nEntries + i] = 0;
790for (j = 0; j < i; j++) {
791avgDist[j * nEntries + i] = avgDist[i * nEntries + j] =
792_DISTSQR(p + i, p + j);
793}
794}
795for (i = 0; i < nEntries; i++) {
796skRow = avgDistSortKey + i * nEntries;
797for (j = 1; j < nEntries; j++) {
798skElt = skRow[j];
799for (k = j; k && (*(skRow[k - 1]) > *(skRow[k])); k--) {
800skRow[k] = skRow[k - 1];
801}
802if (k != j) {
803skRow[k] = skElt;
804}
805}
806}
807return 1;
808}
809
810static int
811build_distance_tables(
812uint32_t *avgDist, uint32_t **avgDistSortKey, Pixel *p, uint32_t nEntries
813) {
814uint32_t i, j;
815DistanceWithIndex *dwi;
816
817for (i = 0; i < nEntries; i++) {
818avgDist[i * nEntries + i] = 0;
819avgDistSortKey[i * nEntries + i] = &(avgDist[i * nEntries + i]);
820for (j = 0; j < i; j++) {
821avgDist[j * nEntries + i] = avgDist[i * nEntries + j] =
822_DISTSQR(p + i, p + j);
823avgDistSortKey[j * nEntries + i] = &(avgDist[j * nEntries + i]);
824avgDistSortKey[i * nEntries + j] = &(avgDist[i * nEntries + j]);
825}
826}
827
828dwi = calloc(nEntries, sizeof(DistanceWithIndex));
829if (!dwi) {
830return 0;
831}
832for (i = 0; i < nEntries; i++) {
833for (j = 0; j < nEntries; j++) {
834dwi[j] = (DistanceWithIndex){&(avgDist[i * nEntries + j]), j};
835}
836qsort(dwi, nEntries, sizeof(DistanceWithIndex), _distance_index_cmp);
837for (j = 0; j < nEntries; j++) {
838avgDistSortKey[i * nEntries + j] = dwi[j].distance;
839}
840}
841free(dwi);
842return 1;
843}
844
845static int
846map_image_pixels(
847Pixel *pixelData,
848uint32_t nPixels,
849Pixel *paletteData,
850uint32_t nPaletteEntries,
851uint32_t *avgDist,
852uint32_t **avgDistSortKey,
853uint32_t *pixelArray
854) {
855uint32_t *aD, **aDSK;
856uint32_t idx;
857uint32_t i, j;
858uint32_t bestdist, bestmatch, dist;
859uint32_t initialdist;
860HashTable *h2;
861
862h2 = hashtable_new(unshifted_pixel_hash, unshifted_pixel_cmp);
863for (i = 0; i < nPixels; i++) {
864if (!hashtable_lookup(h2, pixelData[i], &bestmatch)) {
865bestmatch = 0;
866initialdist = _DISTSQR(paletteData + bestmatch, pixelData + i);
867bestdist = initialdist;
868initialdist <<= 2;
869aDSK = avgDistSortKey + bestmatch * nPaletteEntries;
870aD = avgDist + bestmatch * nPaletteEntries;
871for (j = 0; j < nPaletteEntries; j++) {
872idx = aDSK[j] - aD;
873if (*(aDSK[j]) <= initialdist) {
874dist = _DISTSQR(paletteData + idx, pixelData + i);
875if (dist < bestdist) {
876bestdist = dist;
877bestmatch = idx;
878}
879} else {
880break;
881}
882}
883hashtable_insert(h2, pixelData[i], bestmatch);
884}
885pixelArray[i] = bestmatch;
886}
887hashtable_free(h2);
888return 1;
889}
890
891static int
892map_image_pixels_from_quantized_pixels(
893Pixel *pixelData,
894uint32_t nPixels,
895Pixel *paletteData,
896uint32_t nPaletteEntries,
897uint32_t *avgDist,
898uint32_t **avgDistSortKey,
899uint32_t *pixelArray,
900uint32_t *avg[3],
901uint32_t *count
902) {
903uint32_t *aD, **aDSK;
904uint32_t idx;
905uint32_t i, j;
906uint32_t bestdist, bestmatch, dist;
907uint32_t initialdist;
908HashTable *h2;
909int changes = 0;
910
911h2 = hashtable_new(unshifted_pixel_hash, unshifted_pixel_cmp);
912for (i = 0; i < nPixels; i++) {
913if (!hashtable_lookup(h2, pixelData[i], &bestmatch)) {
914bestmatch = pixelArray[i];
915initialdist = _DISTSQR(paletteData + bestmatch, pixelData + i);
916bestdist = initialdist;
917initialdist <<= 2;
918aDSK = avgDistSortKey + bestmatch * nPaletteEntries;
919aD = avgDist + bestmatch * nPaletteEntries;
920for (j = 0; j < nPaletteEntries; j++) {
921idx = aDSK[j] - aD;
922if (*(aDSK[j]) <= initialdist) {
923dist = _DISTSQR(paletteData + idx, pixelData + i);
924if (dist < bestdist) {
925bestdist = dist;
926bestmatch = idx;
927}
928} else {
929break;
930}
931}
932hashtable_insert(h2, pixelData[i], bestmatch);
933}
934if (pixelArray[i] != bestmatch) {
935changes++;
936avg[0][bestmatch] += pixelData[i].c.r;
937avg[1][bestmatch] += pixelData[i].c.g;
938avg[2][bestmatch] += pixelData[i].c.b;
939avg[0][pixelArray[i]] -= pixelData[i].c.r;
940avg[1][pixelArray[i]] -= pixelData[i].c.g;
941avg[2][pixelArray[i]] -= pixelData[i].c.b;
942count[bestmatch]++;
943count[pixelArray[i]]--;
944pixelArray[i] = bestmatch;
945}
946}
947hashtable_free(h2);
948return changes;
949}
950
951static int
952map_image_pixels_from_median_box(
953Pixel *pixelData,
954uint32_t nPixels,
955Pixel *paletteData,
956uint32_t nPaletteEntries,
957HashTable *medianBoxHash,
958uint32_t *avgDist,
959uint32_t **avgDistSortKey,
960uint32_t *pixelArray
961) {
962uint32_t *aD, **aDSK;
963uint32_t idx;
964uint32_t i, j;
965uint32_t bestdist, bestmatch, dist;
966uint32_t initialdist;
967HashTable *h2;
968uint32_t pixelVal;
969
970h2 = hashtable_new(unshifted_pixel_hash, unshifted_pixel_cmp);
971for (i = 0; i < nPixels; i++) {
972if (hashtable_lookup(h2, pixelData[i], &pixelVal)) {
973pixelArray[i] = pixelVal;
974continue;
975}
976if (!hashtable_lookup(medianBoxHash, pixelData[i], &pixelVal)) {
977#ifdef DEBUG
978printf("pixel lookup failed\n");
979#endif
980return 0;
981}
982initialdist = _DISTSQR(paletteData + pixelVal, pixelData + i);
983bestdist = initialdist;
984bestmatch = pixelVal;
985initialdist <<= 2;
986aDSK = avgDistSortKey + pixelVal * nPaletteEntries;
987aD = avgDist + pixelVal * nPaletteEntries;
988for (j = 0; j < nPaletteEntries; j++) {
989idx = aDSK[j] - aD;
990if (*(aDSK[j]) <= initialdist) {
991dist = _DISTSQR(paletteData + idx, pixelData + i);
992if (dist < bestdist) {
993bestdist = dist;
994bestmatch = idx;
995}
996} else {
997break;
998}
999}
1000pixelArray[i] = bestmatch;
1001hashtable_insert(h2, pixelData[i], bestmatch);
1002}
1003hashtable_free(h2);
1004return 1;
1005}
1006
1007static int
1008compute_palette_from_median_cut(
1009Pixel *pixelData,
1010uint32_t nPixels,
1011HashTable *medianBoxHash,
1012Pixel **palette,
1013uint32_t nPaletteEntries,
1014BoxNode *root
1015) {
1016uint32_t i;
1017uint32_t paletteEntry;
1018Pixel *p;
1019uint32_t *avg[3];
1020uint32_t *count;
1021
1022*palette = NULL;
1023/* malloc check ok, using calloc */
1024if (!(count = calloc(nPaletteEntries, sizeof(uint32_t)))) {
1025return 0;
1026}
1027for (i = 0; i < 3; i++) {
1028avg[i] = NULL;
1029}
1030for (i = 0; i < 3; i++) {
1031/* malloc check ok, using calloc */
1032if (!(avg[i] = calloc(nPaletteEntries, sizeof(uint32_t)))) {
1033for (i = 0; i < 3; i++) {
1034if (avg[i]) {
1035free(avg[i]);
1036}
1037}
1038free(count);
1039return 0;
1040}
1041}
1042for (i = 0; i < nPixels; i++) {
1043#ifdef DEBUG
1044if (!(i % 100)) {
1045printf("%05d\r", i);
1046fflush(stdout);
1047}
1048if (checkContained(root, pixelData + i) > 1) {
1049printf("pixel in two boxes\n");
1050for (i = 0; i < 3; i++) {
1051free(avg[i]);
1052}
1053free(count);
1054return 0;
1055}
1056#endif
1057if (!hashtable_lookup(medianBoxHash, pixelData[i], &paletteEntry)) {
1058#ifdef DEBUG
1059printf("pixel lookup failed\n");
1060#endif
1061for (i = 0; i < 3; i++) {
1062free(avg[i]);
1063}
1064free(count);
1065return 0;
1066}
1067if (paletteEntry >= nPaletteEntries) {
1068#ifdef DEBUG
1069printf(
1070"panic - paletteEntry>=nPaletteEntries (%d>=%d)\n",
1071(int)paletteEntry,
1072(int)nPaletteEntries
1073);
1074#endif
1075for (i = 0; i < 3; i++) {
1076free(avg[i]);
1077}
1078free(count);
1079return 0;
1080}
1081avg[0][paletteEntry] += pixelData[i].c.r;
1082avg[1][paletteEntry] += pixelData[i].c.g;
1083avg[2][paletteEntry] += pixelData[i].c.b;
1084count[paletteEntry]++;
1085}
1086/* malloc check ok, using calloc */
1087p = calloc(nPaletteEntries, sizeof(Pixel));
1088if (!p) {
1089for (i = 0; i < 3; i++) {
1090free(avg[i]);
1091}
1092free(count);
1093return 0;
1094}
1095for (i = 0; i < nPaletteEntries; i++) {
1096p[i].c.r = (int)(.5 + (double)avg[0][i] / (double)count[i]);
1097p[i].c.g = (int)(.5 + (double)avg[1][i] / (double)count[i]);
1098p[i].c.b = (int)(.5 + (double)avg[2][i] / (double)count[i]);
1099}
1100*palette = p;
1101for (i = 0; i < 3; i++) {
1102free(avg[i]);
1103}
1104free(count);
1105return 1;
1106}
1107
1108static int
1109recompute_palette_from_averages(
1110Pixel *palette, uint32_t nPaletteEntries, uint32_t *avg[3], uint32_t *count
1111) {
1112uint32_t i;
1113
1114for (i = 0; i < nPaletteEntries; i++) {
1115palette[i].c.r = (int)(.5 + (double)avg[0][i] / (double)count[i]);
1116palette[i].c.g = (int)(.5 + (double)avg[1][i] / (double)count[i]);
1117palette[i].c.b = (int)(.5 + (double)avg[2][i] / (double)count[i]);
1118}
1119return 1;
1120}
1121
1122static int
1123compute_palette_from_quantized_pixels(
1124Pixel *pixelData,
1125uint32_t nPixels,
1126Pixel *palette,
1127uint32_t nPaletteEntries,
1128uint32_t *avg[3],
1129uint32_t *count,
1130uint32_t *qp
1131) {
1132uint32_t i;
1133
1134memset(count, 0, sizeof(uint32_t) * nPaletteEntries);
1135for (i = 0; i < 3; i++) {
1136memset(avg[i], 0, sizeof(uint32_t) * nPaletteEntries);
1137}
1138for (i = 0; i < nPixels; i++) {
1139if (qp[i] >= nPaletteEntries) {
1140#ifdef DEBUG
1141printf("scream\n");
1142#endif
1143return 0;
1144}
1145avg[0][qp[i]] += pixelData[i].c.r;
1146avg[1][qp[i]] += pixelData[i].c.g;
1147avg[2][qp[i]] += pixelData[i].c.b;
1148count[qp[i]]++;
1149}
1150for (i = 0; i < nPaletteEntries; i++) {
1151palette[i].c.r = (int)(.5 + (double)avg[0][i] / (double)count[i]);
1152palette[i].c.g = (int)(.5 + (double)avg[1][i] / (double)count[i]);
1153palette[i].c.b = (int)(.5 + (double)avg[2][i] / (double)count[i]);
1154}
1155return 1;
1156}
1157
1158static int
1159k_means(
1160Pixel *pixelData,
1161uint32_t nPixels,
1162Pixel *paletteData,
1163uint32_t nPaletteEntries,
1164uint32_t *qp,
1165int threshold
1166) {
1167uint32_t *avg[3];
1168uint32_t *count;
1169uint32_t i;
1170uint32_t *avgDist;
1171uint32_t **avgDistSortKey;
1172int changes;
1173int built = 0;
1174
1175if (nPaletteEntries > UINT32_MAX / (sizeof(uint32_t))) {
1176return 0;
1177}
1178/* malloc check ok, using calloc */
1179if (!(count = calloc(nPaletteEntries, sizeof(uint32_t)))) {
1180return 0;
1181}
1182for (i = 0; i < 3; i++) {
1183avg[i] = NULL;
1184}
1185for (i = 0; i < 3; i++) {
1186/* malloc check ok, using calloc */
1187if (!(avg[i] = calloc(nPaletteEntries, sizeof(uint32_t)))) {
1188goto error_1;
1189}
1190}
1191
1192/* this is enough of a check, since the multiplication n*size is done above */
1193if (nPaletteEntries > UINT32_MAX / nPaletteEntries) {
1194goto error_1;
1195}
1196/* malloc check ok, using calloc, checking n*n above */
1197avgDist = calloc(nPaletteEntries * nPaletteEntries, sizeof(uint32_t));
1198if (!avgDist) {
1199goto error_1;
1200}
1201
1202/* malloc check ok, using calloc, checking n*n above */
1203avgDistSortKey = calloc(nPaletteEntries * nPaletteEntries, sizeof(uint32_t *));
1204if (!avgDistSortKey) {
1205goto error_2;
1206}
1207
1208#ifdef DEBUG
1209printf("[");
1210fflush(stdout);
1211#endif
1212while (1) {
1213if (!built) {
1214compute_palette_from_quantized_pixels(
1215pixelData, nPixels, paletteData, nPaletteEntries, avg, count, qp
1216);
1217if (!build_distance_tables(
1218avgDist, avgDistSortKey, paletteData, nPaletteEntries
1219)) {
1220goto error_3;
1221}
1222built = 1;
1223} else {
1224recompute_palette_from_averages(paletteData, nPaletteEntries, avg, count);
1225resort_distance_tables(
1226avgDist, avgDistSortKey, paletteData, nPaletteEntries
1227);
1228}
1229changes = map_image_pixels_from_quantized_pixels(
1230pixelData,
1231nPixels,
1232paletteData,
1233nPaletteEntries,
1234avgDist,
1235avgDistSortKey,
1236qp,
1237avg,
1238count
1239);
1240if (changes < 0) {
1241goto error_3;
1242}
1243#ifdef DEBUG
1244printf(".(%d)", changes);
1245fflush(stdout);
1246#endif
1247if (changes <= threshold) {
1248break;
1249}
1250}
1251#ifdef DEBUG
1252printf("]\n");
1253#endif
1254if (avgDistSortKey) {
1255free(avgDistSortKey);
1256}
1257if (avgDist) {
1258free(avgDist);
1259}
1260for (i = 0; i < 3; i++) {
1261if (avg[i]) {
1262free(avg[i]);
1263}
1264}
1265if (count) {
1266free(count);
1267}
1268return 1;
1269
1270error_3:
1271if (avgDistSortKey) {
1272free(avgDistSortKey);
1273}
1274error_2:
1275if (avgDist) {
1276free(avgDist);
1277}
1278error_1:
1279for (i = 0; i < 3; i++) {
1280if (avg[i]) {
1281free(avg[i]);
1282}
1283}
1284if (count) {
1285free(count);
1286}
1287return 0;
1288}
1289
1290static int
1291quantize(
1292Pixel *pixelData,
1293uint32_t nPixels,
1294uint32_t nQuantPixels,
1295Pixel **palette,
1296uint32_t *paletteLength,
1297uint32_t **quantizedPixels,
1298int kmeans
1299) {
1300PixelList *hl[3];
1301HashTable *h;
1302BoxNode *root;
1303uint32_t i;
1304uint32_t *qp;
1305uint32_t nPaletteEntries;
1306
1307uint32_t *avgDist;
1308uint32_t **avgDistSortKey;
1309Pixel *p;
1310
1311#ifdef DEBUG
1312uint32_t timer, timer2;
1313#endif
1314
1315#ifdef DEBUG
1316timer2 = clock();
1317printf("create hash table...");
1318fflush(stdout);
1319timer = clock();
1320#endif
1321h = create_pixel_hash(pixelData, nPixels);
1322#ifdef DEBUG
1323printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1324#endif
1325if (!h) {
1326goto error_0;
1327}
1328
1329#ifdef DEBUG
1330printf("create lists from hash table...");
1331fflush(stdout);
1332timer = clock();
1333#endif
1334hl[0] = hl[1] = hl[2] = NULL;
1335hashtable_foreach(h, hash_to_list, hl);
1336#ifdef DEBUG
1337printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1338#endif
1339
1340if (!hl[0]) {
1341goto error_1;
1342}
1343
1344#ifdef DEBUG
1345printf("mergesort lists...");
1346fflush(stdout);
1347timer = clock();
1348#endif
1349for (i = 0; i < 3; i++) {
1350hl[i] = mergesort_pixels(hl[i], i);
1351}
1352#ifdef DEBUG
1353if (!test_sorted(hl)) {
1354printf("bug in mergesort\n");
1355goto error_1;
1356}
1357printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1358#endif
1359
1360#ifdef DEBUG
1361printf("median cut...");
1362fflush(stdout);
1363timer = clock();
1364#endif
1365root = median_cut(hl, nPixels, nQuantPixels);
1366#ifdef DEBUG
1367printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1368#endif
1369if (!root) {
1370goto error_1;
1371}
1372nPaletteEntries = 0;
1373#ifdef DEBUG
1374printf("median cut tree to hash table...");
1375fflush(stdout);
1376timer = clock();
1377#endif
1378annotate_hash_table(root, h, &nPaletteEntries);
1379#ifdef DEBUG
1380printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1381#endif
1382#ifdef DEBUG
1383printf("compute palette...\n");
1384fflush(stdout);
1385timer = clock();
1386#endif
1387if (!compute_palette_from_median_cut(
1388pixelData, nPixels, h, &p, nPaletteEntries, root
1389)) {
1390goto error_3;
1391}
1392#ifdef DEBUG
1393printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1394#endif
1395
1396free_box_tree(root);
1397root = NULL;
1398
1399/* malloc check ok, using calloc for overflow */
1400qp = calloc(nPixels, sizeof(uint32_t));
1401if (!qp) {
1402goto error_4;
1403}
1404
1405if (nPaletteEntries > UINT32_MAX / nPaletteEntries) {
1406goto error_5;
1407}
1408/* malloc check ok, using calloc for overflow, check of n*n above */
1409avgDist = calloc(nPaletteEntries * nPaletteEntries, sizeof(uint32_t));
1410if (!avgDist) {
1411goto error_5;
1412}
1413
1414/* malloc check ok, using calloc for overflow, check of n*n above */
1415avgDistSortKey = calloc(nPaletteEntries * nPaletteEntries, sizeof(uint32_t *));
1416if (!avgDistSortKey) {
1417goto error_6;
1418}
1419
1420if (!build_distance_tables(avgDist, avgDistSortKey, p, nPaletteEntries)) {
1421goto error_7;
1422}
1423
1424if (!map_image_pixels_from_median_box(
1425pixelData, nPixels, p, nPaletteEntries, h, avgDist, avgDistSortKey, qp
1426)) {
1427goto error_7;
1428}
1429
1430#ifdef TEST_NEAREST_NEIGHBOUR
1431#include <math.h>
1432{
1433uint32_t bestmatch, bestdist, dist;
1434HashTable *h2;
1435printf("nearest neighbour search (full search)...");
1436fflush(stdout);
1437timer = clock();
1438h2 = hashtable_new(unshifted_pixel_hash, unshifted_pixel_cmp);
1439for (i = 0; i < nPixels; i++) {
1440if (hashtable_lookup(h2, pixelData[i], &paletteEntry)) {
1441bestmatch = paletteEntry;
1442} else {
1443bestmatch = 0;
1444bestdist = _SQR(pixelData[i].c.r - p[0].c.r) +
1445_SQR(pixelData[i].c.g - p[0].c.g) +
1446_SQR(pixelData[i].c.b - p[0].c.b);
1447for (j = 1; j < nPaletteEntries; j++) {
1448dist = _SQR(pixelData[i].c.r - p[j].c.r) +
1449_SQR(pixelData[i].c.g - p[j].c.g) +
1450_SQR(pixelData[i].c.b - p[j].c.b);
1451if (dist == bestdist && j == qp[i]) {
1452bestmatch = j;
1453}
1454if (dist < bestdist) {
1455bestdist = dist;
1456bestmatch = j;
1457}
1458}
1459hashtable_insert(h2, pixelData[i], bestmatch);
1460}
1461if (qp[i] != bestmatch) {
1462printf(
1463"discrepancy in matching algorithms pixel %d [%d %d] %f %f\n",
1464i,
1465qp[i],
1466bestmatch,
1467sqrt((double)(_SQR(pixelData[i].c.r - p[qp[i]].c.r) +
1468_SQR(pixelData[i].c.g - p[qp[i]].c.g) +
1469_SQR(pixelData[i].c.b - p[qp[i]].c.b))),
1470sqrt((double)(_SQR(pixelData[i].c.r - p[bestmatch].c.r) +
1471_SQR(pixelData[i].c.g - p[bestmatch].c.g) +
1472_SQR(pixelData[i].c.b - p[bestmatch].c.b)))
1473);
1474}
1475}
1476hashtable_free(h2);
1477}
1478#endif
1479#ifdef DEBUG
1480printf("k means...\n");
1481fflush(stdout);
1482timer = clock();
1483#endif
1484if (kmeans > 0) {
1485k_means(pixelData, nPixels, p, nPaletteEntries, qp, kmeans - 1);
1486}
1487#ifdef DEBUG
1488printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1489#endif
1490
1491*quantizedPixels = qp;
1492*palette = p;
1493*paletteLength = nPaletteEntries;
1494
1495#ifdef DEBUG
1496printf("cleanup...");
1497fflush(stdout);
1498timer = clock();
1499#endif
1500if (avgDist) {
1501free(avgDist);
1502}
1503if (avgDistSortKey) {
1504free(avgDistSortKey);
1505}
1506destroy_pixel_hash(h);
1507#ifdef DEBUG
1508printf("done (%f)\n", (clock() - timer) / (double)CLOCKS_PER_SEC);
1509printf("-----\ntotal time %f\n", (clock() - timer2) / (double)CLOCKS_PER_SEC);
1510#endif
1511return 1;
1512
1513error_7:
1514if (avgDistSortKey) {
1515free(avgDistSortKey);
1516}
1517error_6:
1518if (avgDist) {
1519free(avgDist);
1520}
1521error_5:
1522if (qp) {
1523free(qp);
1524}
1525error_4:
1526if (p) {
1527free(p);
1528}
1529error_3:
1530if (root) {
1531free_box_tree(root);
1532}
1533error_1:
1534destroy_pixel_hash(h);
1535error_0:
1536*quantizedPixels = NULL;
1537*paletteLength = 0;
1538*palette = NULL;
1539return 0;
1540}
1541
1542typedef struct {
1543Pixel new;
1544uint32_t furthestV;
1545uint32_t furthestDistance;
1546int secondPixel;
1547} DistanceData;
1548
1549static void
1550compute_distances(const HashTable *h, const Pixel pixel, uint32_t *dist, void *u) {
1551DistanceData *data = (DistanceData *)u;
1552uint32_t oldDist = *dist;
1553uint32_t newDist;
1554newDist = _DISTSQR(&(data->new), &pixel);
1555if (data->secondPixel || newDist < oldDist) {
1556*dist = newDist;
1557oldDist = newDist;
1558}
1559if (oldDist > data->furthestDistance) {
1560data->furthestDistance = oldDist;
1561data->furthestV = pixel.v;
1562}
1563}
1564
1565static int
1566quantize2(
1567Pixel *pixelData,
1568uint32_t nPixels,
1569uint32_t nQuantPixels,
1570Pixel **palette,
1571uint32_t *paletteLength,
1572uint32_t **quantizedPixels,
1573int kmeans
1574) {
1575HashTable *h;
1576uint32_t i;
1577uint32_t mean[3];
1578Pixel *p;
1579DistanceData data;
1580
1581uint32_t *qp;
1582uint32_t *avgDist;
1583uint32_t **avgDistSortKey;
1584
1585/* malloc check ok, using calloc */
1586p = calloc(nQuantPixels, sizeof(Pixel));
1587if (!p) {
1588return 0;
1589}
1590mean[0] = mean[1] = mean[2] = 0;
1591h = hashtable_new(unshifted_pixel_hash, unshifted_pixel_cmp);
1592for (i = 0; i < nPixels; i++) {
1593hashtable_insert(h, pixelData[i], 0xffffffff);
1594mean[0] += pixelData[i].c.r;
1595mean[1] += pixelData[i].c.g;
1596mean[2] += pixelData[i].c.b;
1597}
1598data.new.c.r = (int)(.5 + (double)mean[0] / (double)nPixels);
1599data.new.c.g = (int)(.5 + (double)mean[1] / (double)nPixels);
1600data.new.c.b = (int)(.5 + (double)mean[2] / (double)nPixels);
1601for (i = 0; i < nQuantPixels; i++) {
1602data.furthestDistance = 0;
1603data.furthestV = pixelData[0].v;
1604data.secondPixel = (i == 1) ? 1 : 0;
1605hashtable_foreach_update(h, compute_distances, &data);
1606p[i].v = data.furthestV;
1607data.new.v = data.furthestV;
1608}
1609hashtable_free(h);
1610
1611/* malloc check ok, using calloc */
1612qp = calloc(nPixels, sizeof(uint32_t));
1613if (!qp) {
1614goto error_1;
1615}
1616
1617if (nQuantPixels > UINT32_MAX / nQuantPixels) {
1618goto error_2;
1619}
1620
1621/* malloc check ok, using calloc for overflow, check of n*n above */
1622avgDist = calloc(nQuantPixels * nQuantPixels, sizeof(uint32_t));
1623if (!avgDist) {
1624goto error_2;
1625}
1626
1627/* malloc check ok, using calloc for overflow, check of n*n above */
1628avgDistSortKey = calloc(nQuantPixels * nQuantPixels, sizeof(uint32_t *));
1629if (!avgDistSortKey) {
1630goto error_3;
1631}
1632
1633if (!build_distance_tables(avgDist, avgDistSortKey, p, nQuantPixels)) {
1634goto error_4;
1635}
1636
1637if (!map_image_pixels(
1638pixelData, nPixels, p, nQuantPixels, avgDist, avgDistSortKey, qp
1639)) {
1640goto error_4;
1641}
1642if (kmeans > 0) {
1643k_means(pixelData, nPixels, p, nQuantPixels, qp, kmeans - 1);
1644}
1645
1646*paletteLength = nQuantPixels;
1647*palette = p;
1648*quantizedPixels = qp;
1649free(avgDistSortKey);
1650free(avgDist);
1651return 1;
1652
1653error_4:
1654free(avgDistSortKey);
1655error_3:
1656free(avgDist);
1657error_2:
1658free(qp);
1659error_1:
1660free(p);
1661return 0;
1662}
1663
1664Imaging
1665ImagingQuantize(Imaging im, int colors, int mode, int kmeans) {
1666int i, j;
1667int x, y, v;
1668UINT8 *pp;
1669Pixel *p;
1670Pixel *palette;
1671uint32_t paletteLength;
1672int result;
1673uint32_t *newData;
1674Imaging imOut;
1675int withAlpha = 0;
1676ImagingSectionCookie cookie;
1677
1678if (!im) {
1679return ImagingError_ModeError();
1680}
1681if (colors < 1 || colors > 256) {
1682/* FIXME: for colors > 256, consider returning an RGB image
1683instead (see @PIL205) */
1684return (Imaging)ImagingError_ValueError("bad number of colors");
1685}
1686
1687if (strcmp(im->mode, "L") != 0 && strcmp(im->mode, "P") != 0 &&
1688strcmp(im->mode, "RGB") != 0 && strcmp(im->mode, "RGBA") != 0) {
1689return ImagingError_ModeError();
1690}
1691
1692/* only octree and imagequant supports RGBA */
1693if (!strcmp(im->mode, "RGBA") && mode != 2 && mode != 3) {
1694return ImagingError_ModeError();
1695}
1696
1697if (im->xsize > INT_MAX / im->ysize) {
1698return ImagingError_MemoryError();
1699}
1700/* malloc check ok, using calloc for final overflow, x*y above */
1701p = calloc(im->xsize * im->ysize, sizeof(Pixel));
1702if (!p) {
1703return ImagingError_MemoryError();
1704}
1705
1706/* collect statistics */
1707
1708/* FIXME: maybe we could load the hash tables directly from the
1709image data? */
1710
1711if (!strcmp(im->mode, "L")) {
1712/* grayscale */
1713
1714/* FIXME: converting a "L" image to "P" with 256 colors
1715should be done by a simple copy... */
1716
1717for (i = y = 0; y < im->ysize; y++) {
1718for (x = 0; x < im->xsize; x++, i++) {
1719p[i].c.r = p[i].c.g = p[i].c.b = im->image8[y][x];
1720p[i].c.a = 255;
1721}
1722}
1723
1724} else if (!strcmp(im->mode, "P")) {
1725/* palette */
1726
1727pp = im->palette->palette;
1728
1729for (i = y = 0; y < im->ysize; y++) {
1730for (x = 0; x < im->xsize; x++, i++) {
1731v = im->image8[y][x];
1732p[i].c.r = pp[v * 4 + 0];
1733p[i].c.g = pp[v * 4 + 1];
1734p[i].c.b = pp[v * 4 + 2];
1735p[i].c.a = pp[v * 4 + 3];
1736}
1737}
1738
1739} else if (!strcmp(im->mode, "RGB") || !strcmp(im->mode, "RGBA")) {
1740/* true colour */
1741
1742withAlpha = !strcmp(im->mode, "RGBA");
1743int transparency = 0;
1744unsigned char r = 0, g = 0, b = 0;
1745for (i = y = 0; y < im->ysize; y++) {
1746for (x = 0; x < im->xsize; x++, i++) {
1747p[i].v = im->image32[y][x];
1748if (withAlpha && p[i].c.a == 0) {
1749if (transparency == 0) {
1750transparency = 1;
1751r = p[i].c.r;
1752g = p[i].c.g;
1753b = p[i].c.b;
1754} else {
1755/* Set all subsequent transparent pixels
1756to the same colour as the first */
1757p[i].c.r = r;
1758p[i].c.g = g;
1759p[i].c.b = b;
1760}
1761}
1762}
1763}
1764
1765} else {
1766free(p);
1767return (Imaging)ImagingError_ValueError("internal error");
1768}
1769
1770ImagingSectionEnter(&cookie);
1771
1772switch (mode) {
1773case 0:
1774/* median cut */
1775result = quantize(
1776p,
1777im->xsize * im->ysize,
1778colors,
1779&palette,
1780&paletteLength,
1781&newData,
1782kmeans
1783);
1784break;
1785case 1:
1786/* maximum coverage */
1787result = quantize2(
1788p,
1789im->xsize * im->ysize,
1790colors,
1791&palette,
1792&paletteLength,
1793&newData,
1794kmeans
1795);
1796break;
1797case 2:
1798result = quantize_octree(
1799p,
1800im->xsize * im->ysize,
1801colors,
1802&palette,
1803&paletteLength,
1804&newData,
1805withAlpha
1806);
1807break;
1808case 3:
1809#ifdef HAVE_LIBIMAGEQUANT
1810result = quantize_pngquant(
1811p,
1812im->xsize,
1813im->ysize,
1814colors,
1815&palette,
1816&paletteLength,
1817&newData,
1818withAlpha
1819);
1820#else
1821result = -1;
1822#endif
1823break;
1824default:
1825result = 0;
1826break;
1827}
1828
1829free(p);
1830ImagingSectionLeave(&cookie);
1831
1832if (result > 0) {
1833imOut = ImagingNewDirty("P", im->xsize, im->ysize);
1834ImagingSectionEnter(&cookie);
1835
1836for (i = y = 0; y < im->ysize; y++) {
1837for (x = 0; x < im->xsize; x++) {
1838imOut->image8[y][x] = (unsigned char)newData[i++];
1839}
1840}
1841
1842free(newData);
1843
1844imOut->palette->size = (int)paletteLength;
1845pp = imOut->palette->palette;
1846
1847for (i = j = 0; i < (int)paletteLength; i++) {
1848*pp++ = palette[i].c.r;
1849*pp++ = palette[i].c.g;
1850*pp++ = palette[i].c.b;
1851if (withAlpha) {
1852*pp = palette[i].c.a;
1853}
1854pp++;
1855}
1856
1857if (withAlpha) {
1858strcpy(imOut->palette->mode, "RGBA");
1859}
1860
1861free(palette);
1862ImagingSectionLeave(&cookie);
1863
1864return imOut;
1865
1866} else {
1867if (result == -1) {
1868return (Imaging)ImagingError_ValueError(
1869"dependency required by this method was not "
1870"enabled at compile time"
1871);
1872}
1873
1874return (Imaging)ImagingError_ValueError("quantization error");
1875}
1876}
1877