/[projet1]/public/pc/shared_libraries/freeimage/v3.12.0/Source/FreeImage/PluginPFM.cpp
Defence Force logotype

Contents of /public/pc/shared_libraries/freeimage/v3.12.0/Source/FreeImage/PluginPFM.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 126 - (show annotations)
Mon Jul 13 12:20:10 2009 UTC (10 years, 7 months ago) by dbug
File size: 9992 byte(s)
Added some shared libraries (UnitTest++, and FreeImage) to avoid having every single project brings its own libraries.
Ideally people should add them in a way we can upgrade versions without breaking things:
-> public/pc/shared_libraries/library_name/library_version/actuall_content
1 // ==========================================================
2 // PFM Loader and Writer
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 // Internal functions
27 // ==========================================================
28
29 /** maximum size of a line in the header */
30 #define PFM_MAXLINE 256
31
32 /** Big endian / Little endian float conversion */
33 #define REVERSEBYTES(source, dest) \
34 { \
35 char *j = (char *) source; \
36 char *dj = (char *) dest; \
37 dj[0] = j[3]; \
38 dj[1] = j[2]; \
39 dj[2] = j[1]; \
40 dj[3] = j[0]; \
41 }
42
43 /**
44 Get a line from a ASCII io stream
45 */
46 static BOOL
47 pfm_get_line(FreeImageIO *io, fi_handle handle, char *buffer, int length) {
48 int i;
49 memset(buffer, 0, length);
50 for(i = 0; i < length; i++) {
51 if(!io->read_proc(&buffer[i], 1, 1, handle))
52 return FALSE;
53 if(buffer[i] == 0x0A)
54 break;
55 }
56
57 return (i < length) ? TRUE : FALSE;
58 }
59
60 /**
61 Get an integer value from the actual position pointed by handle
62 */
63 static int
64 pfm_get_int(FreeImageIO *io, fi_handle handle) {
65 static const char *PNM_ERROR_PARSING = "Parsing error";
66
67 char c = 0;
68 BOOL firstchar;
69
70 // skip forward to start of next number
71
72 if(!io->read_proc(&c, 1, 1, handle)) throw PNM_ERROR_PARSING;
73
74 while (1) {
75 // eat comments
76
77 if (c == '#') {
78 // if we're at a comment, read to end of line
79
80 firstchar = TRUE;
81
82 while (1) {
83 if(!io->read_proc(&c, 1, 1, handle)) throw PNM_ERROR_PARSING;
84
85 if (firstchar && c == ' ') {
86 // loop off 1 sp after #
87
88 firstchar = FALSE;
89 } else if (c == '\n') {
90 break;
91 }
92 }
93 }
94
95 if (c >= '0' && c <='9') {
96 // we've found what we were looking for
97
98 break;
99 }
100
101 if(!io->read_proc(&c, 1, 1, handle)) throw PNM_ERROR_PARSING;
102 }
103
104 // we're at the start of a number, continue until we hit a non-number
105
106 int i = 0;
107
108 while (1) {
109 i = (i * 10) + (c - '0');
110
111 if(!io->read_proc(&c, 1, 1, handle)) throw PNM_ERROR_PARSING;
112
113 if (c < '0' || c > '9')
114 break;
115 }
116
117 return i;
118 }
119
120 // ==========================================================
121 // Plugin Interface
122 // ==========================================================
123
124 static int s_format_id;
125
126 // ==========================================================
127 // Plugin Implementation
128 // ==========================================================
129
130 static const char * DLL_CALLCONV
131 Format() {
132 return "PFM";
133 }
134
135 static const char * DLL_CALLCONV
136 Description() {
137 return "Portable floatmap";
138 }
139
140 static const char * DLL_CALLCONV
141 Extension() {
142 return "pfm";
143 }
144
145 static const char * DLL_CALLCONV
146 RegExpr() {
147 return NULL;
148 }
149
150 static const char * DLL_CALLCONV
151 MimeType() {
152 return "image/freeimage-pfm";
153 }
154
155 static BOOL DLL_CALLCONV
156 Validate(FreeImageIO *io, fi_handle handle) {
157 BYTE pfm_id1[] = { 0x50, 0x46 };
158 BYTE pfm_id2[] = { 0x50, 0x66 };
159 BYTE signature[2] = { 0, 0 };
160
161 io->read_proc(signature, 1, sizeof(pfm_id1), handle);
162
163 if (memcmp(pfm_id1, signature, sizeof(pfm_id1)) == 0)
164 return TRUE;
165
166 if (memcmp(pfm_id2, signature, sizeof(pfm_id2)) == 0)
167 return TRUE;
168
169 return FALSE;
170 }
171
172 static BOOL DLL_CALLCONV
173 SupportsExportDepth(int depth) {
174 return FALSE;
175 }
176
177 static BOOL DLL_CALLCONV
178 SupportsExportType(FREE_IMAGE_TYPE type) {
179 return (
180 (type == FIT_FLOAT) ||
181 (type == FIT_RGBF)
182 );
183 }
184
185 // ----------------------------------------------------------
186
187 static FIBITMAP * DLL_CALLCONV
188 Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
189 char line_buffer[PFM_MAXLINE];
190 char id_one = 0, id_two = 0;
191 FIBITMAP *dib = NULL;
192 float *lineBuffer = NULL;
193
194 if (!handle)
195 return NULL;
196
197 try {
198 FREE_IMAGE_TYPE image_type = FIT_UNKNOWN;
199
200 // Read the first two bytes of the file to determine the file format
201 // "PF" = color image
202 // "Pf" = greyscale image
203
204 io->read_proc(&id_one, 1, 1, handle);
205 io->read_proc(&id_two, 1, 1, handle);
206
207 if(id_one == 'P') {
208 if(id_two == 'F') {
209 image_type = FIT_RGBF;
210 } else if(id_two == 'f') {
211 image_type = FIT_FLOAT;
212 }
213 }
214 if(image_type == FIT_UNKNOWN) {
215 // signature error
216 throw "Invalid magic number";
217 }
218
219 // Read the header information: width, height and the scale value
220 unsigned width = (unsigned) pfm_get_int(io, handle);
221 unsigned height = (unsigned) pfm_get_int(io, handle);
222 float scalefactor = 1;
223
224 BOOL bResult = pfm_get_line(io, handle, line_buffer, PFM_MAXLINE);
225 if(bResult) {
226 bResult = (sscanf(line_buffer, "%f", &scalefactor) == 1) ? TRUE : FALSE;
227 }
228 if(!bResult) {
229 throw "Read error: invalid PFM header";
230 }
231
232 // Create a new DIB
233 dib = FreeImage_AllocateT(image_type, width, height);
234 if (dib == NULL) {
235 throw "DIB allocation failed";
236 }
237
238 // Read the image...
239
240 if(image_type == FIT_RGBF) {
241 const unsigned lineWidth = 3 * width;
242 lineBuffer = (float*)malloc(lineWidth * sizeof(float));
243 if(!lineBuffer) {
244 throw "Allocation error";
245 }
246
247 for (unsigned y = 0; y < height; y++) {
248 FIRGBF *bits = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y);
249
250 if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) {
251 throw "Read error";
252 }
253 float *channel = lineBuffer;
254 if(scalefactor > 0) {
255 // MSB
256 for (unsigned x = 0; x < width; x++) {
257 REVERSEBYTES(channel++, &bits[x].red);
258 REVERSEBYTES(channel++, &bits[x].green);
259 REVERSEBYTES(channel++, &bits[x].blue);
260 }
261 } else {
262 // LSB
263 for (unsigned x = 0; x < width; x++) {
264 bits[x].red = *channel++;
265 bits[x].green = *channel++;
266 bits[x].blue = *channel++;
267 }
268 }
269 }
270
271 free(lineBuffer);
272 lineBuffer = NULL;
273
274 } else if(image_type == FIT_FLOAT) {
275 const unsigned lineWidth = width;
276 lineBuffer = (float*)malloc(lineWidth * sizeof(float));
277 if(!lineBuffer) {
278 throw "Allocation error";
279 }
280
281 for (unsigned y = 0; y < height; y++) {
282 float *bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y);
283
284 if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) {
285 throw "Read error";
286 }
287 float *channel = lineBuffer;
288 if(scalefactor > 0) {
289 // MSB - File is Big endian
290 for (unsigned x = 0; x < width; x++) {
291 REVERSEBYTES(channel++, &bits[x]);
292 }
293 } else {
294 // LSB - File is Little Endian
295 for (unsigned x = 0; x < width; x++) {
296 bits[x] = *channel++;
297 }
298 }
299 }
300
301 free(lineBuffer);
302 lineBuffer = NULL;
303 }
304
305 return dib;
306
307 } catch (const char *text) {
308 if(lineBuffer) free(lineBuffer);
309 if(dib) FreeImage_Unload(dib);
310
311 if(NULL != text) {
312 FreeImage_OutputMessageProc(s_format_id, text);
313 }
314
315 return NULL;
316 }
317
318 }
319
320 static BOOL DLL_CALLCONV
321 Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
322 if(!dib || !handle) return FALSE;
323
324 FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
325 if((image_type != FIT_RGBF) && (image_type != FIT_FLOAT)) {
326 return FALSE;
327 }
328
329 unsigned width = FreeImage_GetWidth(dib);
330 unsigned height = FreeImage_GetHeight(dib);
331 unsigned lineWidth = FreeImage_GetLine(dib);
332
333 // save image as Little Endian
334 const float scalefactor = -1.0F;
335
336 char buffer[PFM_MAXLINE]; // temporary buffer whose size should be enough for what we need
337
338 // Find the appropriate magic number for this file type
339
340 char magic = 0;
341
342 switch(image_type) {
343 case FIT_RGBF:
344 magic = 'F'; // RGBF
345 break;
346 case FIT_FLOAT:
347 magic = 'f'; // float greyscale
348 break;
349 default:
350 return FALSE;
351 }
352
353 // Write the header info
354
355 sprintf(buffer, "P%c\n%d %d\n%f\n", magic, width, height, scalefactor);
356 io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
357
358 // Write the image data
359 for (unsigned y = 0; y < height; y++) {
360 BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
361 io->write_proc(bits, 1, lineWidth, handle);
362 }
363
364 return TRUE;
365 }
366
367 // ==========================================================
368 // Init
369 // ==========================================================
370
371 void DLL_CALLCONV
372 InitPFM(Plugin *plugin, int format_id) {
373 s_format_id = format_id;
374
375 plugin->format_proc = Format;
376 plugin->description_proc = Description;
377 plugin->extension_proc = Extension;
378 plugin->regexpr_proc = RegExpr;
379 plugin->open_proc = NULL;
380 plugin->close_proc = NULL;
381 plugin->pagecount_proc = NULL;
382 plugin->pagecapability_proc = NULL;
383 plugin->load_proc = Load;
384 plugin->save_proc = Save;
385 plugin->validate_proc = Validate;
386 plugin->mime_proc = MimeType;
387 plugin->supports_export_bpp_proc = SupportsExportDepth;
388 plugin->supports_export_type_proc = SupportsExportType;
389 plugin->supports_icc_profiles_proc = NULL;
390 }

  ViewVC Help
Powered by ViewVC 1.1.26