Panda3D
ppmcmap.cxx
1 /* libppm3.c - ppm utility library part 3
2 **
3 ** Colormap routines.
4 **
5 ** Copyright (C) 1989, 1991 by Jef Poskanzer.
6 **
7 ** Permission to use, copy, modify, and distribute this software and its
8 ** documentation for any purpose and without fee is hereby granted, provided
9 ** that the above copyright notice appear in all copies and that both that
10 ** copyright notice and this permission notice appear in supporting
11 ** documentation. This software is provided "as is" without express or
12 ** implied warranty.
13 */
14 
15 #include "ppmcmap.h"
16 
17 #define HASH_SIZE 20023
18 
19 #ifdef PPM_PACKCOLORS
20 #define ppm_hashpixel(p) ( ( (int) (p) & 0x7fffffff ) % HASH_SIZE )
21 #else /*PPM_PACKCOLORS*/
22 #define ppm_hashpixel(p) ( ( ( (long) PPM_GETR(p) * 33023 + (long) PPM_GETG(p) * 30013 + (long) PPM_GETB(p) * 27011 ) & 0x7fffffff ) % HASH_SIZE )
23 #endif /*PPM_PACKCOLORS*/
24 
26 ppm_computecolorhist(pixel** pixels,
27  int cols, int rows, int maxcolors,
28  int* colorsP)
29  {
30  colorhash_table cht;
31  colorhist_vector chv;
32 
33  cht = ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP );
34  if ( cht == nullptr )
35  return nullptr;
36  chv = ppm_colorhashtocolorhist( cht, maxcolors );
37  ppm_freecolorhash( cht );
38  return chv;
39  }
40 
41 void
42 ppm_addtocolorhist(colorhist_vector chv,
43  int* colorsP,
44  int maxcolors,
45  pixel* colorP,
46  int value, int position)
47  {
48  int i, j;
49 
50  /* Search colorhist for the color. */
51  for ( i = 0; i < *colorsP; ++i )
52  if ( PPM_EQUAL( chv[i].color, *colorP ) )
53  {
54  /* Found it - move to new slot. */
55  if ( position > i )
56  {
57  for ( j = i; j < position; ++j )
58  chv[j] = chv[j + 1];
59  }
60  else if ( position < i )
61  {
62  for ( j = i; j > position; --j )
63  chv[j] = chv[j - 1];
64  }
65  chv[position].color = *colorP;
66  chv[position].value = value;
67  return;
68  }
69  if ( *colorsP < maxcolors )
70  {
71  /* Didn't find it, but there's room to add it; so do so. */
72  for ( i = *colorsP; i > position; --i )
73  chv[i] = chv[i - 1];
74  chv[position].color = *colorP;
75  chv[position].value = value;
76  ++(*colorsP);
77  }
78  }
79 
81 ppm_computecolorhash(pixel** pixels,
82  int cols, int rows, int maxcolors,
83  int* colorsP)
84  {
85  colorhash_table cht;
86  pixel* pP;
87  colorhist_list chl;
88  int col, row, hash;
89 
90  cht = ppm_alloccolorhash( );
91  *colorsP = 0;
92 
93  /* Go through the entire image, building a hash table of colors. */
94  for ( row = 0; row < rows; ++row )
95  for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
96  {
97  hash = ppm_hashpixel( *pP );
98  for ( chl = cht[hash]; chl != nullptr; chl = chl->next )
99  if ( PPM_EQUAL( chl->ch.color, *pP ) )
100  break;
101  if ( chl != nullptr )
102  ++(chl->ch.value);
103  else
104  {
105  if ( ++(*colorsP) > maxcolors )
106  {
107  ppm_freecolorhash( cht );
108  return nullptr;
109  }
110  chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
111  if ( chl == nullptr )
112  pm_error( "out of memory computing hash table" );
113  chl->ch.color = *pP;
114  chl->ch.value = 1;
115  chl->next = cht[hash];
116  cht[hash] = chl;
117  }
118  }
119 
120  return cht;
121  }
122 
124 ppm_alloccolorhash( )
125  {
126  colorhash_table cht;
127  int i;
128 
129  cht = (colorhash_table) malloc( HASH_SIZE * sizeof(colorhist_list) );
130  if ( cht == nullptr )
131  pm_error( "out of memory allocating hash table" );
132 
133  for ( i = 0; i < HASH_SIZE; ++i )
134  cht[i] = nullptr;
135 
136  return cht;
137  }
138 
139 int
140 ppm_addtocolorhash(colorhash_table cht,
141  pixel* colorP,
142  int value)
143  {
144  int hash;
145  colorhist_list chl;
146 
147  chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
148  if ( chl == nullptr )
149  return -1;
150  hash = ppm_hashpixel( *colorP );
151  chl->ch.color = *colorP;
152  chl->ch.value = value;
153  chl->next = cht[hash];
154  cht[hash] = chl;
155  return 0;
156  }
157 
159 ppm_colorhashtocolorhist(colorhash_table cht,
160  int maxcolors)
161  {
162  colorhist_vector chv;
163  colorhist_list chl;
164  int i, j;
165 
166  /* Now collate the hash table into a simple colorhist array. */
167  chv = (colorhist_vector) malloc( maxcolors * sizeof(struct colorhist_item) );
168  /* (Leave room for expansion by caller.) */
169  if ( chv == nullptr )
170  pm_error( "out of memory generating histogram" );
171 
172  /* Loop through the hash table. */
173  j = 0;
174  for ( i = 0; i < HASH_SIZE; ++i )
175  for ( chl = cht[i]; chl != nullptr; chl = chl->next )
176  {
177  /* Add the new entry. */
178  chv[j] = chl->ch;
179  ++j;
180  }
181 
182  /* All done. */
183  return chv;
184  }
185 
187 ppm_colorhisttocolorhash(colorhist_vector chv,
188  int colors)
189  {
190  colorhash_table cht;
191  int i, hash;
192  pixel color;
193  colorhist_list chl;
194 
195  cht = ppm_alloccolorhash( );
196 
197  for ( i = 0; i < colors; ++i )
198  {
199  color = chv[i].color;
200  hash = ppm_hashpixel( color );
201  for ( chl = cht[hash]; chl != nullptr; chl = chl->next )
202  if ( PPM_EQUAL( chl->ch.color, color ) )
203  pm_error(
204  "same color found twice - %d %d %d", PPM_GETR(color),
205  PPM_GETG(color), PPM_GETB(color) );
206  chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) );
207  if ( chl == nullptr )
208  pm_error( "out of memory" );
209  chl->ch.color = color;
210  chl->ch.value = i;
211  chl->next = cht[hash];
212  cht[hash] = chl;
213  }
214 
215  return cht;
216  }
217 
218 int
219 ppm_lookupcolor(colorhash_table cht,
220  pixel* colorP)
221  {
222  int hash;
223  colorhist_list chl;
224 
225  hash = ppm_hashpixel( *colorP );
226  for ( chl = cht[hash]; chl != nullptr; chl = chl->next )
227  if ( PPM_EQUAL( chl->ch.color, *colorP ) )
228  return chl->ch.value;
229 
230  return -1;
231  }
232 
233 void
234 ppm_freecolorhist(colorhist_vector chv)
235  {
236  free( (char*) chv );
237  }
238 
239 void
240 ppm_freecolorhash(colorhash_table cht)
241  {
242  int i;
243  colorhist_list chl, chlnext;
244 
245  for ( i = 0; i < HASH_SIZE; ++i )
246  for ( chl = cht[i]; chl != nullptr; chl = chlnext )
247  {
248  chlnext = chl->next;
249  free( (char*) chl );
250  }
251  free( (char*) cht );
252  }
void pm_error(const char *format,...)
Outputs the given printf-style message to the user and terminates messily.