Merge branch 'master' of https://github.com/python-imaging/Pillow into namespaced

This commit is contained in:
wiredfool 2013-04-09 12:08:13 -07:00
commit b0fffd24a4
16 changed files with 429 additions and 501 deletions

View File

@ -721,6 +721,16 @@ class Image:
if dither is None: if dither is None:
dither = FLOYDSTEINBERG dither = FLOYDSTEINBERG
# fake a P-mode image, otherwise the transparency will get lost as there is
# currently no other way to convert transparency into an RGBA image
if self.mode == "L" and mode == "RGBA" and "transparency" in self.info:
from PIL import ImagePalette
self.mode = "P"
bytePalette = bytes([i//3 for i in range(768)])
self.palette = ImagePalette.raw("RGB", bytePalette)
self.palette.dirty = 1
self.load()
try: try:
im = self.im.convert(mode, dither) im = self.im.convert(mode, dither)
except ValueError: except ValueError:

View File

@ -10,8 +10,8 @@ def test_toarray():
return ai["shape"], ai["typestr"], len(ai["data"]) return ai["shape"], ai["typestr"], len(ai["data"])
# assert_equal(test("1"), ((100, 128), '|b1', 1600)) # assert_equal(test("1"), ((100, 128), '|b1', 1600))
assert_equal(test("L"), ((100, 128), '|u1', 12800)) assert_equal(test("L"), ((100, 128), '|u1', 12800))
assert_equal(test("I"), ((100, 128), '<i4', 51200)) # FIXME: wrong? assert_equal(test("I"), ((100, 128), Image._ENDIAN + 'i4', 51200)) # FIXME: wrong?
assert_equal(test("F"), ((100, 128), '<f4', 51200)) # FIXME: wrong? assert_equal(test("F"), ((100, 128), Image._ENDIAN + 'f4', 51200)) # FIXME: wrong?
assert_equal(test("RGB"), ((100, 128, 3), '|u1', 38400)) assert_equal(test("RGB"), ((100, 128, 3), '|u1', 38400))
assert_equal(test("RGBA"), ((100, 128, 4), '|u1', 51200)) assert_equal(test("RGBA"), ((100, 128, 4), '|u1', 51200))
assert_equal(test("RGBX"), ((100, 128, 4), '|u1', 51200)) assert_equal(test("RGBX"), ((100, 128, 4), '|u1', 51200))

View File

@ -18,6 +18,8 @@ def test_pack():
else: else:
return [ord(c) for c in im.tobytes("raw", rawmode)] return [ord(c) for c in im.tobytes("raw", rawmode)]
order = 1 if Image._ENDIAN == '<' else -1
assert_equal(pack("1", "1"), [128]) assert_equal(pack("1", "1"), [128])
assert_equal(pack("1", "1;I"), [0]) assert_equal(pack("1", "1;I"), [0])
assert_equal(pack("1", "1;R"), [1]) assert_equal(pack("1", "1;R"), [1])
@ -25,9 +27,9 @@ def test_pack():
assert_equal(pack("L", "L"), [1]) assert_equal(pack("L", "L"), [1])
assert_equal(pack("I", "I"), [1, 0, 0, 0]) assert_equal(pack("I", "I"), [1, 0, 0, 0][::order])
assert_equal(pack("F", "F"), [0, 0, 128, 63]) assert_equal(pack("F", "F"), [0, 0, 128, 63][::order])
assert_equal(pack("LA", "LA"), [1, 2]) assert_equal(pack("LA", "LA"), [1, 2])

View File

@ -84,10 +84,12 @@ def test_tobytes():
def tobytes(mode): def tobytes(mode):
return Image.new(mode, (1, 1), 1).tobytes() return Image.new(mode, (1, 1), 1).tobytes()
order = 1 if Image._ENDIAN == '<' else -1
assert_equal(tobytes("L"), b"\x01") assert_equal(tobytes("L"), b"\x01")
assert_equal(tobytes("I;16"), b"\x01\x00") assert_equal(tobytes("I;16"), b"\x01\x00")
assert_equal(tobytes("I;16B"), b"\x00\x01") assert_equal(tobytes("I;16B"), b"\x00\x01")
assert_equal(tobytes("I"), b"\x01\x00\x00\x00") assert_equal(tobytes("I"), b"\x01\x00\x00\x00"[::order])
def test_convert(): def test_convert():

View File

@ -1370,7 +1370,6 @@ _putdata(ImagingObject* self, PyObject* args)
#ifdef WITH_QUANTIZE #ifdef WITH_QUANTIZE
#include "Quant.h"
static PyObject* static PyObject*
_quantize(ImagingObject* self, PyObject* args) _quantize(ImagingObject* self, PyObject* args)
{ {

View File

@ -282,7 +282,7 @@ font_render(FontObject* self, PyObject* args)
{ {
int i, x, y; int i, x, y;
Imaging im; Imaging im;
int index, error, ascender; int index, error, ascender, descender;
int load_flags; int load_flags;
unsigned char *source; unsigned char *source;
FT_ULong ch; FT_ULong ch;
@ -332,6 +332,7 @@ font_render(FontObject* self, PyObject* args)
int xx, x0, x1; int xx, x0, x1;
source = (unsigned char*) glyph->bitmap.buffer; source = (unsigned char*) glyph->bitmap.buffer;
ascender = PIXEL(self->face->size->metrics.ascender); ascender = PIXEL(self->face->size->metrics.ascender);
descender = PIXEL(self->face->size->metrics.descender);
xx = x + glyph->bitmap_left; xx = x + glyph->bitmap_left;
x0 = 0; x0 = 0;
x1 = glyph->bitmap.width; x1 = glyph->bitmap.width;
@ -340,7 +341,7 @@ font_render(FontObject* self, PyObject* args)
if (xx + x1 > im->xsize) if (xx + x1 > im->xsize)
x1 = im->xsize - xx; x1 = im->xsize - xx;
for (y = 0; y < glyph->bitmap.rows; y++) { for (y = 0; y < glyph->bitmap.rows; y++) {
int yy = y + ascender - glyph->bitmap_top; int yy = y + ascender + descender - glyph->bitmap_top;
if (yy >= 0 && yy < im->ysize) { if (yy >= 0 && yy < im->ysize) {
/* blend this glyph into the buffer */ /* blend this glyph into the buffer */
unsigned char *target = im->image8[yy] + xx; unsigned char *target = im->image8[yy] + xx;
@ -361,6 +362,7 @@ font_render(FontObject* self, PyObject* args)
int xx, x0, x1; int xx, x0, x1;
source = (unsigned char*) glyph->bitmap.buffer; source = (unsigned char*) glyph->bitmap.buffer;
ascender = PIXEL(self->face->size->metrics.ascender); ascender = PIXEL(self->face->size->metrics.ascender);
descender = PIXEL(self->face->size->metrics.descender);
xx = x + glyph->bitmap_left; xx = x + glyph->bitmap_left;
x0 = 0; x0 = 0;
x1 = glyph->bitmap.width; x1 = glyph->bitmap.width;
@ -369,7 +371,7 @@ font_render(FontObject* self, PyObject* args)
if (xx + x1 > im->xsize) if (xx + x1 > im->xsize)
x1 = im->xsize - xx; x1 = im->xsize - xx;
for (y = 0; y < glyph->bitmap.rows; y++) { for (y = 0; y < glyph->bitmap.rows; y++) {
int yy = y + ascender - glyph->bitmap_top; int yy = y + ascender + descender - glyph->bitmap_top;
if (yy >= 0 && yy < im->ysize) { if (yy >= 0 && yy < im->ysize) {
/* blend this glyph into the buffer */ /* blend this glyph into the buffer */
int i; int i;

View File

@ -25,17 +25,15 @@
#include <memory.h> #include <memory.h>
#include <time.h> #include <time.h>
#include "Quant.h" #include "QuantTypes.h"
#include "QuantOctree.h" #include "QuantOctree.h"
#include "QuantDefines.h"
#include "QuantHash.h" #include "QuantHash.h"
#include "QuantHeap.h" #include "QuantHeap.h"
#define NO_OUTPUT #define NO_OUTPUT
typedef struct { typedef struct {
unsigned long scale; uint32_t scale;
} PixelHashData; } PixelHashData;
typedef struct _PixelList { typedef struct _PixelList {
@ -50,7 +48,7 @@ typedef struct _BoxNode {
PixelList *head[3],*tail[3]; PixelList *head[3],*tail[3];
int axis; int axis;
int volume; int volume;
unsigned long pixelCount; uint32_t pixelCount;
} BoxNode; } BoxNode;
#define _SQR(x) ((x)*(x)) #define _SQR(x) ((x)*(x))
@ -76,104 +74,92 @@ typedef struct _BoxNode {
((q)->c.g=(p)->c.g>>(s)), \ ((q)->c.g=(p)->c.g>>(s)), \
((q)->c.b=(p)->c.b>>(s)) ((q)->c.b=(p)->c.b>>(s))
static unsigned long static uint32_t
unshifted_pixel_hash(const HashTable h, const void *p) unshifted_pixel_hash(const HashTable *h, const Pixel pixel)
{ {
Pixel *pixel=(Pixel *)&p; return PIXEL_HASH(pixel.c.r, pixel.c.g, pixel.c.b);
unsigned long hash=PIXEL_HASH(pixel->c.r,
pixel->c.g,
pixel->c.b);
return hash;
} }
static int static int
unshifted_pixel_cmp(const HashTable h, const void *a, const void *b) unshifted_pixel_cmp(const HashTable *h, const Pixel pixel1, const Pixel pixel2)
{ {
Pixel *pixel1=(Pixel *)&a; if (pixel1.c.r==pixel2.c.r) {
Pixel *pixel2=(Pixel *)&b; if (pixel1.c.g==pixel2.c.g) {
if (pixel1->c.r==pixel2->c.r) { if (pixel1.c.b==pixel2.c.b) {
if (pixel1->c.g==pixel2->c.g) {
if (pixel1->c.b==pixel2->c.b) {
return 0; return 0;
} else { } else {
return (int)(pixel1->c.b)-(int)(pixel2->c.b); return (int)(pixel1.c.b)-(int)(pixel2.c.b);
} }
} else { } else {
return (int)(pixel1->c.g)-(int)(pixel2->c.g); return (int)(pixel1.c.g)-(int)(pixel2.c.g);
} }
} else { } else {
return (int)(pixel1->c.r)-(int)(pixel2->c.r); return (int)(pixel1.c.r)-(int)(pixel2.c.r);
} }
} }
static unsigned long static uint32_t
pixel_hash(const HashTable h,const void *p) pixel_hash(const HashTable *h,const Pixel pixel)
{ {
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h); PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
Pixel *pixel=(Pixel *)&p; return PIXEL_HASH(pixel.c.r>>d->scale, pixel.c.g>>d->scale, pixel.c.b>>d->scale);
unsigned long hash=PIXEL_HASH(pixel->c.r>>d->scale,
pixel->c.g>>d->scale,
pixel->c.b>>d->scale);
return hash;
} }
static int static int
pixel_cmp(const HashTable h,const void *a,const void *b) pixel_cmp(const HashTable *h,const Pixel pixel1, const Pixel pixel2)
{ {
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h); PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
Pixel *pixel1=(Pixel *)&a; uint32_t A,B;
Pixel *pixel2=(Pixel *)&b; A=PIXEL_HASH(pixel1.c.r>>d->scale, pixel1.c.g>>d->scale, pixel1.c.b>>d->scale);
unsigned long A,B; B=PIXEL_HASH(pixel2.c.r>>d->scale, pixel2.c.g>>d->scale, pixel2.c.b>>d->scale);
A=PIXEL_HASH(pixel1->c.r>>d->scale,
pixel1->c.g>>d->scale,
pixel1->c.b>>d->scale);
B=PIXEL_HASH(pixel2->c.r>>d->scale,
pixel2->c.g>>d->scale,
pixel2->c.b>>d->scale);
return (A==B)?0:((A<B)?-1:1); return (A==B)?0:((A<B)?-1:1);
} }
static void static void
exists_count_func(const HashTable h, const void *key, void **val) exists_count_func(const HashTable *h, const Pixel key, uint32_t *val)
{ {
*(unsigned long*)val+=1; *val+=1;
} }
static void static void
new_count_func(const HashTable h, const void *key, void **val) new_count_func(const HashTable *h, const Pixel key, uint32_t *val)
{ {
*(unsigned long*)val=1; *val=1;
} }
static void static void
rehash_collide(HashTable h, rehash_collide(const HashTable *h,
void **keyp, Pixel *keyp,
void **valp, uint32_t *valp,
void *newkey, Pixel newkey,
void *newval) uint32_t newval)
{ {
*valp = (void *)(((unsigned long) *valp) + ((unsigned long) newval)); *valp += newval;
} }
/* %% */ /* %% */
static HashTable static HashTable *
create_pixel_hash(Pixel *pixelData,unsigned long nPixels) create_pixel_hash(Pixel *pixelData,uint32_t nPixels)
{ {
PixelHashData *d; PixelHashData *d;
HashTable *hash; HashTable *hash;
unsigned long i; uint32_t i;
unsigned long timer,timer2,timer3; #ifndef NO_OUTPUT
uint32_t timer,timer2,timer3;
#endif
d=malloc(sizeof(PixelHashData)); d=malloc(sizeof(PixelHashData));
if (!d) return NULL; if (!d) return NULL;
hash=hashtable_new(pixel_hash,pixel_cmp); hash=hashtable_new(pixel_hash,pixel_cmp);
hashtable_set_user_data(hash,d); hashtable_set_user_data(hash,d);
d->scale=0; d->scale=0;
#ifndef NO_OUTPUT
timer=timer3=clock(); timer=timer3=clock();
#endif
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
if (!hashtable_insert_or_update_computed(hash, if (!hashtable_insert_or_update_computed(hash,
(void *)pixelData[i].v, pixelData[i],
new_count_func, new_count_func,
exists_count_func)) {; exists_count_func)) {;
} }
@ -181,14 +167,14 @@ create_pixel_hash(Pixel *pixelData,unsigned long nPixels)
d->scale++; d->scale++;
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
printf ("rehashing - new scale: %d\n",(int)d->scale); printf ("rehashing - new scale: %d\n",(int)d->scale);
#endif
timer2=clock(); timer2=clock();
hashtable_rehash_compute(hash,rehash_collide);
timer2=clock()-timer2;
#ifndef NO_OUTPUT
printf ("rehash took %f sec\n",timer2/(double)CLOCKS_PER_SEC);
#endif #endif
hashtable_rehash_compute(hash,rehash_collide);
#ifndef NO_OUTPUT
timer2=clock()-timer2;
printf ("rehash took %f sec\n",timer2/(double)CLOCKS_PER_SEC);
timer+=timer2; timer+=timer2;
#endif
} }
} }
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
@ -201,7 +187,7 @@ create_pixel_hash(Pixel *pixelData,unsigned long nPixels)
} }
static void static void
destroy_pixel_hash(HashTable hash) destroy_pixel_hash(HashTable *hash)
{ {
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(hash); PixelHashData *d=(PixelHashData *)hashtable_get_user_data(hash);
if (d) free(d); if (d) free(d);
@ -237,17 +223,15 @@ compute_box_volume(BoxNode *b)
} }
static void static void
hash_to_list(HashTable h, const void *key, const void *val, void *u) hash_to_list(const HashTable *h, const Pixel pixel, const uint32_t count, void *u)
{ {
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h); PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
PixelList **pl=(PixelList **)u; PixelList **pl=(PixelList **)u;
PixelList *p; PixelList *p;
Pixel *pixel=(Pixel *)&key;
int i; int i;
Pixel q; Pixel q;
int count=(unsigned long) val;
PIXEL_SCALE(pixel,&q,d->scale); PIXEL_SCALE(&pixel,&q,d->scale);
p=malloc(sizeof(PixelList)); p=malloc(sizeof(PixelList));
if (!p) return; if (!p) return;
@ -327,7 +311,7 @@ test_sorted(PixelList *pl[3])
#endif #endif
static int static int
box_heap_cmp(const Heap h, const void *A, const void *B) box_heap_cmp(const Heap *h, const void *A, const void *B)
{ {
BoxNode *a=(BoxNode *)A; BoxNode *a=(BoxNode *)A;
BoxNode *b=(BoxNode *)B; BoxNode *b=(BoxNode *)B;
@ -341,11 +325,11 @@ splitlists(PixelList *h[3],
PixelList *t[3], PixelList *t[3],
PixelList *nh[2][3], PixelList *nh[2][3],
PixelList *nt[2][3], PixelList *nt[2][3],
unsigned long nCount[2], uint32_t nCount[2],
int axis, int axis,
unsigned long pixelCount) uint32_t pixelCount)
{ {
unsigned long left; uint32_t left;
PixelList *l,*r,*c,*n; PixelList *l,*r,*c,*n;
int i; int i;
@ -476,7 +460,7 @@ split(BoxNode *node)
int i; int i;
PixelList *heads[2][3]; PixelList *heads[2][3];
PixelList *tails[2][3]; PixelList *tails[2][3];
unsigned long newCounts[2]; uint32_t newCounts[2];
BoxNode *left,*right; BoxNode *left,*right;
rh=node->head[0]->p.c.r; rh=node->head[0]->p.c.r;
@ -618,13 +602,13 @@ split(BoxNode *node)
static BoxNode * static BoxNode *
median_cut(PixelList *hl[3], median_cut(PixelList *hl[3],
unsigned long imPixelCount, uint32_t imPixelCount,
int nPixels) int nPixels)
{ {
PixelList *tl[3]; PixelList *tl[3];
int i; int i;
BoxNode *root; BoxNode *root;
Heap h; Heap* h;
BoxNode *thisNode; BoxNode *thisNode;
h=ImagingQuantHeapNew(box_heap_cmp); h=ImagingQuantHeapNew(box_heap_cmp);
@ -701,7 +685,7 @@ checkContained(BoxNode *n,Pixel *pp)
#endif #endif
static int static int
annotate_hash_table(BoxNode *n,HashTable h,unsigned long *box) annotate_hash_table(BoxNode *n,HashTable *h,uint32_t *box)
{ {
PixelList *p; PixelList *p;
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h); PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
@ -717,7 +701,7 @@ annotate_hash_table(BoxNode *n,HashTable h,unsigned long *box)
} }
for (p=n->head[0];p;p=p->next[0]) { for (p=n->head[0];p;p=p->next[0]) {
PIXEL_UNSCALE(&(p->p),&q,d->scale); PIXEL_UNSCALE(&(p->p),&q,d->scale);
if (!hashtable_insert(h,(void *)q.v,(void *)*box)) { if (!hashtable_insert(h,q,*box)) {
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
printf ("hashtable insert failed\n"); printf ("hashtable insert failed\n");
#endif #endif
@ -731,20 +715,20 @@ annotate_hash_table(BoxNode *n,HashTable h,unsigned long *box)
static int static int
_sort_ulong_ptr_keys(const void *a, const void *b) _sort_ulong_ptr_keys(const void *a, const void *b)
{ {
unsigned long A=**(unsigned long **)a; uint32_t A=**(uint32_t **)a;
unsigned long B=**(unsigned long **)b; uint32_t B=**(uint32_t **)b;
return (A==B)?0:((A<B)?-1:+1); return (A==B)?0:((A<B)?-1:+1);
} }
static int static int
resort_distance_tables(unsigned long *avgDist, resort_distance_tables(uint32_t *avgDist,
unsigned long **avgDistSortKey, uint32_t **avgDistSortKey,
Pixel *p, Pixel *p,
unsigned long nEntries) uint32_t nEntries)
{ {
unsigned long i,j,k; uint32_t i,j,k;
unsigned long **skRow; uint32_t **skRow;
unsigned long *skElt; uint32_t *skElt;
for (i=0;i<nEntries;i++) { for (i=0;i<nEntries;i++) {
avgDist[i*nEntries+i]=0; avgDist[i*nEntries+i]=0;
@ -767,12 +751,12 @@ resort_distance_tables(unsigned long *avgDist,
} }
static int static int
build_distance_tables(unsigned long *avgDist, build_distance_tables(uint32_t *avgDist,
unsigned long **avgDistSortKey, uint32_t **avgDistSortKey,
Pixel *p, Pixel *p,
unsigned long nEntries) uint32_t nEntries)
{ {
unsigned long i,j; uint32_t i,j;
for (i=0;i<nEntries;i++) { for (i=0;i<nEntries;i++) {
avgDist[i*nEntries+i]=0; avgDist[i*nEntries+i]=0;
@ -787,7 +771,7 @@ build_distance_tables(unsigned long *avgDist,
for (i=0;i<nEntries;i++) { for (i=0;i<nEntries;i++) {
qsort(avgDistSortKey+i*nEntries, qsort(avgDistSortKey+i*nEntries,
nEntries, nEntries,
sizeof(unsigned long *), sizeof(uint32_t *),
_sort_ulong_ptr_keys); _sort_ulong_ptr_keys);
} }
return 1; return 1;
@ -795,23 +779,23 @@ build_distance_tables(unsigned long *avgDist,
static int static int
map_image_pixels(Pixel *pixelData, map_image_pixels(Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
Pixel *paletteData, Pixel *paletteData,
unsigned long nPaletteEntries, uint32_t nPaletteEntries,
unsigned long *avgDist, uint32_t *avgDist,
unsigned long **avgDistSortKey, uint32_t **avgDistSortKey,
unsigned long *pixelArray) uint32_t *pixelArray)
{ {
unsigned long *aD,**aDSK; uint32_t *aD,**aDSK;
unsigned long idx; uint32_t idx;
unsigned long i,j; uint32_t i,j;
unsigned long bestdist,bestmatch,dist; uint32_t bestdist,bestmatch,dist;
unsigned long initialdist; uint32_t initialdist;
HashTable h2; HashTable *h2;
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
if (!hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&bestmatch)) { if (!hashtable_lookup(h2,pixelData[i],&bestmatch)) {
bestmatch=0; bestmatch=0;
initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i); initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i);
bestdist=initialdist; bestdist=initialdist;
@ -830,7 +814,7 @@ map_image_pixels(Pixel *pixelData,
break; break;
} }
} }
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch); hashtable_insert(h2,pixelData[i],bestmatch);
} }
pixelArray[i]=bestmatch; pixelArray[i]=bestmatch;
} }
@ -841,26 +825,26 @@ map_image_pixels(Pixel *pixelData,
static int static int
map_image_pixels_from_quantized_pixels( map_image_pixels_from_quantized_pixels(
Pixel *pixelData, Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
Pixel *paletteData, Pixel *paletteData,
unsigned long nPaletteEntries, uint32_t nPaletteEntries,
unsigned long *avgDist, uint32_t *avgDist,
unsigned long **avgDistSortKey, uint32_t **avgDistSortKey,
unsigned long *pixelArray, uint32_t *pixelArray,
unsigned long *avg[3], uint32_t *avg[3],
unsigned long *count) uint32_t *count)
{ {
unsigned long *aD,**aDSK; uint32_t *aD,**aDSK;
unsigned long idx; uint32_t idx;
unsigned long i,j; uint32_t i,j;
unsigned long bestdist,bestmatch,dist; uint32_t bestdist,bestmatch,dist;
unsigned long initialdist; uint32_t initialdist;
HashTable h2; HashTable *h2;
int changes=0; int changes=0;
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
if (!hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&bestmatch)) { if (!hashtable_lookup(h2,pixelData[i],&bestmatch)) {
bestmatch=pixelArray[i]; bestmatch=pixelArray[i];
initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i); initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i);
bestdist=initialdist; bestdist=initialdist;
@ -879,7 +863,7 @@ map_image_pixels_from_quantized_pixels(
break; break;
} }
} }
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch); hashtable_insert(h2,pixelData[i],bestmatch);
} }
if (pixelArray[i]!=bestmatch) { if (pixelArray[i]!=bestmatch) {
changes++; changes++;
@ -901,29 +885,29 @@ map_image_pixels_from_quantized_pixels(
static int static int
map_image_pixels_from_median_box( map_image_pixels_from_median_box(
Pixel *pixelData, Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
Pixel *paletteData, Pixel *paletteData,
unsigned long nPaletteEntries, uint32_t nPaletteEntries,
HashTable *medianBoxHash, HashTable *medianBoxHash,
unsigned long *avgDist, uint32_t *avgDist,
unsigned long **avgDistSortKey, uint32_t **avgDistSortKey,
unsigned long *pixelArray) uint32_t *pixelArray)
{ {
unsigned long *aD,**aDSK; uint32_t *aD,**aDSK;
unsigned long idx; uint32_t idx;
unsigned long i,j; uint32_t i,j;
unsigned long bestdist,bestmatch,dist; uint32_t bestdist,bestmatch,dist;
unsigned long initialdist; uint32_t initialdist;
HashTable h2; HashTable *h2;
unsigned long pixelVal; uint32_t pixelVal;
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
if (hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&pixelVal)) { if (hashtable_lookup(h2,pixelData[i],&pixelVal)) {
pixelArray[i]=pixelVal; pixelArray[i]=pixelVal;
continue; continue;
} }
if (!hashtable_lookup(medianBoxHash,(void *)pixelData[i].v,(void **)&pixelVal)) { if (!hashtable_lookup(medianBoxHash,pixelData[i],&pixelVal)) {
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
printf ("pixel lookup failed\n"); printf ("pixel lookup failed\n");
#endif #endif
@ -948,7 +932,7 @@ map_image_pixels_from_median_box(
} }
} }
pixelArray[i]=bestmatch; pixelArray[i]=bestmatch;
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch); hashtable_insert(h2,pixelData[i],bestmatch);
} }
hashtable_free(h2); hashtable_free(h2);
return 1; return 1;
@ -957,27 +941,27 @@ map_image_pixels_from_median_box(
static int static int
compute_palette_from_median_cut( compute_palette_from_median_cut(
Pixel *pixelData, Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
HashTable medianBoxHash, HashTable *medianBoxHash,
Pixel **palette, Pixel **palette,
unsigned long nPaletteEntries) uint32_t nPaletteEntries)
{ {
unsigned long i; uint32_t i;
unsigned long paletteEntry; uint32_t paletteEntry;
Pixel *p; Pixel *p;
unsigned long *avg[3]; uint32_t *avg[3];
unsigned long *count; uint32_t *count;
*palette=NULL; *palette=NULL;
if (!(count=malloc(sizeof(unsigned long)*nPaletteEntries))) { if (!(count=malloc(sizeof(uint32_t)*nPaletteEntries))) {
return 0; return 0;
} }
memset(count,0,sizeof(unsigned long)*nPaletteEntries); memset(count,0,sizeof(uint32_t)*nPaletteEntries);
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
avg[i]=NULL; avg[i]=NULL;
} }
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
if (!(avg[i]=malloc(sizeof(unsigned long)*nPaletteEntries))) { if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) {
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
if (avg[i]) free (avg[i]); if (avg[i]) free (avg[i]);
} }
@ -986,7 +970,7 @@ compute_palette_from_median_cut(
} }
} }
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
memset(avg[i],0,sizeof(unsigned long)*nPaletteEntries); memset(avg[i],0,sizeof(uint32_t)*nPaletteEntries);
} }
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
#ifdef TEST_SPLIT_INTEGRITY #ifdef TEST_SPLIT_INTEGRITY
@ -998,7 +982,7 @@ compute_palette_from_median_cut(
return 0; return 0;
} }
#endif #endif
if (!hashtable_lookup(medianBoxHash,(void *)pixelData[i].v,(void **)&paletteEntry)) { if (!hashtable_lookup(medianBoxHash,pixelData[i],&paletteEntry)) {
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
printf ("pixel lookup failed\n"); printf ("pixel lookup failed\n");
#endif #endif
@ -1039,11 +1023,11 @@ compute_palette_from_median_cut(
static int static int
recompute_palette_from_averages( recompute_palette_from_averages(
Pixel *palette, Pixel *palette,
unsigned long nPaletteEntries, uint32_t nPaletteEntries,
unsigned long *avg[3], uint32_t *avg[3],
unsigned long *count) uint32_t *count)
{ {
unsigned long i; uint32_t i;
for (i=0;i<nPaletteEntries;i++) { for (i=0;i<nPaletteEntries;i++) {
palette[i].c.r=(int)(.5+(double)avg[0][i]/(double)count[i]); palette[i].c.r=(int)(.5+(double)avg[0][i]/(double)count[i]);
@ -1056,18 +1040,18 @@ recompute_palette_from_averages(
static int static int
compute_palette_from_quantized_pixels( compute_palette_from_quantized_pixels(
Pixel *pixelData, Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
Pixel *palette, Pixel *palette,
unsigned long nPaletteEntries, uint32_t nPaletteEntries,
unsigned long *avg[3], uint32_t *avg[3],
unsigned long *count, uint32_t *count,
unsigned long *qp) uint32_t *qp)
{ {
unsigned long i; uint32_t i;
memset(count,0,sizeof(unsigned long)*nPaletteEntries); memset(count,0,sizeof(uint32_t)*nPaletteEntries);
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
memset(avg[i],0,sizeof(unsigned long)*nPaletteEntries); memset(avg[i],0,sizeof(uint32_t)*nPaletteEntries);
} }
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
if (qp[i]>=nPaletteEntries) { if (qp[i]>=nPaletteEntries) {
@ -1091,35 +1075,35 @@ compute_palette_from_quantized_pixels(
static int static int
k_means(Pixel *pixelData, k_means(Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
Pixel *paletteData, Pixel *paletteData,
unsigned long nPaletteEntries, uint32_t nPaletteEntries,
unsigned long *qp, uint32_t *qp,
int threshold) int threshold)
{ {
unsigned long *avg[3]; uint32_t *avg[3];
unsigned long *count; uint32_t *count;
unsigned long i; uint32_t i;
unsigned long *avgDist; uint32_t *avgDist;
unsigned long **avgDistSortKey; uint32_t **avgDistSortKey;
int changes; int changes;
int built=0; int built=0;
if (!(count=malloc(sizeof(unsigned long)*nPaletteEntries))) { if (!(count=malloc(sizeof(uint32_t)*nPaletteEntries))) {
return 0; return 0;
} }
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
avg[i]=NULL; avg[i]=NULL;
} }
for(i=0;i<3;i++) { for(i=0;i<3;i++) {
if (!(avg[i]=malloc(sizeof(unsigned long)*nPaletteEntries))) { if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) {
goto error_1; goto error_1;
} }
} }
avgDist=malloc(sizeof(unsigned long)*nPaletteEntries*nPaletteEntries); avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries);
if (!avgDist) { goto error_1; } if (!avgDist) { goto error_1; }
avgDistSortKey=malloc(sizeof(unsigned long *)*nPaletteEntries*nPaletteEntries); avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries);
if (!avgDistSortKey) { goto error_2; } if (!avgDistSortKey) { goto error_2; }
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
@ -1172,26 +1156,26 @@ error_1:
int int
quantize(Pixel *pixelData, quantize(Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
unsigned long nQuantPixels, uint32_t nQuantPixels,
Pixel **palette, Pixel **palette,
unsigned long *paletteLength, uint32_t *paletteLength,
unsigned long **quantizedPixels, uint32_t **quantizedPixels,
int kmeans) int kmeans)
{ {
PixelList *hl[3]; PixelList *hl[3];
HashTable h; HashTable *h;
BoxNode *root; BoxNode *root;
unsigned long i; uint32_t i;
unsigned long *qp; uint32_t *qp;
unsigned long nPaletteEntries; uint32_t nPaletteEntries;
unsigned long *avgDist; uint32_t *avgDist;
unsigned long **avgDistSortKey; uint32_t **avgDistSortKey;
Pixel *p; Pixel *p;
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
unsigned long timer,timer2; uint32_t timer,timer2;
#endif #endif
#ifndef NO_OUTPUT #ifndef NO_OUTPUT
@ -1266,13 +1250,13 @@ quantize(Pixel *pixelData,
free_box_tree(root); free_box_tree(root);
root=NULL; root=NULL;
qp=malloc(sizeof(unsigned long)*nPixels); qp=malloc(sizeof(uint32_t)*nPixels);
if (!qp) { goto error_4; } if (!qp) { goto error_4; }
avgDist=malloc(sizeof(unsigned long)*nPaletteEntries*nPaletteEntries); avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries);
if (!avgDist) { goto error_5; } if (!avgDist) { goto error_5; }
avgDistSortKey=malloc(sizeof(unsigned long *)*nPaletteEntries*nPaletteEntries); avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries);
if (!avgDistSortKey) { goto error_6; } if (!avgDistSortKey) { goto error_6; }
if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) { if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) {
@ -1286,12 +1270,12 @@ quantize(Pixel *pixelData,
#ifdef TEST_NEAREST_NEIGHBOUR #ifdef TEST_NEAREST_NEIGHBOUR
#include <math.h> #include <math.h>
{ {
unsigned long bestmatch,bestdist,dist; uint32_t bestmatch,bestdist,dist;
HashTable h2; HashTable *h2;
printf ("nearest neighbour search (full search)..."); fflush(stdout); timer=clock(); printf ("nearest neighbour search (full search)..."); fflush(stdout); timer=clock();
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
if (hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&paletteEntry)) { if (hashtable_lookup(h2,pixelData[i],&paletteEntry)) {
bestmatch=paletteEntry; bestmatch=paletteEntry;
} else { } else {
bestmatch=0; bestmatch=0;
@ -1312,7 +1296,7 @@ quantize(Pixel *pixelData,
bestmatch=j; bestmatch=j;
} }
} }
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch); hashtable_insert(h2,pixelData[i],bestmatch);
} }
if (qp[i]!=bestmatch ) { if (qp[i]!=bestmatch ) {
printf ("discrepancy in matching algorithms pixel %d [%d %d] %f %f\n", printf ("discrepancy in matching algorithms pixel %d [%d %d] %f %f\n",
@ -1375,53 +1359,52 @@ error_0:
typedef struct { typedef struct {
Pixel new; Pixel new;
Pixel furthest; Pixel furthest;
unsigned long furthestDistance; uint32_t furthestDistance;
int secondPixel; int secondPixel;
} DistanceData; } DistanceData;
static void static void
compute_distances(const HashTable h, const void *key, void **val, void *u) compute_distances(const HashTable *h, const Pixel pixel, uint32_t *dist, void *u)
{ {
DistanceData *data=(DistanceData *)u; DistanceData *data=(DistanceData *)u;
Pixel *pixel=(Pixel *)&key; uint32_t oldDist=*dist;
unsigned long oldDist=*(unsigned long *)val; uint32_t newDist;
unsigned long newDist; newDist=_DISTSQR(&(data->new),&pixel);
newDist=_DISTSQR(&(data->new),pixel);
if (data->secondPixel || newDist<oldDist) { if (data->secondPixel || newDist<oldDist) {
*(unsigned long *)val=newDist; *dist=newDist;
oldDist=newDist; oldDist=newDist;
} }
if (oldDist>data->furthestDistance) { if (oldDist>data->furthestDistance) {
data->furthestDistance=oldDist; data->furthestDistance=oldDist;
data->furthest.v=pixel->v; data->furthest.v=pixel.v;
} }
} }
int int
quantize2(Pixel *pixelData, quantize2(Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
unsigned long nQuantPixels, uint32_t nQuantPixels,
Pixel **palette, Pixel **palette,
unsigned long *paletteLength, uint32_t *paletteLength,
unsigned long **quantizedPixels, uint32_t **quantizedPixels,
int kmeans) int kmeans)
{ {
HashTable h; HashTable *h;
unsigned long i; uint32_t i;
unsigned long mean[3]; uint32_t mean[3];
Pixel *p; Pixel *p;
DistanceData data; DistanceData data;
unsigned long *qp; uint32_t *qp;
unsigned long *avgDist; uint32_t *avgDist;
unsigned long **avgDistSortKey; uint32_t **avgDistSortKey;
p=malloc(sizeof(Pixel)*nQuantPixels); p=malloc(sizeof(Pixel)*nQuantPixels);
if (!p) return 0; if (!p) return 0;
mean[0]=mean[1]=mean[2]=0; mean[0]=mean[1]=mean[2]=0;
h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp); h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) { for (i=0;i<nPixels;i++) {
hashtable_insert(h,(void *)pixelData[i].v,(void *)0xffffffff); hashtable_insert(h,pixelData[i],0xffffffff);
mean[0]+=pixelData[i].c.r; mean[0]+=pixelData[i].c.r;
mean[1]+=pixelData[i].c.g; mean[1]+=pixelData[i].c.g;
mean[2]+=pixelData[i].c.b; mean[2]+=pixelData[i].c.b;
@ -1438,13 +1421,13 @@ quantize2(Pixel *pixelData,
} }
hashtable_free(h); hashtable_free(h);
qp=malloc(sizeof(unsigned long)*nPixels); qp=malloc(sizeof(uint32_t)*nPixels);
if (!qp) { goto error_1; } if (!qp) { goto error_1; }
avgDist=malloc(sizeof(unsigned long)*nQuantPixels*nQuantPixels); avgDist=malloc(sizeof(uint32_t)*nQuantPixels*nQuantPixels);
if (!avgDist) { goto error_2; } if (!avgDist) { goto error_2; }
avgDistSortKey=malloc(sizeof(unsigned long *)*nQuantPixels*nQuantPixels); avgDistSortKey=malloc(sizeof(uint32_t *)*nQuantPixels*nQuantPixels);
if (!avgDistSortKey) { goto error_3; } if (!avgDistSortKey) { goto error_3; }
if (!build_distance_tables(avgDist,avgDistSortKey,p,nQuantPixels)) { if (!build_distance_tables(avgDist,avgDistSortKey,p,nQuantPixels)) {
@ -1482,9 +1465,9 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
UINT8* pp; UINT8* pp;
Pixel* p; Pixel* p;
Pixel* palette; Pixel* palette;
unsigned long paletteLength; uint32_t paletteLength;
int result; int result;
unsigned long* newData; uint32_t* newData;
Imaging imOut; Imaging imOut;
int withAlpha = 0; int withAlpha = 0;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;

View File

@ -1,40 +0,0 @@
/*
* The Python Imaging Library
* $Id$
*
* image quantizer
*
* Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
*
* See the README file for information on usage and redistribution.
*/
#ifndef __QUANT_H__
#define __QUANT_H__
typedef union {
struct {
unsigned char r,g,b,a;
} c;
struct {
unsigned char v[4];
} a;
unsigned long v;
} Pixel;
int quantize(Pixel *,
unsigned long,
unsigned long,
Pixel **,
unsigned long *,
unsigned long **,
int);
int quantize2(Pixel *,
unsigned long,
unsigned long,
Pixel **,
unsigned long *,
unsigned long **,
int);
#endif

View File

@ -1,25 +0,0 @@
/*
* The Python Imaging Library
* $Id$
*
* image quantizer
*
* Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
*
* See the README file for information on usage and redistribution.
*/
#ifndef __DEFINES_H__
#define __DEFINES_H__
#if 0
void *newMalloc(size_t,const char *,const char *,int);
void newFree(void *,const char *,const char *,int);
void print_malloc_stats();
#define malloc(x) newMalloc(x,__FILE__,__FUNCTION__,__LINE__)
#define free(x) newFree(x,__FILE__,__FUNCTION__,__LINE__)
#endif
#endif

View File

@ -22,35 +22,35 @@
#include <math.h> #include <math.h>
#include "QuantHash.h" #include "QuantHash.h"
#include "QuantDefines.h"
typedef struct _IntHashNode { typedef struct _HashNode {
struct _IntHashNode *next; struct _HashNode *next;
void *key,*value; HashKey_t key;
} IntHashNode; HashVal_t value;
} HashNode;
typedef struct _IntHashTable { typedef struct _HashTable {
IntHashNode **table; HashNode **table;
unsigned long length; uint32_t length;
unsigned long count; uint32_t count;
HashFunc hashFunc; HashFunc hashFunc;
HashCmpFunc cmpFunc; HashCmpFunc cmpFunc;
DestroyFunc keyDestroyFunc; KeyDestroyFunc keyDestroyFunc;
DestroyFunc valDestroyFunc; ValDestroyFunc valDestroyFunc;
void *userData; void *userData;
} IntHashTable; } HashTable;
#define MIN_LENGTH 11 #define MIN_LENGTH 11
#define RESIZE_FACTOR 3 #define RESIZE_FACTOR 3
static int _hashtable_insert_node(IntHashTable *,IntHashNode *,int,int,CollisionFunc); static int _hashtable_insert_node(HashTable *,HashNode *,int,int,CollisionFunc);
#if 0 #if 0
static int _hashtable_test(IntHashTable *); static int _hashtable_test(HashTable *);
#endif #endif
HashTable hashtable_new(HashFunc hf,HashCmpFunc cf) { HashTable *hashtable_new(HashFunc hf,HashCmpFunc cf) {
IntHashTable *h; HashTable *h;
h=malloc(sizeof(IntHashTable)); h=malloc(sizeof(HashTable));
if (!h) { return NULL; } if (!h) { return NULL; }
h->hashFunc=hf; h->hashFunc=hf;
h->cmpFunc=cf; h->cmpFunc=cf;
@ -59,25 +59,24 @@ HashTable hashtable_new(HashFunc hf,HashCmpFunc cf) {
h->length=MIN_LENGTH; h->length=MIN_LENGTH;
h->count=0; h->count=0;
h->userData=NULL; h->userData=NULL;
h->table=malloc(sizeof(IntHashNode *)*h->length); h->table=malloc(sizeof(HashNode *)*h->length);
if (!h->table) { free(h); return NULL; } if (!h->table) { free(h); return NULL; }
memset (h->table,0,sizeof(IntHashNode *)*h->length); memset (h->table,0,sizeof(HashNode *)*h->length);
return (HashTable)h; return h;
} }
static void _hashtable_destroy(HashTable H,const void *key,const void *val,void *u) { static void _hashtable_destroy(const HashTable *h,const HashKey_t key,const HashVal_t val,void *u) {
IntHashTable *h=(IntHashTable *)H; if (h->keyDestroyFunc) {
if (h->keyDestroyFunc&&key) { h->keyDestroyFunc(h,key);
h->keyDestroyFunc((HashTable)h,(void *)key);
} }
if (h->valDestroyFunc&&val) { if (h->valDestroyFunc) {
h->valDestroyFunc((HashTable)h,(void *)val); h->valDestroyFunc(h,val);
} }
} }
static unsigned long _findPrime(unsigned long start,int dir) { static uint32_t _findPrime(uint32_t start,int dir) {
static int unit[]={0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0}; static int unit[]={0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0};
unsigned long t; uint32_t t;
while (start>1) { while (start>1) {
if (!unit[start&0x0f]) { if (!unit[start&0x0f]) {
start+=dir; start+=dir;
@ -94,22 +93,20 @@ static unsigned long _findPrime(unsigned long start,int dir) {
return start; return start;
} }
static void _hashtable_rehash(IntHashTable *h, static void _hashtable_rehash(HashTable *h,CollisionFunc cf,uint32_t newSize) {
CollisionFunc cf, HashNode **oldTable=h->table;
unsigned long newSize) { uint32_t i;
IntHashNode **oldTable=h->table; HashNode *n,*nn;
unsigned long i; uint32_t oldSize;
IntHashNode *n,*nn;
unsigned long oldSize;
oldSize=h->length; oldSize=h->length;
h->table=malloc(sizeof(IntHashNode *)*newSize); h->table=malloc(sizeof(HashNode *)*newSize);
if (!h->table) { if (!h->table) {
h->table=oldTable; h->table=oldTable;
return; return;
} }
h->length=newSize; h->length=newSize;
h->count=0; h->count=0;
memset (h->table,0,sizeof(IntHashNode *)*h->length); memset (h->table,0,sizeof(HashNode *)*h->length);
for (i=0;i<oldSize;i++) { for (i=0;i<oldSize;i++) {
for (n=oldTable[i];n;n=nn) { for (n=oldTable[i];n;n=nn) {
nn=n->next; nn=n->next;
@ -119,9 +116,9 @@ static void _hashtable_rehash(IntHashTable *h,
free(oldTable); free(oldTable);
} }
static void _hashtable_resize(IntHashTable *h) { static void _hashtable_resize(HashTable *h) {
unsigned long newSize; uint32_t newSize;
unsigned long oldSize; uint32_t oldSize;
oldSize=h->length; oldSize=h->length;
newSize=oldSize; newSize=oldSize;
if (h->count*RESIZE_FACTOR<h->length) { if (h->count*RESIZE_FACTOR<h->length) {
@ -136,13 +133,13 @@ static void _hashtable_resize(IntHashTable *h) {
} }
#if 0 #if 0
static int _hashtable_test(IntHashTable *h) { static int _hashtable_test(HashTable *h) {
unsigned long i; uint32_t i;
int j; int j;
IntHashNode *n; HashNode *n;
for (i=0;i<h->length;i++) { for (i=0;i<h->length;i++) {
for (n=h->table[i];n&&n->next;n=n->next) { for (n=h->table[i];n&&n->next;n=n->next) {
j=h->cmpFunc((HashTable)h,n->key,n->next->key); j=h->cmpFunc(h,n->key,n->next->key);
printf ("%c",j?(j<0?'-':'+'):'='); printf ("%c",j?(j<0?'-':'+'):'=');
} }
printf ("\n"); printf ("\n");
@ -151,26 +148,26 @@ static int _hashtable_test(IntHashTable *h) {
} }
#endif #endif
static int _hashtable_insert_node(IntHashTable *h,IntHashNode *node,int resize,int update,CollisionFunc cf) { static int _hashtable_insert_node(HashTable *h,HashNode *node,int resize,int update,CollisionFunc cf) {
unsigned long hash=h->hashFunc((HashTable)h,node->key)%h->length; uint32_t hash=h->hashFunc(h,node->key)%h->length;
IntHashNode **n,*nv; HashNode **n,*nv;
int i; int i;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) { for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n; nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,node->key); i=h->cmpFunc(h,nv->key,node->key);
if (!i) { if (!i) {
if (cf) { if (cf) {
nv->key=node->key; nv->key=node->key;
cf((HashTable)h,&(nv->key),&(nv->value),node->key,node->value); cf(h,&(nv->key),&(nv->value),node->key,node->value);
free(node); free(node);
return 1; return 1;
} else { } else {
if (h->valDestroyFunc) { if (h->valDestroyFunc) {
h->valDestroyFunc((HashTable)h,nv->value); h->valDestroyFunc(h,nv->value);
} }
if (h->keyDestroyFunc) { if (h->keyDestroyFunc) {
h->keyDestroyFunc((HashTable)h,nv->key); h->keyDestroyFunc(h,nv->key);
} }
nv->key=node->key; nv->key=node->key;
nv->value=node->value; nv->value=node->value;
@ -192,17 +189,17 @@ static int _hashtable_insert_node(IntHashTable *h,IntHashNode *node,int resize,i
} }
} }
static int _hashtable_insert(IntHashTable *h,void *key,void *val,int resize,int update) { static int _hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val,int resize,int update) {
IntHashNode **n,*nv; HashNode **n,*nv;
IntHashNode *t; HashNode *t;
int i; int i;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length; uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) { for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n; nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,key); i=h->cmpFunc(h,nv->key,key);
if (!i) { if (!i) {
if (h->valDestroyFunc) { h->valDestroyFunc((HashTable)h,nv->value); } if (h->valDestroyFunc) { h->valDestroyFunc(h,nv->value); }
nv->value=val; nv->value=val;
return 1; return 1;
} else if (i>0) { } else if (i>0) {
@ -210,7 +207,7 @@ static int _hashtable_insert(IntHashTable *h,void *key,void *val,int resize,int
} }
} }
if (!update) { if (!update) {
t=malloc(sizeof(IntHashNode)); t=malloc(sizeof(HashNode));
if (!t) return 0; if (!t) return 0;
t->next=*n; t->next=*n;
*n=t; *n=t;
@ -224,15 +221,15 @@ static int _hashtable_insert(IntHashTable *h,void *key,void *val,int resize,int
} }
} }
static int _hashtable_lookup_or_insert(IntHashTable *h,void *key,void **retVal,void *newVal,int resize) { static int _hashtable_lookup_or_insert(HashTable *h,HashKey_t key,HashVal_t *retVal,HashVal_t newVal,int resize) {
IntHashNode **n,*nv; HashNode **n,*nv;
IntHashNode *t; HashNode *t;
int i; int i;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length; uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) { for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n; nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,key); i=h->cmpFunc(h,nv->key,key);
if (!i) { if (!i) {
*retVal=nv->value; *retVal=nv->value;
return 1; return 1;
@ -240,7 +237,7 @@ static int _hashtable_lookup_or_insert(IntHashTable *h,void *key,void **retVal,v
break; break;
} }
} }
t=malloc(sizeof(IntHashNode)); t=malloc(sizeof(HashNode));
if (!t) return 0; if (!t) return 0;
t->next=*n; t->next=*n;
*n=t; *n=t;
@ -252,26 +249,25 @@ static int _hashtable_lookup_or_insert(IntHashTable *h,void *key,void **retVal,v
return 1; return 1;
} }
int hashtable_insert_or_update_computed(HashTable H, int hashtable_insert_or_update_computed(HashTable *h,
void *key, HashKey_t key,
ComputeFunc newFunc, ComputeFunc newFunc,
ComputeFunc existsFunc) { ComputeFunc existsFunc) {
IntHashTable *h=(IntHashTable *)H; HashNode **n,*nv;
IntHashNode **n,*nv; HashNode *t;
IntHashNode *t;
int i; int i;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length; uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) { for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n; nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,key); i=h->cmpFunc(h,nv->key,key);
if (!i) { if (!i) {
void *old=nv->value; HashVal_t old=nv->value;
if (existsFunc) { if (existsFunc) {
existsFunc(H,nv->key,&(nv->value)); existsFunc(h,nv->key,&(nv->value));
if (nv->value!=old) { if (nv->value!=old) {
if (h->valDestroyFunc) { if (h->valDestroyFunc) {
h->valDestroyFunc((HashTable)h,old); h->valDestroyFunc(h,old);
} }
} }
} else { } else {
@ -282,13 +278,13 @@ int hashtable_insert_or_update_computed(HashTable H,
break; break;
} }
} }
t=malloc(sizeof(IntHashNode)); t=malloc(sizeof(HashNode));
if (!t) return 0; if (!t) return 0;
t->key=key; t->key=key;
t->next=*n; t->next=*n;
*n=t; *n=t;
if (newFunc) { if (newFunc) {
newFunc(H,t->key,&(t->value)); newFunc(h,t->key,&(t->value));
} else { } else {
free(t); free(t);
return 0; return 0;
@ -298,52 +294,47 @@ int hashtable_insert_or_update_computed(HashTable H,
return 1; return 1;
} }
int hashtable_update(HashTable H,void *key,void *val) { int hashtable_update(HashTable *h,HashKey_t key,HashVal_t val) {
IntHashTable *h=(IntHashTable *)H;
return _hashtable_insert(h,key,val,1,0); return _hashtable_insert(h,key,val,1,0);
} }
int hashtable_insert(HashTable H,void *key,void *val) { int hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val) {
IntHashTable *h=(IntHashTable *)H;
return _hashtable_insert(h,key,val,1,0); return _hashtable_insert(h,key,val,1,0);
} }
void hashtable_foreach_update(HashTable H,IteratorUpdateFunc i,void *u) { void hashtable_foreach_update(HashTable *h,IteratorUpdateFunc i,void *u) {
IntHashTable *h=(IntHashTable *)H; HashNode *n;
IntHashNode *n; uint32_t x;
unsigned long x;
if (h->table) { if (h->table) {
for (x=0;x<h->length;x++) { for (x=0;x<h->length;x++) {
for (n=h->table[x];n;n=n->next) { for (n=h->table[x];n;n=n->next) {
i((HashTable)h,n->key,(void **)&(n->value),u); i(h,n->key,&(n->value),u);
} }
} }
} }
} }
void hashtable_foreach(HashTable H,IteratorFunc i,void *u) { void hashtable_foreach(HashTable *h,IteratorFunc i,void *u) {
IntHashTable *h=(IntHashTable *)H; HashNode *n;
IntHashNode *n; uint32_t x;
unsigned long x;
if (h->table) { if (h->table) {
for (x=0;x<h->length;x++) { for (x=0;x<h->length;x++) {
for (n=h->table[x];n;n=n->next) { for (n=h->table[x];n;n=n->next) {
i((HashTable)h,n->key,n->value,u); i(h,n->key,n->value,u);
} }
} }
} }
} }
void hashtable_free(HashTable H) { void hashtable_free(HashTable *h) {
IntHashTable *h=(IntHashTable *)H; HashNode *n,*nn;
IntHashNode *n,*nn; uint32_t i;
unsigned long i;
if (h->table) { if (h->table) {
if (h->keyDestroyFunc || h->keyDestroyFunc) { if (h->keyDestroyFunc || h->keyDestroyFunc) {
hashtable_foreach(H,_hashtable_destroy,NULL); hashtable_foreach(h,_hashtable_destroy,NULL);
} }
for (i=0;i<h->length;i++) { for (i=0;i<h->length;i++) {
for (n=h->table[i];n;n=nn) { for (n=h->table[i];n;n=nn) {
@ -356,31 +347,29 @@ void hashtable_free(HashTable H) {
free(h); free(h);
} }
DestroyFunc hashtable_set_value_destroy_func(HashTable H,DestroyFunc d) { ValDestroyFunc hashtable_set_value_destroy_func(HashTable *h,ValDestroyFunc d) {
IntHashTable *h=(IntHashTable *)H; ValDestroyFunc r=h->valDestroyFunc;
DestroyFunc r=h->valDestroyFunc;
h->valDestroyFunc=d; h->valDestroyFunc=d;
return r; return r;
} }
DestroyFunc hashtable_set_key_destroy_func(HashTable H,DestroyFunc d) { KeyDestroyFunc hashtable_set_key_destroy_func(HashTable *h,KeyDestroyFunc d) {
IntHashTable *h=(IntHashTable *)H; KeyDestroyFunc r=h->keyDestroyFunc;
DestroyFunc r=h->keyDestroyFunc;
h->keyDestroyFunc=d; h->keyDestroyFunc=d;
return r; return r;
} }
static int _hashtable_remove(IntHashTable *h, static int _hashtable_remove(HashTable *h,
const void *key, const HashKey_t key,
void **keyRet, HashKey_t *keyRet,
void **valRet, HashVal_t *valRet,
int resize) { int resize) {
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length; uint32_t hash=h->hashFunc(h,key)%h->length;
IntHashNode *n,*p; HashNode *n,*p;
int i; int i;
for (p=NULL,n=h->table[hash];n;p=n,n=n->next) { for (p=NULL,n=h->table[hash];n;p=n,n=n->next) {
i=h->cmpFunc((HashTable)h,n->key,key); i=h->cmpFunc(h,n->key,key);
if (!i) { if (!i) {
if (p) p=n->next; else h->table[hash]=n->next; if (p) p=n->next; else h->table[hash]=n->next;
*keyRet=n->key; *keyRet=n->key;
@ -395,17 +384,17 @@ static int _hashtable_remove(IntHashTable *h,
return 0; return 0;
} }
static int _hashtable_delete(IntHashTable *h,const void *key,int resize) { static int _hashtable_delete(HashTable *h,const HashKey_t key,int resize) {
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length; uint32_t hash=h->hashFunc(h,key)%h->length;
IntHashNode *n,*p; HashNode *n,*p;
int i; int i;
for (p=NULL,n=h->table[hash];n;p=n,n=n->next) { for (p=NULL,n=h->table[hash];n;p=n,n=n->next) {
i=h->cmpFunc((HashTable)h,n->key,key); i=h->cmpFunc(h,n->key,key);
if (!i) { if (!i) {
if (p) p=n->next; else h->table[hash]=n->next; if (p) p=n->next; else h->table[hash]=n->next;
if (h->valDestroyFunc) { h->valDestroyFunc((HashTable)h,n->value); } if (h->valDestroyFunc) { h->valDestroyFunc(h,n->value); }
if (h->keyDestroyFunc) { h->keyDestroyFunc((HashTable)h,n->key); } if (h->keyDestroyFunc) { h->keyDestroyFunc(h,n->key); }
free(n); free(n);
h->count++; h->count++;
return 1; return 1;
@ -416,39 +405,33 @@ static int _hashtable_delete(IntHashTable *h,const void *key,int resize) {
return 0; return 0;
} }
int hashtable_remove(HashTable H,const void *key,void **keyRet,void **valRet) { int hashtable_remove(HashTable *h,const HashKey_t key,HashKey_t *keyRet,HashVal_t *valRet) {
IntHashTable *h=(IntHashTable *)H;
return _hashtable_remove(h,key,keyRet,valRet,1); return _hashtable_remove(h,key,keyRet,valRet,1);
} }
int hashtable_delete(HashTable H,const void *key) { int hashtable_delete(HashTable *h,const HashKey_t key) {
IntHashTable *h=(IntHashTable *)H;
return _hashtable_delete(h,key,1); return _hashtable_delete(h,key,1);
} }
void hashtable_rehash_compute(HashTable H,CollisionFunc cf) { void hashtable_rehash_compute(HashTable *h,CollisionFunc cf) {
IntHashTable *h=(IntHashTable *)H;
_hashtable_rehash(h,cf,h->length); _hashtable_rehash(h,cf,h->length);
} }
void hashtable_rehash(HashTable H) { void hashtable_rehash(HashTable *h) {
IntHashTable *h=(IntHashTable *)H;
_hashtable_rehash(h,NULL,h->length); _hashtable_rehash(h,NULL,h->length);
} }
int hashtable_lookup_or_insert(HashTable H,void *key,void **valp,void *val) { int hashtable_lookup_or_insert(HashTable *h,HashKey_t key,HashVal_t *valp,HashVal_t val) {
IntHashTable *h=(IntHashTable *)H;
return _hashtable_lookup_or_insert(h,key,valp,val,1); return _hashtable_lookup_or_insert(h,key,valp,val,1);
} }
int hashtable_lookup(const HashTable H,const void *key,void **valp) { int hashtable_lookup(const HashTable *h,const HashKey_t key,HashVal_t *valp) {
IntHashTable *h=(IntHashTable *)H; uint32_t hash=h->hashFunc(h,key)%h->length;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length; HashNode *n;
IntHashNode *n;
int i; int i;
for (n=h->table[hash];n;n=n->next) { for (n=h->table[hash];n;n=n->next) {
i=h->cmpFunc((HashTable)h,n->key,key); i=h->cmpFunc(h,n->key,key);
if (!i) { if (!i) {
*valp=n->value; *valp=n->value;
return 1; return 1;
@ -459,18 +442,15 @@ int hashtable_lookup(const HashTable H,const void *key,void **valp) {
return 0; return 0;
} }
unsigned long hashtable_get_count(const HashTable H) { uint32_t hashtable_get_count(const HashTable *h) {
IntHashTable *h=(IntHashTable *)H;
return h->count; return h->count;
} }
void *hashtable_get_user_data(const HashTable H) { void *hashtable_get_user_data(const HashTable *h) {
IntHashTable *h=(IntHashTable *)H;
return h->userData; return h->userData;
} }
void *hashtable_set_user_data(HashTable H,void *data) { void *hashtable_set_user_data(HashTable *h,void *data) {
IntHashTable *h=(IntHashTable *)H;
void *r=h->userData; void *r=h->userData;
h->userData=data; h->userData=data;
return r; return r;

View File

@ -9,28 +9,41 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#ifndef __HASH_H__ #ifndef __QUANTHASH_H__
#define __HASH_H__ #define __QUANTHASH_H__
#include "QuantTypes.h" #include "QuantTypes.h"
HashTable hashtable_new(HashFunc,HashCmpFunc); typedef struct _HashTable HashTable;
void hashtable_free(HashTable); typedef Pixel HashKey_t;
void hashtable_foreach(HashTable,IteratorFunc,void *); typedef uint32_t HashVal_t;
void hashtable_foreach_update(HashTable,IteratorUpdateFunc,void *);
int hashtable_insert(HashTable,void *,void *);
int hashtable_update(HashTable,void *,void *);
int hashtable_lookup(const HashTable,const void *,void **);
int hashtable_lookup_or_insert(HashTable,void *,void **,void *);
int hashtable_insert_or_update_computed(HashTable,void *,ComputeFunc,ComputeFunc);
int hashtable_delete(HashTable,const void *);
int hashtable_remove(HashTable,const void *,void **,void **);
void *hashtable_set_user_data(HashTable,void *);
void *hashtable_get_user_data(const HashTable);
DestroyFunc hashtable_set_key_destroy_func(HashTable,DestroyFunc);
DestroyFunc hashtable_set_value_destroy_func(HashTable,DestroyFunc);
unsigned long hashtable_get_count(const HashTable);
void hashtable_rehash(HashTable);
void hashtable_rehash_compute(HashTable,CollisionFunc);
#endif typedef uint32_t (*HashFunc)(const HashTable *,const HashKey_t);
typedef int (*HashCmpFunc)(const HashTable *,const HashKey_t,const HashKey_t);
typedef void (*IteratorFunc)(const HashTable *,const HashKey_t,const HashVal_t,void *);
typedef void (*IteratorUpdateFunc)(const HashTable *,const HashKey_t,HashVal_t *,void *);
typedef void (*KeyDestroyFunc)(const HashTable *,HashKey_t);
typedef void (*ValDestroyFunc)(const HashTable *,HashVal_t);
typedef void (*ComputeFunc)(const HashTable *,const HashKey_t,HashVal_t *);
typedef void (*CollisionFunc)(const HashTable *,HashKey_t *,HashVal_t *,HashKey_t,HashVal_t);
HashTable * hashtable_new(HashFunc hf,HashCmpFunc cf);
void hashtable_free(HashTable *h);
void hashtable_foreach(HashTable *h,IteratorFunc i,void *u);
void hashtable_foreach_update(HashTable *h,IteratorUpdateFunc i,void *u);
int hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val);
int hashtable_update(HashTable *h,HashKey_t key,HashVal_t val);
int hashtable_lookup(const HashTable *h,const HashKey_t key,HashVal_t *valp);
int hashtable_lookup_or_insert(HashTable *h,HashKey_t key,HashVal_t *valp,HashVal_t val);
int hashtable_insert_or_update_computed(HashTable *h,HashKey_t key,ComputeFunc newFunc,ComputeFunc existsFunc);
int hashtable_delete(HashTable *h,const HashKey_t key);
int hashtable_remove(HashTable *h,const HashKey_t key,HashKey_t *keyRet,HashVal_t *valRet);
void *hashtable_set_user_data(HashTable *h,void *data);
void *hashtable_get_user_data(const HashTable *h);
KeyDestroyFunc hashtable_set_key_destroy_func(HashTable *,KeyDestroyFunc d);
ValDestroyFunc hashtable_set_value_destroy_func(HashTable *,ValDestroyFunc d);
uint32_t hashtable_get_count(const HashTable *h);
void hashtable_rehash(HashTable *h);
void hashtable_rehash_compute(HashTable *h,CollisionFunc cf);
#endif // __QUANTHASH_H__

View File

@ -21,31 +21,29 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "QuantHash.h" #include "QuantHeap.h"
#include "QuantDefines.h"
typedef struct { typedef struct _Heap {
void **heap; void **heap;
int heapsize; int heapsize;
int heapcount; int heapcount;
HeapCmpFunc cf; HeapCmpFunc cf;
} IntHeap; } Heap;
#define INITIAL_SIZE 256 #define INITIAL_SIZE 256
#define DEBUG // #define DEBUG
#ifdef DEBUG #ifdef DEBUG
static int _heap_test(Heap); static int _heap_test(Heap *);
#endif #endif
void ImagingQuantHeapFree(Heap H) { void ImagingQuantHeapFree(Heap *h) {
IntHeap *h=(IntHeap *)H;
free(h->heap); free(h->heap);
free(h); free(h);
} }
static int _heap_grow(IntHeap *h,int newsize) { static int _heap_grow(Heap *h,int newsize) {
void *newheap; void *newheap;
if (!newsize) newsize=h->heapsize<<1; if (!newsize) newsize=h->heapsize<<1;
if (newsize<h->heapsize) return 0; if (newsize<h->heapsize) return 0;
@ -59,15 +57,14 @@ static int _heap_grow(IntHeap *h,int newsize) {
} }
#ifdef DEBUG #ifdef DEBUG
static int _heap_test(Heap H) { static int _heap_test(Heap *h) {
IntHeap *h=(IntHeap *)H;
int k; int k;
for (k=1;k*2<=h->heapcount;k++) { for (k=1;k*2<=h->heapcount;k++) {
if (h->cf(H,h->heap[k],h->heap[k*2])<0) { if (h->cf(h,h->heap[k],h->heap[k*2])<0) {
printf ("heap is bad\n"); printf ("heap is bad\n");
return 0; return 0;
} }
if (k*2+1<=h->heapcount && h->cf(H,h->heap[k],h->heap[k*2+1])<0) { if (k*2+1<=h->heapcount && h->cf(h,h->heap[k],h->heap[k*2+1])<0) {
printf ("heap is bad\n"); printf ("heap is bad\n");
return 0; return 0;
} }
@ -76,8 +73,7 @@ static int _heap_test(Heap H) {
} }
#endif #endif
int ImagingQuantHeapRemove(Heap H,void **r) { int ImagingQuantHeapRemove(Heap* h,void **r) {
IntHeap *h=(IntHeap *)H;
int k,l; int k,l;
void *v; void *v;
@ -89,31 +85,30 @@ int ImagingQuantHeapRemove(Heap H,void **r) {
for (k=1;k*2<=h->heapcount;k=l) { for (k=1;k*2<=h->heapcount;k=l) {
l=k*2; l=k*2;
if (l<h->heapcount) { if (l<h->heapcount) {
if (h->cf(H,h->heap[l],h->heap[l+1])<0) { if (h->cf(h,h->heap[l],h->heap[l+1])<0) {
l++; l++;
} }
} }
if (h->cf(H,v,h->heap[l])>0) { if (h->cf(h,v,h->heap[l])>0) {
break; break;
} }
h->heap[k]=h->heap[l]; h->heap[k]=h->heap[l];
} }
h->heap[k]=v; h->heap[k]=v;
#ifdef DEBUG #ifdef DEBUG
if (!_heap_test(H)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); } if (!_heap_test(h)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); }
#endif #endif
return 1; return 1;
} }
int ImagingQuantHeapAdd(Heap H,void *val) { int ImagingQuantHeapAdd(Heap *h,void *val) {
IntHeap *h=(IntHeap *)H;
int k; int k;
if (h->heapcount==h->heapsize-1) { if (h->heapcount==h->heapsize-1) {
_heap_grow(h,0); _heap_grow(h,0);
} }
k=++h->heapcount; k=++h->heapcount;
while (k!=1) { while (k!=1) {
if (h->cf(H,val,h->heap[k/2])<=0) { if (h->cf(h,val,h->heap[k/2])<=0) {
break; break;
} }
h->heap[k]=h->heap[k/2]; h->heap[k]=h->heap[k/2];
@ -121,13 +116,12 @@ int ImagingQuantHeapAdd(Heap H,void *val) {
} }
h->heap[k]=val; h->heap[k]=val;
#ifdef DEBUG #ifdef DEBUG
if (!_heap_test(H)) { printf ("oops - heap_add messed up the heap\n"); exit(1); } if (!_heap_test(h)) { printf ("oops - heap_add messed up the heap\n"); exit(1); }
#endif #endif
return 1; return 1;
} }
int ImagingQuantHeapTop(Heap H,void **r) { int ImagingQuantHeapTop(Heap *h,void **r) {
IntHeap *h=(IntHeap *)H;
if (!h->heapcount) { if (!h->heapcount) {
return 0; return 0;
} }
@ -136,15 +130,14 @@ int ImagingQuantHeapTop(Heap H,void **r) {
} }
Heap *ImagingQuantHeapNew(HeapCmpFunc cf) { Heap *ImagingQuantHeapNew(HeapCmpFunc cf) {
IntHeap *h; Heap *h;
h=malloc(sizeof(IntHeap)); h=malloc(sizeof(Heap));
if (!h) return NULL; if (!h) return NULL;
h->heapsize=INITIAL_SIZE; h->heapsize=INITIAL_SIZE;
h->heap=malloc(sizeof(void *)*h->heapsize); h->heap=malloc(sizeof(void *)*h->heapsize);
if (!h->heap) { free(h); return NULL; } if (!h->heap) { free(h); return NULL; }
h->heapcount=0; h->heapcount=0;
h->cf=cf; h->cf=cf;
return (Heap)h; return h;
} }

View File

@ -9,15 +9,19 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#ifndef __HEAP_H__ #ifndef __QUANTHEAP_H__
#define __HEAP_H__ #define __QUANTHEAP_H__
#include "QuantTypes.h" #include "QuantTypes.h"
void ImagingQuantHeapFree(Heap); typedef struct _Heap Heap;
int ImagingQuantHeapRemove(Heap,void **);
int ImagingQuantHeapAdd(Heap,void *); typedef int (*HeapCmpFunc)(const Heap *,const void *,const void *);
int ImagingQuantHeapTop(Heap,void **);
void ImagingQuantHeapFree(Heap *);
int ImagingQuantHeapRemove(Heap *,void **);
int ImagingQuantHeapAdd(Heap *,void *);
int ImagingQuantHeapTop(Heap *,void **);
Heap *ImagingQuantHeapNew(HeapCmpFunc); Heap *ImagingQuantHeapNew(HeapCmpFunc);
#endif #endif // __QUANTHEAP_H__

View File

@ -27,15 +27,15 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "Quant.h" #include "QuantOctree.h"
typedef struct _ColorBucket{ typedef struct _ColorBucket{
/* contains palette index when used for look up cube */ /* contains palette index when used for look up cube */
unsigned long count; uint32_t count;
unsigned long r; uint32_t r;
unsigned long g; uint32_t g;
unsigned long b; uint32_t b;
unsigned long a; uint32_t a;
} *ColorBucket; } *ColorBucket;
typedef struct _ColorCube{ typedef struct _ColorCube{
@ -262,7 +262,7 @@ set_lookup_value(const ColorCube cube, const Pixel *p, long value) {
bucket->count = value; bucket->count = value;
} }
unsigned long uint32_t
lookup_color(const ColorCube cube, const Pixel *p) { lookup_color(const ColorCube cube, const Pixel *p) {
ColorBucket bucket = color_bucket_from_cube(cube, p); ColorBucket bucket = color_bucket_from_cube(cube, p);
return bucket->count; return bucket->count;
@ -302,9 +302,9 @@ create_palette_array(const ColorBucket palette, unsigned int paletteLength) {
static void static void
map_image_pixels(const Pixel *pixelData, map_image_pixels(const Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
const ColorCube lookupCube, const ColorCube lookupCube,
unsigned long *pixelArray) uint32_t *pixelArray)
{ {
long i; long i;
for (i=0; i<nPixels; i++) { for (i=0; i<nPixels; i++) {
@ -316,11 +316,11 @@ const int CUBE_LEVELS[8] = {4, 4, 4, 0, 2, 2, 2, 0};
const int CUBE_LEVELS_ALPHA[8] = {3, 4, 3, 3, 2, 2, 2, 2}; const int CUBE_LEVELS_ALPHA[8] = {3, 4, 3, 3, 2, 2, 2, 2};
int quantize_octree(Pixel *pixelData, int quantize_octree(Pixel *pixelData,
unsigned long nPixels, uint32_t nPixels,
unsigned long nQuantPixels, uint32_t nQuantPixels,
Pixel **palette, Pixel **palette,
unsigned long *paletteLength, uint32_t *paletteLength,
unsigned long **quantizedPixels, uint32_t **quantizedPixels,
int withAlpha) int withAlpha)
{ {
ColorCube fineCube = NULL; ColorCube fineCube = NULL;
@ -330,7 +330,7 @@ int quantize_octree(Pixel *pixelData,
ColorBucket paletteBucketsCoarse = NULL; ColorBucket paletteBucketsCoarse = NULL;
ColorBucket paletteBucketsFine = NULL; ColorBucket paletteBucketsFine = NULL;
ColorBucket paletteBuckets = NULL; ColorBucket paletteBuckets = NULL;
unsigned long *qp = NULL; uint32_t *qp = NULL;
long i; long i;
long nCoarseColors, nFineColors, nAlreadySubtracted; long nCoarseColors, nFineColors, nAlreadySubtracted;
const int *cubeBits; const int *cubeBits;

View File

@ -1,12 +1,14 @@
#ifndef __QUANT_OCTREE_H__ #ifndef __QUANT_OCTREE_H__
#define __QUANT_OCTREE_H__ #define __QUANT_OCTREE_H__
#include "QuantTypes.h"
int quantize_octree(Pixel *, int quantize_octree(Pixel *,
unsigned long, uint32_t,
unsigned long, uint32_t,
Pixel **, Pixel **,
unsigned long *, uint32_t *,
unsigned long **, uint32_t **,
int); int);
#endif #endif

View File

@ -12,17 +12,20 @@
#ifndef __TYPES_H__ #ifndef __TYPES_H__
#define __TYPES_H__ #define __TYPES_H__
typedef void *HashTable; #ifdef _MSC_VER
typedef void *Heap; typedef unsigned __int32 uint32_t;
#else
#include <stdint.h>
#endif
typedef unsigned long (*HashFunc)(const HashTable,const void *); typedef union {
typedef int (*HashCmpFunc)(const HashTable,const void *,const void *); struct {
typedef void (*IteratorFunc)(const HashTable,const void *,const void *,void *); unsigned char r,g,b,a;
typedef void (*IteratorUpdateFunc)(const HashTable,const void *,void **,void *); } c;
typedef void (*DestroyFunc)(const HashTable,void *); struct {
typedef void (*ComputeFunc)(const HashTable,const void *,void **); unsigned char v[4];
typedef void (*CollisionFunc)(const HashTable,void **,void **,void *,void *); } a;
uint32_t v;
typedef int (*HeapCmpFunc)(const Heap,const void *,const void *); } Pixel;
#endif #endif