2010-07-31 06:52:47 +04:00
|
|
|
/*
|
|
|
|
* 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>
|
2016-05-21 17:31:19 +03:00
|
|
|
#include <limits.h>
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2013-04-08 02:52:15 +04:00
|
|
|
#include "QuantHeap.h"
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2013-04-17 16:27:07 +04:00
|
|
|
struct _Heap {
|
2010-07-31 06:52:47 +04:00
|
|
|
void **heap;
|
|
|
|
int heapsize;
|
|
|
|
int heapcount;
|
|
|
|
HeapCmpFunc cf;
|
2013-04-17 16:27:07 +04:00
|
|
|
};
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
#define INITIAL_SIZE 256
|
|
|
|
|
2013-04-08 02:52:15 +04:00
|
|
|
// #define DEBUG
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2013-04-08 02:52:15 +04:00
|
|
|
static int _heap_test(Heap *);
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
|
2013-04-08 02:52:15 +04:00
|
|
|
void ImagingQuantHeapFree(Heap *h) {
|
2010-07-31 06:52:47 +04:00
|
|
|
free(h->heap);
|
|
|
|
free(h);
|
|
|
|
}
|
|
|
|
|
2013-04-08 02:52:15 +04:00
|
|
|
static int _heap_grow(Heap *h,int newsize) {
|
2010-07-31 06:52:47 +04:00
|
|
|
void *newheap;
|
|
|
|
if (!newsize) newsize=h->heapsize<<1;
|
|
|
|
if (newsize<h->heapsize) return 0;
|
2016-05-21 17:31:19 +03:00
|
|
|
if (newsize > INT_MAX / sizeof(void *)){
|
2016-03-16 14:47:18 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2016-07-01 14:27:01 +03:00
|
|
|
/* malloc check ok, using calloc for overflow, also checking
|
2016-03-16 14:47:18 +03:00
|
|
|
above due to memcpy below*/
|
|
|
|
newheap=calloc(newsize, sizeof(void *));
|
2010-07-31 06:52:47 +04:00
|
|
|
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
|
2013-04-08 02:52:15 +04:00
|
|
|
static int _heap_test(Heap *h) {
|
2010-07-31 06:52:47 +04:00
|
|
|
int k;
|
|
|
|
for (k=1;k*2<=h->heapcount;k++) {
|
2013-04-08 02:52:15 +04:00
|
|
|
if (h->cf(h,h->heap[k],h->heap[k*2])<0) {
|
2010-07-31 06:52:47 +04:00
|
|
|
printf ("heap is bad\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2013-04-08 02:52:15 +04:00
|
|
|
if (k*2+1<=h->heapcount && h->cf(h,h->heap[k],h->heap[k*2+1])<0) {
|
2010-07-31 06:52:47 +04:00
|
|
|
printf ("heap is bad\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-04-08 02:52:15 +04:00
|
|
|
int ImagingQuantHeapRemove(Heap* h,void **r) {
|
2010-07-31 06:52:47 +04:00
|
|
|
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) {
|
2013-04-08 02:52:15 +04:00
|
|
|
if (h->cf(h,h->heap[l],h->heap[l+1])<0) {
|
2010-07-31 06:52:47 +04:00
|
|
|
l++;
|
|
|
|
}
|
|
|
|
}
|
2013-04-08 02:52:15 +04:00
|
|
|
if (h->cf(h,v,h->heap[l])>0) {
|
2010-07-31 06:52:47 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
h->heap[k]=h->heap[l];
|
|
|
|
}
|
|
|
|
h->heap[k]=v;
|
|
|
|
#ifdef DEBUG
|
2013-04-08 02:52:15 +04:00
|
|
|
if (!_heap_test(h)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); }
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-04-08 02:52:15 +04:00
|
|
|
int ImagingQuantHeapAdd(Heap *h,void *val) {
|
2010-07-31 06:52:47 +04:00
|
|
|
int k;
|
|
|
|
if (h->heapcount==h->heapsize-1) {
|
|
|
|
_heap_grow(h,0);
|
|
|
|
}
|
|
|
|
k=++h->heapcount;
|
|
|
|
while (k!=1) {
|
2013-04-08 02:52:15 +04:00
|
|
|
if (h->cf(h,val,h->heap[k/2])<=0) {
|
2010-07-31 06:52:47 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
h->heap[k]=h->heap[k/2];
|
|
|
|
k>>=1;
|
|
|
|
}
|
|
|
|
h->heap[k]=val;
|
|
|
|
#ifdef DEBUG
|
2013-04-08 02:52:15 +04:00
|
|
|
if (!_heap_test(h)) { printf ("oops - heap_add messed up the heap\n"); exit(1); }
|
2010-07-31 06:52:47 +04:00
|
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-04-08 02:52:15 +04:00
|
|
|
int ImagingQuantHeapTop(Heap *h,void **r) {
|
2010-07-31 06:52:47 +04:00
|
|
|
if (!h->heapcount) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*r=h->heap[1];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Heap *ImagingQuantHeapNew(HeapCmpFunc cf) {
|
2013-04-08 02:52:15 +04:00
|
|
|
Heap *h;
|
2016-09-03 05:23:42 +03:00
|
|
|
|
2016-03-16 14:47:18 +03:00
|
|
|
/* malloc check ok, small constant allocation */
|
2013-04-08 02:52:15 +04:00
|
|
|
h=malloc(sizeof(Heap));
|
2010-07-31 06:52:47 +04:00
|
|
|
if (!h) return NULL;
|
|
|
|
h->heapsize=INITIAL_SIZE;
|
2016-03-16 14:47:18 +03:00
|
|
|
/* malloc check ok, using calloc for overflow */
|
|
|
|
h->heap=calloc(h->heapsize, sizeof(void *));
|
2016-07-01 14:27:01 +03:00
|
|
|
if (!h->heap) {
|
|
|
|
free(h);
|
|
|
|
return NULL;
|
2016-03-16 14:47:18 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
h->heapcount=0;
|
|
|
|
h->cf=cf;
|
2013-04-08 02:52:15 +04:00
|
|
|
return h;
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|