mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	Merge pull request #179 from manisandro/quantization
Make quantization code more portable
This commit is contained in:
		
						commit
						21562761ac
					
				| 
						 | 
					@ -1369,7 +1369,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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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__
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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__
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user