mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			151 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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;
 | 
						|
}
 | 
						|
 |