/* * The Python Imaging Library * $Id$ * * heap data type used by the image quantizer * * history: * 98-09-10 tjs Contributed * 98-12-29 fl Added to PIL 1.0b1 * * Written by Toby J Sargeant . * * Copyright (c) 1998 by Toby J Sargeant * Copyright (c) 1998 by Secret Labs AB * * See the README file for information on usage and redistribution. */ #include #include #include #include #include "QuantHash.h" #include "QuantDefines.h" typedef struct { void **heap; int heapsize; int heapcount; HeapCmpFunc cf; } IntHeap; #define INITIAL_SIZE 256 #define DEBUG #ifdef DEBUG static int _heap_test(Heap); #endif void ImagingQuantHeapFree(Heap H) { IntHeap *h=(IntHeap *)H; free(h->heap); free(h); } static int _heap_grow(IntHeap *h,int newsize) { void *newheap; if (!newsize) newsize=h->heapsize<<1; if (newsizeheapsize) return 0; newheap=malloc(sizeof(void *)*newsize); if (!newheap) return 0; memcpy(newheap,h->heap,sizeof(void *)*h->heapsize); free(h->heap); h->heap=newheap; h->heapsize=newsize; return 1; } #ifdef DEBUG static int _heap_test(Heap H) { IntHeap *h=(IntHeap *)H; int k; for (k=1;k*2<=h->heapcount;k++) { if (h->cf(H,h->heap[k],h->heap[k*2])<0) { printf ("heap is bad\n"); return 0; } if (k*2+1<=h->heapcount && h->cf(H,h->heap[k],h->heap[k*2+1])<0) { printf ("heap is bad\n"); return 0; } } return 1; } #endif int ImagingQuantHeapRemove(Heap H,void **r) { IntHeap *h=(IntHeap *)H; int k,l; void *v; if (!h->heapcount) { return 0; } *r=h->heap[1]; v=h->heap[h->heapcount--]; for (k=1;k*2<=h->heapcount;k=l) { l=k*2; if (lheapcount) { if (h->cf(H,h->heap[l],h->heap[l+1])<0) { l++; } } if (h->cf(H,v,h->heap[l])>0) { break; } h->heap[k]=h->heap[l]; } h->heap[k]=v; #ifdef DEBUG if (!_heap_test(H)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); } #endif return 1; } int ImagingQuantHeapAdd(Heap H,void *val) { IntHeap *h=(IntHeap *)H; int k; if (h->heapcount==h->heapsize-1) { _heap_grow(h,0); } k=++h->heapcount; while (k!=1) { if (h->cf(H,val,h->heap[k/2])<=0) { break; } h->heap[k]=h->heap[k/2]; k>>=1; } h->heap[k]=val; #ifdef DEBUG if (!_heap_test(H)) { printf ("oops - heap_add messed up the heap\n"); exit(1); } #endif return 1; } int ImagingQuantHeapTop(Heap H,void **r) { IntHeap *h=(IntHeap *)H; if (!h->heapcount) { return 0; } *r=h->heap[1]; return 1; } Heap *ImagingQuantHeapNew(HeapCmpFunc cf) { IntHeap *h; h=malloc(sizeof(IntHeap)); if (!h) return NULL; h->heapsize=INITIAL_SIZE; h->heap=malloc(sizeof(void *)*h->heapsize); if (!h->heap) { free(h); return NULL; } h->heapcount=0; h->cf=cf; return (Heap)h; }