/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/ConversionRGBF.cpp
Line | Count | Source |
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 RGBF |
27 | | // ---------------------------------------------------------- |
28 | | |
29 | | FIBITMAP * DLL_CALLCONV |
30 | 0 | FreeImage_ConvertToRGBF(FIBITMAP *dib) { |
31 | 0 | FIBITMAP *src = NULL; |
32 | 0 | FIBITMAP *dst = NULL; |
33 | |
|
34 | 0 | if(!FreeImage_HasPixels(dib)) return NULL; |
35 | | |
36 | 0 | const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); |
37 | | |
38 | | // check for allowed conversions |
39 | 0 | switch(src_type) { |
40 | 0 | case FIT_BITMAP: |
41 | 0 | { |
42 | | // allow conversion from 24- and 32-bit |
43 | 0 | const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); |
44 | 0 | if((color_type != FIC_RGB) && (color_type != FIC_RGBALPHA)) { |
45 | 0 | src = FreeImage_ConvertTo24Bits(dib); |
46 | 0 | if(!src) return NULL; |
47 | 0 | } else { |
48 | 0 | src = dib; |
49 | 0 | } |
50 | 0 | break; |
51 | 0 | } |
52 | 0 | case FIT_UINT16: |
53 | | // allow conversion from 16-bit |
54 | 0 | src = dib; |
55 | 0 | break; |
56 | 0 | case FIT_RGB16: |
57 | | // allow conversion from 48-bit RGB |
58 | 0 | src = dib; |
59 | 0 | break; |
60 | 0 | case FIT_RGBA16: |
61 | | // allow conversion from 64-bit RGBA (ignore the alpha channel) |
62 | 0 | src = dib; |
63 | 0 | break; |
64 | 0 | case FIT_FLOAT: |
65 | | // allow conversion from 32-bit float |
66 | 0 | src = dib; |
67 | 0 | break; |
68 | 0 | case FIT_RGBAF: |
69 | | // allow conversion from 128-bit RGBAF |
70 | 0 | src = dib; |
71 | 0 | break; |
72 | 0 | case FIT_RGBF: |
73 | | // RGBF type : clone the src |
74 | 0 | return FreeImage_Clone(dib); |
75 | 0 | break; |
76 | 0 | default: |
77 | 0 | return NULL; |
78 | 0 | } |
79 | | |
80 | | // allocate dst image |
81 | | |
82 | 0 | const unsigned width = FreeImage_GetWidth(src); |
83 | 0 | const unsigned height = FreeImage_GetHeight(src); |
84 | |
|
85 | 0 | dst = FreeImage_AllocateT(FIT_RGBF, width, height); |
86 | 0 | if(!dst) { |
87 | 0 | if(src != dib) { |
88 | 0 | FreeImage_Unload(src); |
89 | 0 | } |
90 | 0 | return NULL; |
91 | 0 | } |
92 | | |
93 | | // copy metadata from src to dst |
94 | 0 | FreeImage_CloneMetadata(dst, src); |
95 | | |
96 | | // convert from src type to RGBF |
97 | |
|
98 | 0 | const unsigned src_pitch = FreeImage_GetPitch(src); |
99 | 0 | const unsigned dst_pitch = FreeImage_GetPitch(dst); |
100 | |
|
101 | 0 | switch(src_type) { |
102 | 0 | case FIT_BITMAP: |
103 | 0 | { |
104 | | // calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit) |
105 | 0 | const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); |
106 | |
|
107 | 0 | const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); |
108 | 0 | BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); |
109 | |
|
110 | 0 | for(unsigned y = 0; y < height; y++) { |
111 | 0 | const BYTE *src_pixel = (BYTE*)src_bits; |
112 | 0 | FIRGBF *dst_pixel = (FIRGBF*)dst_bits; |
113 | 0 | for(unsigned x = 0; x < width; x++) { |
114 | | // convert and scale to the range [0..1] |
115 | 0 | dst_pixel->red = (float)(src_pixel[FI_RGBA_RED]) / 255.0F; |
116 | 0 | dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F; |
117 | 0 | dst_pixel->blue = (float)(src_pixel[FI_RGBA_BLUE]) / 255.0F; |
118 | |
|
119 | 0 | src_pixel += bytespp; |
120 | 0 | dst_pixel ++; |
121 | 0 | } |
122 | 0 | src_bits += src_pitch; |
123 | 0 | dst_bits += dst_pitch; |
124 | 0 | } |
125 | 0 | } |
126 | 0 | break; |
127 | | |
128 | 0 | case FIT_UINT16: |
129 | 0 | { |
130 | 0 | const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); |
131 | 0 | BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); |
132 | |
|
133 | 0 | for(unsigned y = 0; y < height; y++) { |
134 | 0 | const WORD *src_pixel = (WORD*)src_bits; |
135 | 0 | FIRGBF *dst_pixel = (FIRGBF*)dst_bits; |
136 | |
|
137 | 0 | for(unsigned x = 0; x < width; x++) { |
138 | | // convert and scale to the range [0..1] |
139 | 0 | const float dst_value = (float)src_pixel[x] / 65535.0F; |
140 | 0 | dst_pixel[x].red = dst_value; |
141 | 0 | dst_pixel[x].green = dst_value; |
142 | 0 | dst_pixel[x].blue = dst_value; |
143 | 0 | } |
144 | 0 | src_bits += src_pitch; |
145 | 0 | dst_bits += dst_pitch; |
146 | 0 | } |
147 | 0 | } |
148 | 0 | break; |
149 | | |
150 | 0 | case FIT_RGB16: |
151 | 0 | { |
152 | 0 | const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); |
153 | 0 | BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); |
154 | |
|
155 | 0 | for(unsigned y = 0; y < height; y++) { |
156 | 0 | const FIRGB16 *src_pixel = (FIRGB16*) src_bits; |
157 | 0 | FIRGBF *dst_pixel = (FIRGBF*) dst_bits; |
158 | |
|
159 | 0 | for(unsigned x = 0; x < width; x++) { |
160 | | // convert and scale to the range [0..1] |
161 | 0 | dst_pixel[x].red = (float)(src_pixel[x].red) / 65535.0F; |
162 | 0 | dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; |
163 | 0 | dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; |
164 | 0 | } |
165 | 0 | src_bits += src_pitch; |
166 | 0 | dst_bits += dst_pitch; |
167 | 0 | } |
168 | 0 | } |
169 | 0 | break; |
170 | | |
171 | 0 | case FIT_RGBA16: |
172 | 0 | { |
173 | 0 | const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); |
174 | 0 | BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); |
175 | |
|
176 | 0 | for(unsigned y = 0; y < height; y++) { |
177 | 0 | const FIRGBA16 *src_pixel = (FIRGBA16*) src_bits; |
178 | 0 | FIRGBF *dst_pixel = (FIRGBF*) dst_bits; |
179 | |
|
180 | 0 | for(unsigned x = 0; x < width; x++) { |
181 | | // convert and scale to the range [0..1] |
182 | 0 | dst_pixel[x].red = (float)(src_pixel[x].red) / 65535.0F; |
183 | 0 | dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; |
184 | 0 | dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; |
185 | 0 | } |
186 | 0 | src_bits += src_pitch; |
187 | 0 | dst_bits += dst_pitch; |
188 | 0 | } |
189 | 0 | } |
190 | 0 | break; |
191 | | |
192 | 0 | case FIT_FLOAT: |
193 | 0 | { |
194 | 0 | const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); |
195 | 0 | BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); |
196 | |
|
197 | 0 | for(unsigned y = 0; y < height; y++) { |
198 | 0 | const float *src_pixel = (float*) src_bits; |
199 | 0 | FIRGBF *dst_pixel = (FIRGBF*) dst_bits; |
200 | |
|
201 | 0 | for(unsigned x = 0; x < width; x++) { |
202 | | // convert by copying greyscale channel to each R, G, B channels |
203 | | // assume float values are in [0..1] |
204 | 0 | const float value = CLAMP(src_pixel[x], 0.0F, 1.0F); |
205 | 0 | dst_pixel[x].red = value; |
206 | 0 | dst_pixel[x].green = value; |
207 | 0 | dst_pixel[x].blue = value; |
208 | 0 | } |
209 | 0 | src_bits += src_pitch; |
210 | 0 | dst_bits += dst_pitch; |
211 | 0 | } |
212 | 0 | } |
213 | 0 | break; |
214 | | |
215 | 0 | case FIT_RGBAF: |
216 | 0 | { |
217 | 0 | const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); |
218 | 0 | BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); |
219 | |
|
220 | 0 | for(unsigned y = 0; y < height; y++) { |
221 | 0 | const FIRGBAF *src_pixel = (FIRGBAF*) src_bits; |
222 | 0 | FIRGBF *dst_pixel = (FIRGBF*) dst_bits; |
223 | |
|
224 | 0 | for(unsigned x = 0; x < width; x++) { |
225 | | // convert and skip alpha channel |
226 | 0 | dst_pixel[x].red = CLAMP(src_pixel[x].red, 0.0F, 1.0F); |
227 | 0 | dst_pixel[x].green = CLAMP(src_pixel[x].green, 0.0F, 1.0F); |
228 | 0 | dst_pixel[x].blue = CLAMP(src_pixel[x].blue, 0.0F, 1.0F); |
229 | 0 | } |
230 | 0 | src_bits += src_pitch; |
231 | 0 | dst_bits += dst_pitch; |
232 | 0 | } |
233 | 0 | } |
234 | 0 | break; |
235 | 0 | } |
236 | | |
237 | 0 | if(src != dib) { |
238 | 0 | FreeImage_Unload(src); |
239 | 0 | } |
240 | |
|
241 | 0 | return dst; |
242 | 0 | } |
243 | | |