1 #include "img_conv.h"
2
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7
8
9 #define var (( PImage) self)
10
11 /* Color mappers */
12 #define BCPARMS self, dstData, dstPal, dstType, dstPalSize, palSize_only
13 #define BCSELFGRAY self, var->data, dstPal, imByte, dstPalSize, palSize_only
14
15 static void
ic_Byte_convert(Handle self,Byte * dstData,PRGBColor dstPal,int dstType,int * dstPalSize,Bool palSize_only,Bool inplace)16 ic_Byte_convert( Handle self, Byte * dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only, Bool inplace)
17 {
18 int new_data_size = LINE_SIZE(var->w, 8) * var->h;
19 Byte * new_data;
20 RGBColor dummy_pal[256];
21 int dummy_pal_size = 0;
22
23 if ( !inplace) {
24 new_data = allocb( new_data_size);
25 if ( !new_data) {
26 croak("Not enough memory:%d bytes", new_data_size);
27 return;
28 }
29 memset( new_data, 0, new_data_size);
30 } else
31 new_data = var-> data;
32 ic_type_convert( self, new_data, dummy_pal, imByte, &dummy_pal_size, false);
33 if ( !inplace) {
34 free( var-> data);
35 var-> data = new_data;
36 }
37 var-> type = imByte;
38 var-> dataSize = new_data_size;
39 var-> lineSize = new_data_size / var-> h;
40 memcpy( var-> palette, std256gray_palette, sizeof(std256gray_palette));
41 var-> palSize = 256;
42 ic_type_convert( self, dstData, dstPal, dstType, dstPalSize, palSize_only);
43 }
44
45 static void
ic_raize_palette(Handle self,Byte * dstData,PRGBColor dstPal,int dstType,int * dstPalSize,Bool palSize_only)46 ic_raize_palette( Handle self, Byte * dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only)
47 {
48 Byte * odata = var-> data;
49 int otype = var-> type, dummy_pal_size = 0, oconv = var->conversion;
50 var->conversion = ictNone;
51 ic_type_convert( self, dstData, var-> palette, dstType, &dummy_pal_size, false);
52 var-> palSize = dummy_pal_size;
53 var-> type = dstType;
54 var-> data = dstData;
55 ic_type_convert( self, dstData, dstPal, dstType, dstPalSize, palSize_only);
56 var-> data = odata;
57 var-> type = otype;
58 var-> conversion = oconv;
59 }
60
61 void
ic_type_convert(Handle self,Byte * dstData,PRGBColor dstPal,int dstType,int * dstPalSize,Bool palSize_only)62 ic_type_convert( Handle self, Byte * dstData, PRGBColor dstPal, int dstType, int * dstPalSize, Bool palSize_only)
63 {
64 int srcType = var->type;
65 int orgDstType = dstType;
66
67 /* remove redundant combinations */
68 switch( srcType)
69 {
70 case imBW:
71 case im16 + imGrayScale:
72 case imRGB + imGrayScale:
73 srcType &=~ imGrayScale;
74 break;
75 }
76
77 switch( dstType)
78 {
79 case imBW:
80 case im16 + imGrayScale:
81 case imRGB + imGrayScale:
82 dstType &=~ imGrayScale;
83 break;
84 }
85
86 /* fill grayscale palette, if any */
87 if ( orgDstType & imGrayScale) {
88 /* XXX check ictpUnoptimized on dst grayscales */
89 switch( orgDstType & imBPP) {
90 case imbpp1:
91 memcpy( dstPal, stdmono_palette, sizeof( stdmono_palette));
92 *dstPalSize = 2;
93 break;
94 case imbpp4:
95 memcpy( dstPal, std16gray_palette, sizeof( std16gray_palette));
96 *dstPalSize = 16;
97 break;
98 case imbpp8:
99 memcpy( dstPal, std256gray_palette, sizeof( std256gray_palette));
100 *dstPalSize = 256;
101 break;
102 }
103 } else if (
104 (( var->conversion & ictpMask ) == ictpCubic) &&
105 (( orgDstType & imBPP) <= (srcType & imBPP)) &&
106 (*dstPalSize == 0 || palSize_only)
107 ) {
108 palSize_only = false;
109 switch( orgDstType & imBPP) {
110 case imbpp1:
111 memcpy( dstPal, stdmono_palette, sizeof( stdmono_palette));
112 *dstPalSize = 2;
113 break;
114 case imbpp4:
115 memcpy( dstPal, cubic_palette16, sizeof( cubic_palette16));
116 *dstPalSize = 16;
117 break;
118 case imbpp8:
119 memcpy( dstPal, cubic_palette, sizeof( cubic_palette));
120 *dstPalSize = 216;
121 break;
122 }
123 }
124
125 /* no palette conversion, same type, - out */
126 if (
127 srcType == dstType && (
128 *dstPalSize == 0 || (
129 (srcType != imbpp1) &&
130 (srcType != imbpp4) &&
131 (srcType != imbpp8)
132 )
133 )
134 ) {
135 memcpy( dstData, var->data, var->dataSize);
136 if (( orgDstType & imGrayScale) == 0) {
137 memcpy( dstPal, var->palette, var->palSize * 3);
138 *dstPalSize = var-> palSize;
139 }
140 return;
141 }
142
143 #define CASE_CONVERSION(src,dst,ictc) \
144 case ict##ictc: \
145 ic_##src##_##dst##_ict##ictc(BCPARMS); \
146 break
147 #define CASE_COLOR_BYTE_CONVERT \
148 case imMono:\
149 case im16:\
150 case im256:\
151 case imRGB:\
152 ic_Byte_convert( BCPARMS, true);\
153 break
154 #define CASE_NUMERIC_BYTE_CONVERT \
155 case imShort: \
156 case imLong: \
157 case imFloat: \
158 case imDouble: \
159 case imComplex: \
160 case imDComplex: \
161 ic_Byte_convert( BCPARMS, false); \
162 break;
163
164 switch( srcType)
165 {
166 case imMono: switch( dstType)
167 {
168 case imMono:
169 switch ( var->conversion)
170 {
171 case ictPosterization:
172 if ( palSize_only || *dstPalSize == 0) {
173 if ( dstData != var->data) memcpy( dstData, var->data, var->dataSize);
174 if ( dstPal != var->palette) memcpy( dstPal, var->palette, var->palSize * 3);
175 *dstPalSize = var-> palSize;
176 return;
177 }
178 case ictNone:
179 case ictOrdered:
180 case ictErrorDiffusion:
181 ic_mono_mono_ictNone(BCPARMS);
182 break;
183 CASE_CONVERSION(mono,mono,Optimized);
184 }
185 break;
186 case im16:
187 if ( *dstPalSize > 0)
188 ic_raize_palette(BCPARMS);
189 else
190 ic_mono_nibble_ictNone(BCPARMS);
191 break;
192 case im256:
193 if ( *dstPalSize > 0)
194 ic_raize_palette(BCPARMS);
195 else
196 ic_mono_byte_ictNone(BCPARMS);
197 break;
198 case imByte:
199 ic_mono_graybyte_ictNone(BCPARMS);
200 break;
201 case imRGB:
202 ic_mono_rgb_ictNone(BCPARMS);
203 break;
204 CASE_NUMERIC_BYTE_CONVERT;
205 }
206 break; /* imMono */
207
208 case im16: switch( dstType)
209 {
210 case imMono:
211 switch ( var->conversion)
212 {
213 case ictPosterization:
214 ic_nibble_mono_ictNone(BCPARMS);
215 break;
216 CASE_CONVERSION(nibble, mono, None);
217 CASE_CONVERSION(nibble, mono, Optimized);
218 CASE_CONVERSION(nibble, mono, Ordered);
219 CASE_CONVERSION(nibble, mono, ErrorDiffusion);
220 }
221 break;
222 case im16:
223 switch ( var->conversion)
224 {
225 CASE_CONVERSION(nibble, nibble, None);
226 CASE_CONVERSION(nibble, nibble, Posterization);
227 CASE_CONVERSION(nibble, nibble, Optimized);
228 CASE_CONVERSION(nibble, nibble, Ordered);
229 CASE_CONVERSION(nibble, nibble, ErrorDiffusion);
230 }
231 break;
232 case im256:
233 if ( *dstPalSize > 0)
234 ic_raize_palette(BCPARMS);
235 else
236 ic_nibble_byte_ictNone(BCPARMS);
237 break;
238 case imByte:
239 ic_nibble_graybyte_ictNone(BCPARMS);
240 break;
241 case imRGB:
242 ic_nibble_rgb_ictNone(BCPARMS);
243 break;
244 CASE_NUMERIC_BYTE_CONVERT;
245 }
246 break; /* im16 */
247
248 case im256: switch( dstType)
249 {
250 case imMono:
251 switch ( var->conversion)
252 {
253 case ictPosterization:
254 ic_byte_mono_ictNone(BCPARMS);
255 break;
256 CASE_CONVERSION(byte, mono, None);
257 CASE_CONVERSION(byte, mono, Optimized);
258 CASE_CONVERSION(byte, mono, Ordered);
259 CASE_CONVERSION(byte, mono, ErrorDiffusion);
260 }
261 break;
262 case im16:
263 switch ( var->conversion)
264 {
265 CASE_CONVERSION(byte, nibble, None);
266 CASE_CONVERSION(byte, nibble, Posterization);
267 CASE_CONVERSION(byte, nibble, Optimized);
268 CASE_CONVERSION(byte, nibble, Ordered);
269 CASE_CONVERSION(byte, nibble, ErrorDiffusion);
270 }
271 break;
272 case im256:
273 switch ( var->conversion)
274 {
275 CASE_CONVERSION(byte, byte, None);
276 CASE_CONVERSION(byte, byte, Posterization);
277 CASE_CONVERSION(byte, byte, Optimized);
278 CASE_CONVERSION(byte, byte, Ordered);
279 CASE_CONVERSION(byte, byte, ErrorDiffusion);
280 }
281 break;
282 case imByte:
283 ic_byte_graybyte_ictNone(BCPARMS);
284 break;
285 case imRGB:
286 ic_byte_rgb_ictNone(BCPARMS);
287 break;
288 CASE_NUMERIC_BYTE_CONVERT;
289 }
290 break; /* im256 */
291
292 case imByte: switch( dstType)
293 {
294 case imMono:
295 switch ( var->conversion)
296 {
297 case ictPosterization:
298 ic_byte_mono_ictNone(BCPARMS);
299 break;
300 CASE_CONVERSION(byte, mono, None);
301 CASE_CONVERSION(byte, mono, Optimized);
302 CASE_CONVERSION(graybyte, mono, Ordered);
303 CASE_CONVERSION(graybyte, mono, ErrorDiffusion);
304 }
305 break;
306 case im16:
307 switch ( var->conversion)
308 {
309 CASE_CONVERSION(byte, nibble, None);
310 CASE_CONVERSION(byte, nibble, Posterization);
311 CASE_CONVERSION(byte, nibble, Optimized);
312 CASE_CONVERSION(graybyte, nibble, Ordered);
313 CASE_CONVERSION(graybyte, nibble, ErrorDiffusion);
314 }
315 break;
316 case im256:
317 switch ( var->conversion)
318 {
319 CASE_CONVERSION(byte, byte, None);
320 CASE_CONVERSION(byte, byte, Posterization);
321 CASE_CONVERSION(byte, byte, Optimized);
322 CASE_CONVERSION(byte, byte, Ordered);
323 CASE_CONVERSION(byte, byte, ErrorDiffusion);
324 }
325 break;
326 case imRGB:
327 ic_graybyte_rgb_ictNone(BCPARMS);
328 break;
329 case imShort:
330 ic_Byte_Short( BCPARMS);
331 break;
332 case imLong:
333 ic_Byte_Long( BCPARMS);
334 break;
335 case imFloat:
336 ic_Byte_float( BCPARMS);
337 break;
338 case imDouble:
339 ic_Byte_double( BCPARMS);
340 break;
341 case imComplex:
342 ic_Byte_float_complex(BCPARMS);
343 break;
344 case imDComplex:ic_Byte_double_complex(BCPARMS);
345 break;
346 }
347 break; /* imByte */
348
349 case imShort: switch ( dstType)
350 {
351 CASE_COLOR_BYTE_CONVERT;
352 case imByte : ic_Short_Byte( BCPARMS); break;
353 case imLong : ic_Short_Long( BCPARMS); break;
354 case imFloat : ic_Short_float( BCPARMS); break;
355 case imDouble : ic_Short_double( BCPARMS); break;
356 case imComplex: ic_Short_float_complex(BCPARMS); break;
357 case imDComplex: ic_Short_double_complex(BCPARMS); break;
358 }
359 break;
360 /* imShort */
361
362 case imLong: switch ( dstType)
363 {
364 CASE_COLOR_BYTE_CONVERT;
365 case imByte : ic_Long_Byte( BCPARMS); break;
366 case imShort : ic_Long_Short( BCPARMS); break;
367 case imFloat : ic_Long_float( BCPARMS); break;
368 case imDouble : ic_Long_double( BCPARMS); break;
369 case imComplex: ic_Long_float_complex(BCPARMS); break;
370 case imDComplex: ic_Long_double_complex(BCPARMS); break;
371 }
372 break;
373 /* imLong */
374
375 case imFloat: switch ( dstType)
376 {
377 CASE_COLOR_BYTE_CONVERT;
378 case imByte : ic_float_Byte( BCPARMS); break;
379 case imShort : ic_float_Short( BCPARMS); break;
380 case imLong : ic_float_Long( BCPARMS); break;
381 case imDouble : ic_float_double( BCPARMS); break;
382 case imComplex: ic_float_float_complex(BCPARMS); break;
383 case imDComplex: ic_float_double_complex(BCPARMS); break;
384 }
385 break;
386 /* imFloat */
387
388
389 case imDouble: switch ( dstType)
390 {
391 CASE_COLOR_BYTE_CONVERT;
392 case imByte : ic_double_Byte( BCPARMS); break;
393 case imShort : ic_double_Short( BCPARMS); break;
394 case imLong : ic_double_Long( BCPARMS); break;
395 case imFloat : ic_double_float( BCPARMS); break;
396 case imComplex: ic_double_float_complex(BCPARMS); break;
397 case imDComplex: ic_double_double_complex(BCPARMS); break;
398 }
399 break;
400 /* imDouble */
401
402 case imRGB: switch( dstType)
403 {
404 case imMono:
405 switch ( var->conversion)
406 {
407 CASE_CONVERSION(rgb, mono, None);
408 CASE_CONVERSION(rgb, mono, Posterization);
409 CASE_CONVERSION(rgb, mono, Optimized);
410 CASE_CONVERSION(rgb, mono, Ordered);
411 CASE_CONVERSION(rgb, mono, ErrorDiffusion);
412 }
413 break;
414 case im16:
415 switch ( var->conversion)
416 {
417 CASE_CONVERSION(rgb, nibble, None);
418 CASE_CONVERSION(rgb, nibble, Posterization);
419 CASE_CONVERSION(rgb, nibble, Optimized);
420 CASE_CONVERSION(rgb, nibble, Ordered);
421 CASE_CONVERSION(rgb, nibble, ErrorDiffusion);
422 }
423 break;
424 case im256:
425 switch ( var->conversion)
426 {
427 CASE_CONVERSION(rgb, byte, None);
428 CASE_CONVERSION(rgb, byte, Posterization);
429 CASE_CONVERSION(rgb, byte, Optimized);
430 CASE_CONVERSION(rgb, byte, Ordered);
431 CASE_CONVERSION(rgb, byte, ErrorDiffusion);
432 break;
433 }
434 break;
435 case imByte:
436 ic_rgb_graybyte_ictNone(BCPARMS);
437 break;
438 CASE_NUMERIC_BYTE_CONVERT;
439 }
440 break; /* imRGB */
441
442 case imComplex: switch( dstType) {
443 CASE_COLOR_BYTE_CONVERT;
444 case imByte: ic_float_complex_Byte(BCPARMS); break;
445 case imShort: ic_float_complex_Short(BCPARMS); break;
446 case imLong: ic_float_complex_Long(BCPARMS); break;
447 case imDouble: ic_float_complex_double(BCPARMS); break;
448 case imFloat: ic_float_complex_float( BCPARMS); break;
449 }
450 break;
451 /* imComplex */
452
453 case imDComplex: switch( dstType) {
454 CASE_COLOR_BYTE_CONVERT;
455 case imByte: ic_double_complex_Byte(BCPARMS); break;
456 case imShort: ic_double_complex_Short(BCPARMS); break;
457 case imLong: ic_double_complex_Long(BCPARMS); break;
458 case imDouble: ic_double_complex_double(BCPARMS); break;
459 case imFloat: ic_double_complex_float( BCPARMS); break;
460 }
461 break;
462 /* imDComplex */
463 }
464 }
465
466 static int imTypes[] = {
467 imbpp1, imbpp1|imGrayScale,
468 imbpp4, imbpp4|imGrayScale,
469 imbpp8, imbpp8|imGrayScale,
470 imRGB,
471 imShort, imLong, imFloat, imDouble,
472 imComplex, imDComplex, imTrigComplex, imTrigDComplex,
473 -1
474 };
475
476 Bool
itype_supported(int type)477 itype_supported( int type)
478 {
479 int i = 0;
480 while( imTypes[i] != type && imTypes[i] != -1) i++;
481 return imTypes[i] != -1;
482 }
483
484 static int imConversions[] = {
485 ictNone,
486 ictPosterization,
487 ictOrdered,
488 ictErrorDiffusion,
489 ictOptimized,
490 -1
491 };
492
493 Bool
iconvtype_supported(int conv)494 iconvtype_supported( int conv)
495 {
496 int i = 0;
497 while( imConversions[i] != conv && imConversions[i] != -1) i++;
498 return imConversions[i] != -1;
499 }
500
501 void
init_image_support(void)502 init_image_support(void)
503 {
504 cm_init_colormap();
505 }
506
507 #ifdef __cplusplus
508 }
509 #endif
510