Pillow/libImaging/QuantHeap.c
2010-07-30 22:52:47 -04:00

151 lines
3.0 KiB
C

/*
* 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 <tjs@longford.cs.monash.edu.au>.
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#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 (newsize<h->heapsize) 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 (l<h->heapcount) {
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;
}