Panda3D
Loading...
Searching...
No Matches
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
26ppm_computecolorhist(pixel** pixels,
27 int cols, int rows, int maxcolors,
28 int* colorsP)
29 {
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
41void
42ppm_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
81ppm_computecolorhash(pixel** pixels,
82 int cols, int rows, int maxcolors,
83 int* colorsP)
84 {
86 pixel* pP;
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
124ppm_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
139int
140ppm_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
159ppm_colorhashtocolorhist(colorhash_table cht,
160 int maxcolors)
161 {
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
187ppm_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
218int
219ppm_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
233void
234ppm_freecolorhist(colorhist_vector chv)
235 {
236 free( (char*) chv );
237 }
238
239void
240ppm_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.