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

Contents of /public/pc/shared_libraries/freeimage/v3.12.0/Source/FreeImage/PluginPSD.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: 11922 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 // Photoshop Loader
3 //
4 // Design and implementation by
5 // - Floris van den Berg (flvdberg@wxs.nl)
6 // - Thorsten Radde (support@IdealSoftware.com)
7 //
8 // Based on public domain code created and
9 // published by Thatcher Ulrich (ulrich@world.std.com)
10 //
11 // This file is part of FreeImage 3
12 //
13 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
14 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
15 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
16 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
17 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
18 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
19 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
20 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
21 // THIS DISCLAIMER.
22 //
23 // Use at your own risk!
24 // ==========================================================
25
26 #include "FreeImage.h"
27
28 // ==========================================================
29 // Bitmap pointer access macros
30 // ==========================================================
31
32 #define BP_START(DIB, WIDTH, HEIGHT) \
33 int xxxscanline = 0; \
34 RGBQUAD *xxxbits = (RGBQUAD *)FreeImage_GetScanLine(DIB, HEIGHT - 1 - xxxscanline); \
35 RGBQUAD *xxxp = xxxbits;
36
37 #define BP_NEXT(DIB, WIDTH, HEIGHT) \
38 xxxp++; \
39 if (xxxp - xxxbits == WIDTH) { \
40 xxxscanline++; \
41 xxxbits = (RGBQUAD *)FreeImage_GetScanLine(DIB, HEIGHT - 1 - xxxscanline); \
42 xxxp = xxxbits; \
43 }
44
45 #define BP_SETVALUE(VALUE, OFFSET) \
46 ((BYTE *)xxxp)[OFFSET] = (BYTE)VALUE;
47
48 // ==========================================================
49 // Internal functions
50 // ==========================================================
51
52 static unsigned
53 Read8(FreeImageIO *io, fi_handle handle) {
54 unsigned char i = 0;
55 io->read_proc(&i, 1, 1, handle);
56 return i;
57 }
58
59 static unsigned
60 Read16(FreeImageIO *io, fi_handle handle) {
61 // reads a two-byte big-endian integer from the given file and returns its value.
62 // assumes unsigned.
63
64 unsigned hi = Read8(io, handle);
65 unsigned lo = Read8(io, handle);
66 return lo + (hi << 8);
67 }
68
69 static unsigned
70 Read32(FreeImageIO *io, fi_handle handle) {
71 // reads a four-byte big-endian integer from the given file and returns its value.
72 // assumes unsigned.
73
74 unsigned b3 = Read8(io, handle);
75 unsigned b2 = Read8(io, handle);
76 unsigned b1 = Read8(io, handle);
77 unsigned b0 = Read8(io, handle);
78 return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
79 }
80
81 // ----------------------------------------------------------
82
83 static void
84 ScanForResolution(float* hres, float* vres, FreeImageIO *io, fi_handle handle, int byte_count) {
85 // scans through the next byte_count bytes of the file, looking for an
86 // image resource block encoding the image's resolution. Returns the resolution(s),
87 // if found, in the pointed-to floats. Units are in pixels/meter.
88
89 while (byte_count) {
90 // read the image resource block header.
91
92 if (Read32(io, handle) != 0x3842494D /* "8BIM" */)
93 throw "image resource block has unknown signature";
94
95 int id = Read16(io, handle);
96
97 // skip the name.
98
99 int name_length = Read8(io, handle) | 1; // name_length must be odd, so that total including size byte is even.
100
101 io->seek_proc(handle, name_length, SEEK_CUR);
102
103 // get the size of the data block.
104
105 int data_size = Read32(io, handle);
106
107 if ((data_size & 1) == 1)
108 data_size++; // block size must be even.
109
110 // account for header size.
111
112 byte_count -= 11 + name_length;
113
114 // if this block is a resolution info structure, then get the resolution.
115
116 if (id == 0x03ED) {
117 int junk;
118
119 int hres_fixed = Read32(io, handle);
120 junk = Read16(io, handle); // display units of hres.
121 junk = Read16(io, handle); // display units of width.
122
123 int vres_fixed = Read32(io, handle);
124 junk = Read16(io, handle); // display units of vres.
125 junk = Read16(io, handle); // display units of height.
126
127 byte_count -= data_size;
128 data_size -= 16;
129
130 // skip any extra bytes at the end of this block...
131
132 if (data_size > 0)
133 io->seek_proc(handle, data_size, SEEK_CUR);
134
135 // need to convert resolution figures from fixed point, pixels/inch
136 // to floating point, pixels/meter.
137
138 *hres = hres_fixed * ((float)39.4 / (float)65536.0);
139 *vres = vres_fixed * ((float)39.4 / (float)65536.0);
140 } else {
141 // skip the rest of this block.
142
143 io->seek_proc(handle, data_size, SEEK_CUR);
144
145 byte_count -= data_size;
146 }
147 }
148 }
149
150 // ----------------------------------------------------------
151
152 static FIBITMAP *
153 LoadPSDRGB(FreeImageIO *io, fi_handle handle, int width, int height, int channel_count) {
154 // skip the mode data. (it's the palette for indexed color; other info for other modes.)
155
156 long area = width * height;
157
158 // skip the reserved data
159
160 int reserved_data_count = Read32(io, handle);
161
162 if (reserved_data_count)
163 io->seek_proc(handle, reserved_data_count, SEEK_CUR);
164
165 // find out if the data is compressed
166 // 0: no compressiod
167 // 1: RLE compressed
168
169 unsigned compression = Read16(io, handle);
170
171 if ((compression > 1) || (compression < 0))
172 return NULL;
173
174 // some formatting information about the channels
175
176 const struct ChannelInfo {
177 int ofs, deflt;
178 } Channel[4] = {
179 { FI_RGBA_RED, 0 }, // red
180 { FI_RGBA_GREEN, 0 }, // green
181 { FI_RGBA_BLUE, 0 }, // blue
182 { FI_RGBA_ALPHA, 255 } // alpha
183 };
184
185 // Create the destination bitmap
186
187 FIBITMAP *dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
188
189 // finally, read the image data.
190
191 if (compression) {
192 // the RLE-compressed data is preceeded by a 2-byte data count for each row in the data
193
194 io->seek_proc(handle, height * channel_count * 2, SEEK_CUR);
195
196 // read the RLE data by channel
197
198 for (int channel = 0; channel < 4; channel++) {
199 const ChannelInfo &c = Channel[channel];
200
201 BP_START(dib, width, height)
202
203 if (channel >= channel_count) {
204 // fill this channel with default data.
205
206 for (int i = 0; i < area; i++) {
207 BP_SETVALUE(c.deflt, c.ofs);
208 BP_NEXT(dib, width, height)
209 }
210 } else {
211 // read the RLE data.
212
213 int count = 0;
214
215 while (count < area) {
216 int len = Read8(io, handle);
217
218 if (len == 128) {
219 // nop
220 } else if (len < 128) {
221 // copy next len + 1 bytes literally.
222
223 len++;
224 // check for buffer overrun
225 if ((count + len) > area) {
226 len = area - count;
227 }
228 count += len;
229
230 while (len) {
231 BP_SETVALUE(Read8(io, handle), c.ofs);
232 BP_NEXT(dib, width, height)
233
234 len--;
235 }
236 } else if (len > 128) {
237 // next -len + 1 bytes in the dest are replicated from next source byte.
238 // (interpret len as a negative 8-bit int.)
239
240 len ^= 0x0FF;
241 len += 2;
242 // check for buffer overrun
243 if ((count + len) > area) {
244 len = area - count;
245 }
246 count += len;
247
248 unsigned val = Read8(io, handle);
249
250 while (len) {
251 BP_SETVALUE(val, c.ofs);
252 BP_NEXT(dib, width, height)
253
254 len--;
255 }
256 }
257 }
258 }
259 }
260 } else {
261 // we're at the raw image data. it's each channel in order (Red, Green, Blue, Alpha, ...)
262 // where each channel consists of an 8-bit value for each pixel in the image.
263
264 for (int channel = 0; channel < 4; channel++) {
265 const ChannelInfo &c = Channel[channel];
266
267 BP_START(dib, width, height)
268
269 if (channel >= channel_count) {
270 // fill this channel with default data.
271
272 for (int i = 0; i < area; i++) {
273 BP_SETVALUE(c.deflt, c.ofs);
274 BP_NEXT(dib, width, height)
275 }
276 } else {
277 // read the data
278
279 for (int i = 0; i < area; i++) {
280 BP_SETVALUE(Read8(io, handle), c.ofs);
281 BP_NEXT(dib, width, height)
282 }
283 }
284 }
285 }
286
287 return dib;
288 }
289
290 // ==========================================================
291 // Plugin Interface
292 // ==========================================================
293
294 static int s_format_id;
295
296 // ==========================================================
297 // Plugin Implementation
298 // ==========================================================
299
300 static const char * DLL_CALLCONV
301 Format() {
302 return "PSD";
303 }
304
305 static const char * DLL_CALLCONV
306 Description() {
307 return "Adobe Photoshop";
308 }
309
310 static const char * DLL_CALLCONV
311 Extension() {
312 return "psd";
313 }
314
315 static const char * DLL_CALLCONV
316 MimeType() {
317 return "image/freeimage-psd";
318 }
319
320 static BOOL DLL_CALLCONV
321 Validate(FreeImageIO *io, fi_handle handle) {
322 return (Read32(io, handle) == 0x38425053);
323 }
324
325 static BOOL DLL_CALLCONV
326 SupportsExportDepth(int depth) {
327 return FALSE;
328 }
329
330 static BOOL DLL_CALLCONV
331 SupportsExportType(FREE_IMAGE_TYPE type) {
332 return FALSE;
333 }
334
335 // ----------------------------------------------------------
336
337 static FIBITMAP * DLL_CALLCONV
338 Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
339 try {
340 if (Read32(io, handle) == 0x38425053) {
341 if (Read16(io, handle) == 1) {
342 // 6 reserved bytes.
343
344 Read32(io, handle);
345 Read16(io, handle);
346
347 // Read the number of channels (R, G, B, A, etc).
348
349 unsigned channel_count = Read16(io, handle);
350
351 if (channel_count >= 0 && channel_count <= 16) {
352 unsigned height = Read32(io, handle);
353 unsigned width = Read32(io, handle);
354
355 if (Read16(io, handle) == 8) {
356 unsigned mode = Read16(io, handle);
357
358 // Get Resolution Information
359 float hres = 2835, vres = 2835; // 72 dpi
360
361 int mode_data_count = Read32(io, handle);
362 if (mode_data_count)
363 io->seek_proc(handle, mode_data_count, SEEK_CUR);
364
365 int resource_data_count = Read32(io, handle);
366 ScanForResolution(&hres, &vres, io, handle, resource_data_count);
367
368 // Valid options are:
369 // 0: Bitmap (not implemented)
370 // 1: Grayscale (not implemented)
371 // 2: Indexed color (not implemented)
372 // 3: RGB color
373 // 4: CMYK color (not implemented)
374 // 7: Multichannel (not implemented)
375 // 8: Duotone (not implemented)
376 // 9: Lab color (not implemented)
377
378 FIBITMAP *pBitmap = NULL;
379
380 switch (mode) {
381 case 3 :
382 pBitmap = LoadPSDRGB(io, handle, width, height, channel_count);
383 break;
384
385 default :
386 throw "color mode not supported";
387 }
388
389 if (pBitmap) {
390 FreeImage_SetDotsPerMeterX(pBitmap, (LONG)hres);
391 FreeImage_SetDotsPerMeterY(pBitmap, (LONG)vres);
392 }
393
394 return pBitmap;
395 }
396 }
397 }
398 }
399 } catch(const char *message) {
400 FreeImage_OutputMessageProc(s_format_id, message);
401 }
402
403 return NULL;
404 }
405
406 // ==========================================================
407 // Init
408 // ==========================================================
409
410 void DLL_CALLCONV
411 InitPSD(Plugin *plugin, int format_id) {
412 s_format_id = format_id;
413
414 plugin->format_proc = Format;
415 plugin->description_proc = Description;
416 plugin->extension_proc = Extension;
417 plugin->regexpr_proc = NULL;
418 plugin->open_proc = NULL;
419 plugin->close_proc = NULL;
420 plugin->pagecount_proc = NULL;
421 plugin->pagecapability_proc = NULL;
422 plugin->load_proc = Load;
423 plugin->save_proc = NULL;
424 plugin->validate_proc = Validate;
425 plugin->mime_proc = MimeType;
426 plugin->supports_export_bpp_proc = SupportsExportDepth;
427 plugin->supports_export_type_proc = SupportsExportType;
428 plugin->supports_icc_profiles_proc = NULL; // not implemented yet;
429 }

  ViewVC Help
Powered by ViewVC 1.1.26