1 /* See LICENSE file for licensing information.
2 */
3
4 #include "pm_c_util.h"
5 #include "mallocvar.h"
6 #include "pnm.h"
7 #include "palm.h"
8
9 #include "palmcolormap.h"
10
11
12
13 static pixval
scaleSample(pixval const arg,pixval const oldMaxval,pixval const newMaxval)14 scaleSample(pixval const arg,
15 pixval const oldMaxval,
16 pixval const newMaxval) {
17
18 return (arg * newMaxval + oldMaxval/2) / oldMaxval;
19 }
20
21
22
23 ColormapEntry
palmcolor_mapEntryColorFmPixel(pixel const color,pixval const maxval,pixval const newMaxval)24 palmcolor_mapEntryColorFmPixel(pixel const color,
25 pixval const maxval,
26 pixval const newMaxval) {
27
28
29 return
30 0
31 | (scaleSample(PPM_GETR(color), maxval, newMaxval) << 16)
32 | (scaleSample(PPM_GETG(color), maxval, newMaxval) << 8)
33 | (scaleSample(PPM_GETB(color), maxval, newMaxval) << 0);
34 }
35
36
37
38 int
palmcolor_compare_indices(const void * const p1,const void * const p2)39 palmcolor_compare_indices(const void * const p1,
40 const void * const p2) {
41 /*----------------------------------------------------------------------------
42 This is a 'qsort' collation function.
43 -----------------------------------------------------------------------------*/
44 if ((*((ColormapEntry *) p1) & 0xFF000000) < (*((ColormapEntry *) p2) & 0xFF000000))
45 return -1;
46 else if ((*((ColormapEntry *) p1) & 0xFF000000) > (*((ColormapEntry *) p2) & 0xFF000000))
47 return 1;
48 else
49 return 0;
50 }
51
52
53
54 int
palmcolor_compare_colors(const void * const p1,const void * const p2)55 palmcolor_compare_colors(const void * const p1,
56 const void * const p2) {
57 /*----------------------------------------------------------------------------
58 This is a 'qsort' collation function.
59 -----------------------------------------------------------------------------*/
60 unsigned long const val1 = *((const unsigned long *) p1) & 0xFFFFFF;
61 unsigned long const val2 = *((const unsigned long *) p2) & 0xFFFFFF;
62
63 if (val1 < val2)
64 return -1;
65 else if (val1 > val2)
66 return 1;
67 else
68 return 0;
69 }
70
71 /***********************************************************************
72 ***********************************************************************
73 ***********************************************************************
74 ******* colortables from pilrc-2.6/bitmap.c ***************************
75 ***********************************************************************
76 ***********************************************************************
77 ***********************************************************************/
78
79 #if 0
80
81 /*
82 * The 1bit-2 color system palette for Palm Computing Devices.
83 */
84 static int PalmPalette1bpp[2][3] =
85 {
86 { 255, 255, 255}, { 0, 0, 0 }
87 };
88
89 /*
90 * The 2bit-4 color system palette for Palm Computing Devices.
91 */
92 static int PalmPalette2bpp[4][3] =
93 {
94 { 255, 255, 255}, { 192, 192, 192}, { 128, 128, 128 }, { 0, 0, 0 }
95 };
96
97 /*
98 * The 4bit-16 color system palette for Palm Computing Devices.
99 */
100 static int PalmPalette4bpp[16][3] =
101 {
102 { 255, 255, 255}, { 238, 238, 238 }, { 221, 221, 221 }, { 204, 204, 204 },
103 { 187, 187, 187}, { 170, 170, 170 }, { 153, 153, 153 }, { 136, 136, 136 },
104 { 119, 119, 119}, { 102, 102, 102 }, { 85, 85, 85 }, { 68, 68, 68 },
105 { 51, 51, 51}, { 34, 34, 34 }, { 17, 17, 17 }, { 0, 0, 0 }
106 };
107
108 /*
109 * The 4bit-16 color system palette for Palm Computing Devices.
110 */
111 static int PalmPalette4bppColor[16][3] =
112 {
113 { 255, 255, 255}, { 128, 128, 128 }, { 128, 0, 0 }, { 128, 128, 0 },
114 { 0, 128, 0}, { 0, 128, 128 }, { 0, 0, 128 }, { 128, 0, 128 },
115 { 255, 0, 255}, { 192, 192, 192 }, { 255, 0, 0 }, { 255, 255, 0 },
116 { 0, 255, 0}, { 0, 255, 255 }, { 0, 0, 255 }, { 0, 0, 0 }
117 };
118
119 #endif /* 0 */
120
121 /*
122 * The 8bit-256 color system palette for Palm Computing Devices.
123 *
124 * NOTE: only the first 231, plus the last one, are valid.
125 */
126 static int PalmPalette8bpp[256][3] =
127 {
128 { 255, 255, 255 }, { 255, 204, 255 }, { 255, 153, 255 }, { 255, 102, 255 },
129 { 255, 51, 255 }, { 255, 0, 255 }, { 255, 255, 204 }, { 255, 204, 204 },
130 { 255, 153, 204 }, { 255, 102, 204 }, { 255, 51, 204 }, { 255, 0, 204 },
131 { 255, 255, 153 }, { 255, 204, 153 }, { 255, 153, 153 }, { 255, 102, 153 },
132 { 255, 51, 153 }, { 255, 0, 153 }, { 204, 255, 255 }, { 204, 204, 255 },
133 { 204, 153, 255 }, { 204, 102, 255 }, { 204, 51, 255 }, { 204, 0, 255 },
134 { 204, 255, 204 }, { 204, 204, 204 }, { 204, 153, 204 }, { 204, 102, 204 },
135 { 204, 51, 204 }, { 204, 0, 204 }, { 204, 255, 153 }, { 204, 204, 153 },
136 { 204, 153, 153 }, { 204, 102, 153 }, { 204, 51, 153 }, { 204, 0, 153 },
137 { 153, 255, 255 }, { 153, 204, 255 }, { 153, 153, 255 }, { 153, 102, 255 },
138 { 153, 51, 255 }, { 153, 0, 255 }, { 153, 255, 204 }, { 153, 204, 204 },
139 { 153, 153, 204 }, { 153, 102, 204 }, { 153, 51, 204 }, { 153, 0, 204 },
140 { 153, 255, 153 }, { 153, 204, 153 }, { 153, 153, 153 }, { 153, 102, 153 },
141 { 153, 51, 153 }, { 153, 0, 153 }, { 102, 255, 255 }, { 102, 204, 255 },
142 { 102, 153, 255 }, { 102, 102, 255 }, { 102, 51, 255 }, { 102, 0, 255 },
143 { 102, 255, 204 }, { 102, 204, 204 }, { 102, 153, 204 }, { 102, 102, 204 },
144 { 102, 51, 204 }, { 102, 0, 204 }, { 102, 255, 153 }, { 102, 204, 153 },
145 { 102, 153, 153 }, { 102, 102, 153 }, { 102, 51, 153 }, { 102, 0, 153 },
146 { 51, 255, 255 }, { 51, 204, 255 }, { 51, 153, 255 }, { 51, 102, 255 },
147 { 51, 51, 255 }, { 51, 0, 255 }, { 51, 255, 204 }, { 51, 204, 204 },
148 { 51, 153, 204 }, { 51, 102, 204 }, { 51, 51, 204 }, { 51, 0, 204 },
149 { 51, 255, 153 }, { 51, 204, 153 }, { 51, 153, 153 }, { 51, 102, 153 },
150 { 51, 51, 153 }, { 51, 0, 153 }, { 0, 255, 255 }, { 0, 204, 255 },
151 { 0, 153, 255 }, { 0, 102, 255 }, { 0, 51, 255 }, { 0, 0, 255 },
152 { 0, 255, 204 }, { 0, 204, 204 }, { 0, 153, 204 }, { 0, 102, 204 },
153 { 0, 51, 204 }, { 0, 0, 204 }, { 0, 255, 153 }, { 0, 204, 153 },
154 { 0, 153, 153 }, { 0, 102, 153 }, { 0, 51, 153 }, { 0, 0, 153 },
155 { 255, 255, 102 }, { 255, 204, 102 }, { 255, 153, 102 }, { 255, 102, 102 },
156 { 255, 51, 102 }, { 255, 0, 102 }, { 255, 255, 51 }, { 255, 204, 51 },
157 { 255, 153, 51 }, { 255, 102, 51 }, { 255, 51, 51 }, { 255, 0, 51 },
158 { 255, 255, 0 }, { 255, 204, 0 }, { 255, 153, 0 }, { 255, 102, 0 },
159 { 255, 51, 0 }, { 255, 0, 0 }, { 204, 255, 102 }, { 204, 204, 102 },
160 { 204, 153, 102 }, { 204, 102, 102 }, { 204, 51, 102 }, { 204, 0, 102 },
161 { 204, 255, 51 }, { 204, 204, 51 }, { 204, 153, 51 }, { 204, 102, 51 },
162 { 204, 51, 51 }, { 204, 0, 51 }, { 204, 255, 0 }, { 204, 204, 0 },
163 { 204, 153, 0 }, { 204, 102, 0 }, { 204, 51, 0 }, { 204, 0, 0 },
164 { 153, 255, 102 }, { 153, 204, 102 }, { 153, 153, 102 }, { 153, 102, 102 },
165 { 153, 51, 102 }, { 153, 0, 102 }, { 153, 255, 51 }, { 153, 204, 51 },
166 { 153, 153, 51 }, { 153, 102, 51 }, { 153, 51, 51 }, { 153, 0, 51 },
167 { 153, 255, 0 }, { 153, 204, 0 }, { 153, 153, 0 }, { 153, 102, 0 },
168 { 153, 51, 0 }, { 153, 0, 0 }, { 102, 255, 102 }, { 102, 204, 102 },
169 { 102, 153, 102 }, { 102, 102, 102 }, { 102, 51, 102 }, { 102, 0, 102 },
170 { 102, 255, 51 }, { 102, 204, 51 }, { 102, 153, 51 }, { 102, 102, 51 },
171 { 102, 51, 51 }, { 102, 0, 51 }, { 102, 255, 0 }, { 102, 204, 0 },
172 { 102, 153, 0 }, { 102, 102, 0 }, { 102, 51, 0 }, { 102, 0, 0 },
173 { 51, 255, 102 }, { 51, 204, 102 }, { 51, 153, 102 }, { 51, 102, 102 },
174 { 51, 51, 102 }, { 51, 0, 102 }, { 51, 255, 51 }, { 51, 204, 51 },
175 { 51, 153, 51 }, { 51, 102, 51 }, { 51, 51, 51 }, { 51, 0, 51 },
176 { 51, 255, 0 }, { 51, 204, 0 }, { 51, 153, 0 }, { 51, 102, 0 },
177 { 51, 51, 0 }, { 51, 0, 0 }, { 0, 255, 102 }, { 0, 204, 102 },
178 { 0, 153, 102 }, { 0, 102, 102 }, { 0, 51, 102 }, { 0, 0, 102 },
179 { 0, 255, 51 }, { 0, 204, 51 }, { 0, 153, 51 }, { 0, 102, 51 },
180 { 0, 51, 51 }, { 0, 0, 51 }, { 0, 255, 0 }, { 0, 204, 0 },
181 { 0, 153, 0 }, { 0, 102, 0 }, { 0, 51, 0 }, { 17, 17, 17 },
182 { 34, 34, 34 }, { 68, 68, 68 }, { 85, 85, 85 }, { 119, 119, 119 },
183 { 136, 136, 136 }, { 170, 170, 170 }, { 187, 187, 187 }, { 221, 221, 221 },
184 { 238, 238, 238 }, { 192, 192, 192 }, { 128, 0, 0 }, { 128, 0, 128 },
185 { 0, 128, 0 }, { 0, 128, 128 }, { 0, 0, 0 }, { 0, 0, 0 },
186 { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
187 { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
188 { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
189 { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
190 { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
191 { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }
192 };
193
194
195
196 Colormap *
palmcolor_build_default_8bit_colormap(void)197 palmcolor_build_default_8bit_colormap(void) {
198
199 unsigned int i;
200
201 Colormap * cmP;
202
203 MALLOCVAR_NOFAIL(cmP);
204 cmP->nentries = 232;
205 MALLOCARRAY_NOFAIL(cmP->color_entries, cmP->nentries);
206
207 /* Fill in the colors */
208 for (i = 0; i < 231; ++i) {
209 cmP->color_entries[i] = ((i << 24) |
210 (PalmPalette8bpp[i][0] << 16) |
211 (PalmPalette8bpp[i][1] << 8) |
212 (PalmPalette8bpp[i][2]));
213 }
214 cmP->color_entries[231] = 0xFF000000;
215 cmP->ncolors = 232;
216
217 /* now sort the table */
218 qsort(cmP->color_entries, cmP->ncolors, sizeof(ColormapEntry),
219 palmcolor_compare_colors);
220 return cmP;
221 }
222
223
224
225 Colormap *
palmcolor_build_custom_8bit_colormap(pixel ** const pixels,unsigned int const rows,unsigned int const cols,pixval const maxval)226 palmcolor_build_custom_8bit_colormap(pixel ** const pixels,
227 unsigned int const rows,
228 unsigned int const cols,
229 pixval const maxval) {
230
231 unsigned int row;
232 Colormap * colormapP;
233
234 MALLOCVAR_NOFAIL(colormapP);
235 colormapP->nentries = 256;
236 MALLOCARRAY_NOFAIL(colormapP->color_entries, colormapP->nentries);
237 colormapP->ncolors = 0; /* initial value */
238
239 for (row = 0; row < rows; ++row) {
240 unsigned int col;
241 for (col = 0; col < cols; ++col) {
242 ColormapEntry * foundEntryP;
243 ColormapEntry const searchTarget =
244 palmcolor_mapEntryColorFmPixel(pixels[row][col], maxval, 255);
245
246 foundEntryP =
247 bsearch(&searchTarget,
248 colormapP->color_entries, colormapP->ncolors,
249 sizeof(ColormapEntry), palmcolor_compare_colors);
250 if (!foundEntryP) {
251 if (colormapP->ncolors >= colormapP->nentries)
252 pm_error("Too many colors for custom colormap "
253 "(max %u). "
254 "Try using pnmquant to reduce the number "
255 "of colors.", colormapP->nentries);
256 else {
257 /* add the new color, and re-sort */
258 unsigned int const colorIndex = colormapP->ncolors++;
259 ColormapEntry const newEntry =
260 searchTarget | (colorIndex << 24);
261 colormapP->color_entries[colorIndex] = newEntry;
262 qsort(colormapP->color_entries, colormapP->ncolors,
263 sizeof(ColormapEntry), palmcolor_compare_colors);
264 }
265 }
266 }
267 }
268 return colormapP;
269 }
270
271
272
273 Colormap *
palmcolor_read_colormap(FILE * const ifP)274 palmcolor_read_colormap (FILE * const ifP) {
275
276 unsigned short ncolors;
277 Colormap * retval;
278 int rc;
279
280 rc = pm_readbigshort(ifP, (short *) &ncolors);
281 if (rc != 0)
282 retval = NULL;
283 else {
284 long colorentry;
285 Colormap * colormapP;
286 unsigned int i;
287 bool error;
288
289 MALLOCVAR_NOFAIL(colormapP);
290 colormapP->nentries = ncolors;
291 MALLOCARRAY_NOFAIL(colormapP->color_entries, colormapP->nentries);
292
293 for (i = 0, error = FALSE; i < ncolors && !error; ++i) {
294 int rc;
295 rc = pm_readbiglong(ifP, &colorentry);
296 if (rc != 0)
297 error = TRUE;
298 else
299 colormapP->color_entries[i] = (colorentry & 0xFFFFFFFF);
300 }
301 if (error) {
302 free (colormapP->color_entries);
303 free (colormapP);
304 retval = NULL;
305 } else {
306 colormapP->ncolors = ncolors;
307 retval = colormapP;
308 }
309 }
310 return retval;
311 }
312