1 // ==========================================================
2 // Bitmap conversion routines
3 //
4 // Design and implementation by
5 // - Herv� Drolon (drolon@infonie.fr)
6 // - Tanner Helland (tannerhelland@users.sf.net)
7 //
8 // This file is part of FreeImage 3
9 //
10 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
11 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
12 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
13 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
14 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
15 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
16 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
17 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
18 // THIS DISCLAIMER.
19 //
20 // Use at your own risk!
21 // ==========================================================
22 
23 #include "FreeImage.h"
24 #include "Utilities.h"
25 
26 // ----------------------------------------------------------
27 
28 /** Convert a greyscale image of type Tsrc to type Tdst.
29 	Conversion is done using standard C language casting convention.
30 */
31 template<class Tdst, class Tsrc>
32 class CONVERT_TYPE
33 {
34 public:
35 	FIBITMAP* convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type);
36 };
37 
38 template<class Tdst, class Tsrc> FIBITMAP*
convert(FIBITMAP * src,FREE_IMAGE_TYPE dst_type)39 CONVERT_TYPE<Tdst, Tsrc>::convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type) {
40 
41 	FIBITMAP *dst = NULL;
42 
43 	unsigned width	= FreeImage_GetWidth(src);
44 	unsigned height = FreeImage_GetHeight(src);
45 	unsigned bpp	= FreeImage_GetBPP(src);
46 
47 	// allocate dst image
48 
49 	dst = FreeImage_AllocateT(dst_type, width, height, bpp,
50 			FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src));
51 	if(!dst) return NULL;
52 
53 	// convert from src_type to dst_type
54 
55 	for(unsigned y = 0; y < height; y++) {
56 		const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
57 		Tdst *dst_bits = reinterpret_cast<Tdst*>(FreeImage_GetScanLine(dst, y));
58 
59 		for(unsigned x = 0; x < width; x++) {
60 			*dst_bits++ = static_cast<Tdst>(*src_bits++);
61 		}
62 	}
63 
64 	return dst;
65 }
66 
67 
68 /** Convert a greyscale image of type Tsrc to a 8-bit grayscale dib.
69 	Conversion is done using either a linear scaling from [min, max] to [0, 255]
70 	or a rounding from src_pixel to (BYTE) MIN(255, MAX(0, q)) where int q = int(src_pixel + 0.5);
71 */
72 template<class Tsrc>
73 class CONVERT_TO_BYTE
74 {
75 public:
76 	FIBITMAP* convert(FIBITMAP *src, BOOL scale_linear);
77 };
78 
79 template<class Tsrc> FIBITMAP*
convert(FIBITMAP * src,BOOL scale_linear)80 CONVERT_TO_BYTE<Tsrc>::convert(FIBITMAP *src, BOOL scale_linear) {
81 	FIBITMAP *dst = NULL;
82 	unsigned x, y;
83 
84 	unsigned width	= FreeImage_GetWidth(src);
85 	unsigned height = FreeImage_GetHeight(src);
86 
87 	// allocate a 8-bit dib
88 
89 	dst = FreeImage_AllocateT(FIT_BITMAP, width, height, 8, 0, 0, 0);
90 	if(!dst) return NULL;
91 
92 	// build a greyscale palette
93 	RGBQUAD *pal = FreeImage_GetPalette(dst);
94 	for(int i = 0; i < 256; i++) {
95 		pal[i].rgbRed = (BYTE)i;
96 		pal[i].rgbGreen = (BYTE)i;
97 		pal[i].rgbBlue = (BYTE)i;
98 	}
99 
100 	// convert the src image to dst
101 	// (FIBITMAP are stored upside down)
102 	if(scale_linear) {
103 		Tsrc max, min;
104 		double scale;
105 
106 		// find the min and max value of the image
107 		Tsrc l_min, l_max;
108 		min = 255, max = 0;
109 		for(y = 0; y < height; y++) {
110 			Tsrc *bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
111 			MAXMIN(bits, width, l_max, l_min);
112 			if(l_max > max) max = l_max;
113 			if(l_min < min) min = l_min;
114 		}
115 		if(max == min) {
116 			max = 255; min = 0;
117 		}
118 
119 		// compute the scaling factor
120 		scale = 255 / (double)(max - min);
121 
122 		// scale to 8-bit
123 		for(y = 0; y < height; y++) {
124 			Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
125 			BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
126 			for(x = 0; x < width; x++) {
127 				dst_bits[x] = (BYTE)( scale * (src_bits[x] - min) + 0.5);
128 			}
129 		}
130 	} else {
131 		for(y = 0; y < height; y++) {
132 			Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
133 			BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
134 			for(x = 0; x < width; x++) {
135 				// rounding
136 				int q = int(src_bits[x] + 0.5);
137 				dst_bits[x] = (BYTE) MIN(255, MAX(0, q));
138 			}
139 		}
140 	}
141 
142 	return dst;
143 }
144 
145 /** Convert a greyscale image of type Tsrc to a FICOMPLEX dib.
146 */
147 template<class Tsrc>
148 class CONVERT_TO_COMPLEX
149 {
150 public:
151 	FIBITMAP* convert(FIBITMAP *src);
152 };
153 
154 template<class Tsrc> FIBITMAP*
convert(FIBITMAP * src)155 CONVERT_TO_COMPLEX<Tsrc>::convert(FIBITMAP *src) {
156 	FIBITMAP *dst = NULL;
157 
158 	unsigned width	= FreeImage_GetWidth(src);
159 	unsigned height = FreeImage_GetHeight(src);
160 
161 	// allocate dst image
162 
163 	dst = FreeImage_AllocateT(FIT_COMPLEX, width, height);
164 	if(!dst) return NULL;
165 
166 	// convert from src_type to FIT_COMPLEX
167 
168 	for(unsigned y = 0; y < height; y++) {
169 		const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
170 		FICOMPLEX *dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y);
171 
172 		for(unsigned x = 0; x < width; x++) {
173 			dst_bits[x].r = (double)src_bits[x];
174 			dst_bits[x].i = 0;
175 		}
176 	}
177 
178 	return dst;
179 }
180 
181 // ----------------------------------------------------------
182 
183 // Convert from type BYTE to type X
184 CONVERT_TYPE<unsigned short, BYTE>	convertByteToUShort;
185 CONVERT_TYPE<short, BYTE>			convertByteToShort;
186 CONVERT_TYPE<DWORD, BYTE>			convertByteToULong;
187 CONVERT_TYPE<LONG, BYTE>			convertByteToLong;
188 CONVERT_TYPE<float, BYTE>			convertByteToFloat;
189 CONVERT_TYPE<double, BYTE>			convertByteToDouble;
190 
191 // Convert from type X to type BYTE
192 CONVERT_TO_BYTE<unsigned short>	convertUShortToByte;
193 CONVERT_TO_BYTE<short>			convertShortToByte;
194 CONVERT_TO_BYTE<DWORD>			convertULongToByte;
195 CONVERT_TO_BYTE<LONG>			convertLongToByte;
196 CONVERT_TO_BYTE<float>			convertFloatToByte;
197 CONVERT_TO_BYTE<double>			convertDoubleToByte;
198 
199 // Convert from type X to type float
200 CONVERT_TYPE<float, unsigned short>	convertUShortToFloat;
201 CONVERT_TYPE<float, short>			convertShortToFloat;
202 CONVERT_TYPE<float, DWORD>			convertULongToFloat;
203 CONVERT_TYPE<float, LONG>			convertLongToFloat;
204 
205 // Convert from type X to type double
206 CONVERT_TYPE<double, unsigned short>	convertUShortToDouble;
207 CONVERT_TYPE<double, short>				convertShortToDouble;
208 CONVERT_TYPE<double, DWORD>				convertULongToDouble;
209 CONVERT_TYPE<double, LONG>				convertLongToDouble;
210 CONVERT_TYPE<double, float>				convertFloatToDouble;
211 
212 // Convert from type X to type FICOMPLEX
213 CONVERT_TO_COMPLEX<BYTE>			convertByteToComplex;
214 CONVERT_TO_COMPLEX<unsigned short>	convertUShortToComplex;
215 CONVERT_TO_COMPLEX<short>			convertShortToComplex;
216 CONVERT_TO_COMPLEX<DWORD>			convertULongToComplex;
217 CONVERT_TO_COMPLEX<LONG>			convertLongToComplex;
218 CONVERT_TO_COMPLEX<float>			convertFloatToComplex;
219 CONVERT_TO_COMPLEX<double>			convertDoubleToComplex;
220 
221 // ----------------------------------------------------------
222 
223 // ----------------------------------------------------------
224 //   smart convert X to standard FIBITMAP
225 // ----------------------------------------------------------
226 
227 /** Convert image of any type to a standard 8-bit greyscale image.
228 For standard images, a clone of the input image is returned.
229 When the scale_linear parameter is TRUE, conversion is done by scaling linearly
230 each pixel to an integer value between [0..255]. When it is FALSE, conversion is done
231 by rounding each float pixel to an integer between [0..255].
232 For complex images, the magnitude is extracted as a double image, then converted according to the scale parameter.
233 @param image Image to convert
234 @param scale_linear Linear scaling / rounding switch
235 */
236 FIBITMAP* DLL_CALLCONV
FreeImage_ConvertToStandardType(FIBITMAP * src,BOOL scale_linear)237 FreeImage_ConvertToStandardType(FIBITMAP *src, BOOL scale_linear) {
238 	FIBITMAP *dst = NULL;
239 
240 	if(!src) return NULL;
241 
242 	// convert from src_type to FIT_BITMAP
243 
244 	const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src);
245 
246 	switch(src_type) {
247 		case FIT_BITMAP:	// standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
248 			dst = FreeImage_Clone(src);
249 			break;
250 		case FIT_UINT16:	// array of unsigned short: unsigned 16-bit
251 			dst = convertUShortToByte.convert(src, scale_linear);
252 			break;
253 		case FIT_INT16:		// array of short: signed 16-bit
254 			dst = convertShortToByte.convert(src, scale_linear);
255 			break;
256 		case FIT_UINT32:	// array of unsigned long: unsigned 32-bit
257 			dst = convertULongToByte.convert(src, scale_linear);
258 			break;
259 		case FIT_INT32:		// array of long: signed 32-bit
260 			dst = convertLongToByte.convert(src, scale_linear);
261 			break;
262 		case FIT_FLOAT:		// array of float: 32-bit
263 			dst = convertFloatToByte.convert(src, scale_linear);
264 			break;
265 		case FIT_DOUBLE:	// array of double: 64-bit
266 			dst = convertDoubleToByte.convert(src, scale_linear);
267 			break;
268 		case FIT_COMPLEX:	// array of FICOMPLEX: 2 x 64-bit
269 			{
270 				// Convert to type FIT_DOUBLE
271 				FIBITMAP *dib_double = FreeImage_GetComplexChannel(src, FICC_MAG);
272 				if(dib_double) {
273 					// Convert to a standard bitmap (linear scaling)
274 					dst = convertDoubleToByte.convert(dib_double, scale_linear);
275 					// Free image of type FIT_DOUBLE
276 					FreeImage_Unload(dib_double);
277 				}
278 			}
279 			break;
280 		case FIT_RGB16:		// 48-bit RGB image: 3 x 16-bit
281 			break;
282 		case FIT_RGBA16:	// 64-bit RGBA image: 4 x 16-bit
283 			break;
284 		case FIT_RGBF:		// 96-bit RGB float image: 3 x 32-bit IEEE floating point
285 			break;
286 		case FIT_RGBAF:		// 128-bit RGBA float image: 4 x 32-bit IEEE floating point
287 			break;
288 	}
289 
290 	if(NULL == dst) {
291 		FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, FIT_BITMAP);
292 	} else {
293 		// copy metadata from src to dst
294 		FreeImage_CloneMetadata(dst, src);
295 	}
296 
297 	return dst;
298 }
299 
300 
301 
302 // ----------------------------------------------------------
303 //   smart convert X to Y
304 // ----------------------------------------------------------
305 
306 FIBITMAP* DLL_CALLCONV
FreeImage_ConvertToType(FIBITMAP * src,FREE_IMAGE_TYPE dst_type,BOOL scale_linear)307 FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear) {
308 	FIBITMAP *dst = NULL;
309 
310 	if(!FreeImage_HasPixels(src)) return NULL;
311 
312 	// convert from src_type to dst_type
313 
314 	const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src);
315 
316 	if(src_type == dst_type) {
317 		return FreeImage_Clone(src);
318 	}
319 
320 	const unsigned src_bpp = FreeImage_GetBPP(src);
321 
322 	switch(src_type) {
323 		case FIT_BITMAP:
324 			switch(dst_type) {
325 				case FIT_UINT16:
326 					dst = FreeImage_ConvertToUINT16(src);
327 					break;
328 				case FIT_INT16:
329 					dst = (src_bpp == 8) ? convertByteToShort.convert(src, dst_type) : NULL;
330 					break;
331 				case FIT_UINT32:
332 					dst = (src_bpp == 8) ? convertByteToULong.convert(src, dst_type) : NULL;
333 					break;
334 				case FIT_INT32:
335 					dst = (src_bpp == 8) ? convertByteToLong.convert(src, dst_type) : NULL;
336 					break;
337 				case FIT_FLOAT:
338 					dst = FreeImage_ConvertToFloat(src);
339 					break;
340 				case FIT_DOUBLE:
341 					dst = (src_bpp == 8) ? convertByteToDouble.convert(src, dst_type) : NULL;
342 					break;
343 				case FIT_COMPLEX:
344 					dst = (src_bpp == 8) ? convertByteToComplex.convert(src) : NULL;
345 					break;
346 				case FIT_RGB16:
347 					dst = FreeImage_ConvertToRGB16(src);
348 					break;
349 				case FIT_RGBA16:
350 					dst = FreeImage_ConvertToRGBA16(src);
351 					break;
352 				case FIT_RGBF:
353 					dst = FreeImage_ConvertToRGBF(src);
354 					break;
355 				case FIT_RGBAF:
356 					dst = FreeImage_ConvertToRGBAF(src);
357 					break;
358 			}
359 			break;
360 		case FIT_UINT16:
361 			switch(dst_type) {
362 				case FIT_BITMAP:
363 					dst = FreeImage_ConvertToStandardType(src, scale_linear);
364 					break;
365 				case FIT_INT16:
366 					break;
367 				case FIT_UINT32:
368 					break;
369 				case FIT_INT32:
370 					break;
371 				case FIT_FLOAT:
372 					dst = FreeImage_ConvertToFloat(src);
373 					break;
374 				case FIT_DOUBLE:
375 					dst = convertUShortToDouble.convert(src, dst_type);
376 					break;
377 				case FIT_COMPLEX:
378 					dst = convertUShortToComplex.convert(src);
379 					break;
380 				case FIT_RGB16:
381 					dst = FreeImage_ConvertToRGB16(src);
382 					break;
383 				case FIT_RGBA16:
384 					dst = FreeImage_ConvertToRGBA16(src);
385 					break;
386 				case FIT_RGBF:
387 					dst = FreeImage_ConvertToRGBF(src);
388 					break;
389 				case FIT_RGBAF:
390 					dst = FreeImage_ConvertToRGBAF(src);
391 					break;
392 			}
393 			break;
394 		case FIT_INT16:
395 			switch(dst_type) {
396 				case FIT_BITMAP:
397 					dst = FreeImage_ConvertToStandardType(src, scale_linear);
398 					break;
399 				case FIT_UINT16:
400 					break;
401 				case FIT_UINT32:
402 					break;
403 				case FIT_INT32:
404 					break;
405 				case FIT_FLOAT:
406 					dst = convertShortToFloat.convert(src, dst_type);
407 					break;
408 				case FIT_DOUBLE:
409 					dst = convertShortToDouble.convert(src, dst_type);
410 					break;
411 				case FIT_COMPLEX:
412 					dst = convertShortToComplex.convert(src);
413 					break;
414 				case FIT_RGB16:
415 					break;
416 				case FIT_RGBA16:
417 					break;
418 				case FIT_RGBF:
419 					break;
420 				case FIT_RGBAF:
421 					break;
422 			}
423 			break;
424 		case FIT_UINT32:
425 			switch(dst_type) {
426 				case FIT_BITMAP:
427 					dst = FreeImage_ConvertToStandardType(src, scale_linear);
428 					break;
429 				case FIT_UINT16:
430 					break;
431 				case FIT_INT16:
432 					break;
433 				case FIT_INT32:
434 					break;
435 				case FIT_FLOAT:
436 					dst = convertULongToFloat.convert(src, dst_type);
437 					break;
438 				case FIT_DOUBLE:
439 					dst = convertULongToDouble.convert(src, dst_type);
440 					break;
441 				case FIT_COMPLEX:
442 					dst = convertULongToComplex.convert(src);
443 					break;
444 				case FIT_RGB16:
445 					break;
446 				case FIT_RGBA16:
447 					break;
448 				case FIT_RGBF:
449 					break;
450 				case FIT_RGBAF:
451 					break;
452 			}
453 			break;
454 		case FIT_INT32:
455 			switch(dst_type) {
456 				case FIT_BITMAP:
457 					dst = FreeImage_ConvertToStandardType(src, scale_linear);
458 					break;
459 				case FIT_UINT16:
460 					break;
461 				case FIT_INT16:
462 					break;
463 				case FIT_UINT32:
464 					break;
465 				case FIT_FLOAT:
466 					dst = convertLongToFloat.convert(src, dst_type);
467 					break;
468 				case FIT_DOUBLE:
469 					dst = convertLongToDouble.convert(src, dst_type);
470 					break;
471 				case FIT_COMPLEX:
472 					dst = convertLongToComplex.convert(src);
473 					break;
474 				case FIT_RGB16:
475 					break;
476 				case FIT_RGBA16:
477 					break;
478 				case FIT_RGBF:
479 					break;
480 				case FIT_RGBAF:
481 					break;
482 			}
483 			break;
484 		case FIT_FLOAT:
485 			switch(dst_type) {
486 				case FIT_BITMAP:
487 					dst = FreeImage_ConvertToStandardType(src, scale_linear);
488 					break;
489 				case FIT_UINT16:
490 					break;
491 				case FIT_INT16:
492 					break;
493 				case FIT_UINT32:
494 					break;
495 				case FIT_INT32:
496 					break;
497 				case FIT_DOUBLE:
498 					dst = convertFloatToDouble.convert(src, dst_type);
499 					break;
500 				case FIT_COMPLEX:
501 					dst = convertFloatToComplex.convert(src);
502 					break;
503 				case FIT_RGB16:
504 					break;
505 				case FIT_RGBA16:
506 					break;
507 				case FIT_RGBF:
508 					dst = FreeImage_ConvertToRGBF(src);
509 					break;
510 				case FIT_RGBAF:
511 					dst = FreeImage_ConvertToRGBAF(src);
512 					break;
513 			}
514 			break;
515 		case FIT_DOUBLE:
516 			switch(dst_type) {
517 				case FIT_BITMAP:
518 					dst = FreeImage_ConvertToStandardType(src, scale_linear);
519 					break;
520 				case FIT_UINT16:
521 					break;
522 				case FIT_INT16:
523 					break;
524 				case FIT_UINT32:
525 					break;
526 				case FIT_INT32:
527 					break;
528 				case FIT_FLOAT:
529 					break;
530 				case FIT_COMPLEX:
531 					dst = convertDoubleToComplex.convert(src);
532 					break;
533 				case FIT_RGB16:
534 					break;
535 				case FIT_RGBA16:
536 					break;
537 				case FIT_RGBF:
538 					break;
539 				case FIT_RGBAF:
540 					break;
541 			}
542 			break;
543 		case FIT_COMPLEX:
544 			switch(dst_type) {
545 				case FIT_BITMAP:
546 					break;
547 				case FIT_UINT16:
548 					break;
549 				case FIT_INT16:
550 					break;
551 				case FIT_UINT32:
552 					break;
553 				case FIT_INT32:
554 					break;
555 				case FIT_FLOAT:
556 					break;
557 				case FIT_DOUBLE:
558 					break;
559 				case FIT_RGB16:
560 					break;
561 				case FIT_RGBA16:
562 					break;
563 				case FIT_RGBF:
564 					break;
565 				case FIT_RGBAF:
566 					break;
567 			}
568 			break;
569 		case FIT_RGB16:
570 			switch(dst_type) {
571 				case FIT_BITMAP:
572 					dst = FreeImage_ConvertTo24Bits(src);
573 					break;
574 				case FIT_UINT16:
575 					dst = FreeImage_ConvertToUINT16(src);
576 					break;
577 				case FIT_INT16:
578 					break;
579 				case FIT_UINT32:
580 					break;
581 				case FIT_INT32:
582 					break;
583 				case FIT_FLOAT:
584 					dst = FreeImage_ConvertToFloat(src);
585 					break;
586 				case FIT_DOUBLE:
587 					break;
588 				case FIT_COMPLEX:
589 					break;
590 				case FIT_RGBA16:
591 					dst = FreeImage_ConvertToRGBA16(src);
592 					break;
593 				case FIT_RGBF:
594 					dst = FreeImage_ConvertToRGBF(src);
595 					break;
596 				case FIT_RGBAF:
597 					dst = FreeImage_ConvertToRGBAF(src);
598 					break;
599 			}
600 			break;
601 		case FIT_RGBA16:
602 			switch(dst_type) {
603 				case FIT_BITMAP:
604 					dst = FreeImage_ConvertTo32Bits(src);
605 					break;
606 				case FIT_UINT16:
607 					dst = FreeImage_ConvertToUINT16(src);
608 					break;
609 				case FIT_INT16:
610 					break;
611 				case FIT_UINT32:
612 					break;
613 				case FIT_INT32:
614 					break;
615 				case FIT_FLOAT:
616 					dst = FreeImage_ConvertToFloat(src);
617 					break;
618 				case FIT_DOUBLE:
619 					break;
620 				case FIT_COMPLEX:
621 					break;
622 				case FIT_RGB16:
623 					dst = FreeImage_ConvertToRGB16(src);
624 					break;
625 				case FIT_RGBF:
626 					dst = FreeImage_ConvertToRGBF(src);
627 					break;
628 				case FIT_RGBAF:
629 					dst = FreeImage_ConvertToRGBAF(src);
630 					break;
631 			}
632 			break;
633 		case FIT_RGBF:
634 			switch(dst_type) {
635 				case FIT_BITMAP:
636 					break;
637 				case FIT_UINT16:
638 					break;
639 				case FIT_INT16:
640 					break;
641 				case FIT_UINT32:
642 					break;
643 				case FIT_INT32:
644 					break;
645 				case FIT_FLOAT:
646 					dst = FreeImage_ConvertToFloat(src);
647 					break;
648 				case FIT_DOUBLE:
649 					break;
650 				case FIT_COMPLEX:
651 					break;
652 				case FIT_RGB16:
653 					break;
654 				case FIT_RGBA16:
655 					break;
656 				case FIT_RGBAF:
657 					dst = FreeImage_ConvertToRGBAF(src);
658 					break;
659 			}
660 			break;
661 		case FIT_RGBAF:
662 			switch(dst_type) {
663 				case FIT_BITMAP:
664 					break;
665 				case FIT_UINT16:
666 					break;
667 				case FIT_INT16:
668 					break;
669 				case FIT_UINT32:
670 					break;
671 				case FIT_INT32:
672 					break;
673 				case FIT_FLOAT:
674 					dst = FreeImage_ConvertToFloat(src);
675 					break;
676 				case FIT_DOUBLE:
677 					break;
678 				case FIT_COMPLEX:
679 					break;
680 				case FIT_RGB16:
681 					break;
682 				case FIT_RGBA16:
683 					break;
684 				case FIT_RGBF:
685 					dst = FreeImage_ConvertToRGBF(src);
686 					break;
687 			}
688 			break;
689 	}
690 
691 	if(NULL == dst) {
692 		FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, dst_type);
693 	} else {
694 		// copy metadata from src to dst
695 		FreeImage_CloneMetadata(dst, src);
696 	}
697 
698 	return dst;
699 }
700