1 // ==========================================================
2 // Bitmap conversion routines
3 //
4 // Design and implementation by
5 // - Herv� Drolon (drolon@infonie.fr)
6 //
7 // This file is part of FreeImage 3
8 //
9 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
10 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
11 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
12 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
13 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
14 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
15 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
16 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
17 // THIS DISCLAIMER.
18 //
19 // Use at your own risk!
20 // ==========================================================
21
22 #include "FreeImage.h"
23 #include "Utilities.h"
24
25 // ----------------------------------------------------------
26 // smart convert X to RGB16
27 // ----------------------------------------------------------
28
29 FIBITMAP * DLL_CALLCONV
FreeImage_ConvertToRGB16(FIBITMAP * dib)30 FreeImage_ConvertToRGB16(FIBITMAP *dib) {
31 FIBITMAP *src = NULL;
32 FIBITMAP *dst = NULL;
33
34 if(!FreeImage_HasPixels(dib)) return NULL;
35
36 const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib);
37
38 // check for allowed conversions
39 switch(src_type) {
40 case FIT_BITMAP:
41 {
42 // convert to 24-bit if needed
43 if((FreeImage_GetBPP(dib) == 24) || (FreeImage_GetBPP(dib) == 32)) {
44 src = dib;
45 } else {
46 src = FreeImage_ConvertTo24Bits(dib);
47 if(!src) return NULL;
48 }
49 break;
50 }
51 case FIT_UINT16:
52 // allow conversion from unsigned 16-bit
53 src = dib;
54 break;
55 case FIT_RGB16:
56 // RGB16 type : clone the src
57 return FreeImage_Clone(dib);
58 break;
59 case FIT_RGBA16:
60 // allow conversion from 64-bit RGBA (ignore the alpha channel)
61 src = dib;
62 break;
63 default:
64 return NULL;
65 }
66
67 // allocate dst image
68
69 const unsigned width = FreeImage_GetWidth(src);
70 const unsigned height = FreeImage_GetHeight(src);
71
72 dst = FreeImage_AllocateT(FIT_RGB16, width, height);
73 if(!dst) {
74 if(src != dib) {
75 FreeImage_Unload(src);
76 }
77 return NULL;
78 }
79
80 // copy metadata from src to dst
81 FreeImage_CloneMetadata(dst, src);
82
83 // convert from src type to RGB16
84
85 switch(src_type) {
86 case FIT_BITMAP:
87 {
88 // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit)
89 const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
90
91 for(unsigned y = 0; y < height; y++) {
92 const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y);
93 FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y);
94 for(unsigned x = 0; x < width; x++) {
95 dst_bits[x].red = src_bits[FI_RGBA_RED] << 8;
96 dst_bits[x].green = src_bits[FI_RGBA_GREEN] << 8;
97 dst_bits[x].blue = src_bits[FI_RGBA_BLUE] << 8;
98 src_bits += bytespp;
99 }
100 }
101 }
102 break;
103
104 case FIT_UINT16:
105 {
106 for(unsigned y = 0; y < height; y++) {
107 const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y);
108 FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y);
109 for(unsigned x = 0; x < width; x++) {
110 // convert by copying greyscale channel to each R, G, B channels
111 dst_bits[x].red = src_bits[x];
112 dst_bits[x].green = src_bits[x];
113 dst_bits[x].blue = src_bits[x];
114 }
115 }
116 }
117 break;
118
119 case FIT_RGBA16:
120 {
121 for(unsigned y = 0; y < height; y++) {
122 const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y);
123 FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y);
124 for(unsigned x = 0; x < width; x++) {
125 // convert and skip alpha channel
126 dst_bits[x].red = src_bits[x].red;
127 dst_bits[x].green = src_bits[x].green;
128 dst_bits[x].blue = src_bits[x].blue;
129 }
130 }
131 }
132 break;
133
134 default:
135 break;
136 }
137
138 if(src != dib) {
139 FreeImage_Unload(src);
140 }
141
142 return dst;
143 }
144
145