123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- /*
- * 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 <limits.h>
- #include "QuantHeap.h"
- struct _Heap {
- void **heap;
- unsigned int heapsize;
- unsigned int heapcount;
- HeapCmpFunc cf;
- };
- #define INITIAL_SIZE 256
- // #define DEBUG
- #ifdef DEBUG
- static int
- _heap_test(Heap *);
- #endif
- void
- ImagingQuantHeapFree(Heap *h) {
- free(h->heap);
- free(h);
- }
- static int
- _heap_grow(Heap *h, unsigned int newsize) {
- void *newheap;
- if (!newsize) {
- newsize = h->heapsize << 1;
- }
- if (newsize < h->heapsize) {
- return 0;
- }
- if (newsize > INT_MAX / sizeof(void *)) {
- return 0;
- }
- /* malloc check ok, using calloc for overflow, also checking
- above due to memcpy below*/
- newheap = calloc(newsize, sizeof(void *));
- 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) {
- unsigned 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) {
- unsigned 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) {
- 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) {
- if (!h->heapcount) {
- return 0;
- }
- *r = h->heap[1];
- return 1;
- }
- Heap *
- ImagingQuantHeapNew(HeapCmpFunc cf) {
- Heap *h;
- /* malloc check ok, small constant allocation */
- h = malloc(sizeof(Heap));
- if (!h) {
- return NULL;
- }
- h->heapsize = INITIAL_SIZE;
- /* malloc check ok, using calloc for overflow */
- h->heap = calloc(h->heapsize, sizeof(void *));
- if (!h->heap) {
- free(h);
- return NULL;
- }
- h->heapcount = 0;
- h->cf = cf;
- return h;
- }
|