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