1 // ==========================================================
2 // Photoshop Loader
3 //
4 // Design and implementation by
5 // - Hervé Drolon (drolon@infonie.fr)
6 // - Mihail Naydenov (mnaydenov@users.sourceforge.net)
7 // - Garrick Meeker (garrickmeeker@users.sourceforge.net)
8 //
9 // Based on LGPL code created and published by http://sourceforge.net/projects/elynx/
10 // Format is now publicly documented at:
11 // https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
12 //
13 // This file is part of FreeImage 3
14 //
15 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
16 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
17 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
18 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
19 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
20 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
21 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
22 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
23 // THIS DISCLAIMER.
24 //
25 // Use at your own risk!
26 // ==========================================================
27
28 #include "FreeImage.h"
29 #include "Utilities.h"
30 #include "PSDParser.h"
31
32 #include "../Metadata/FreeImageTag.h"
33
34 // --------------------------------------------------------------------------
35
36 // PSD signature (= '8BPS')
37 #define PSD_SIGNATURE 0x38425053
38 // Image resource block signature (= '8BIM')
39 #define PSD_RESOURCE 0x3842494D
40
41 // PSD color modes
42 #define PSDP_BITMAP 0
43 #define PSDP_GRAYSCALE 1
44 #define PSDP_INDEXED 2
45 #define PSDP_RGB 3
46 #define PSDP_CMYK 4
47 #define PSDP_MULTICHANNEL 7
48 #define PSDP_DUOTONE 8
49 #define PSDP_LAB 9
50
51 // PSD compression schemes
52 #define PSDP_COMPRESSION_NONE 0 //! Raw data
53 #define PSDP_COMPRESSION_RLE 1 //! RLE compression (same as TIFF packed bits)
54 #define PSDP_COMPRESSION_ZIP 2 //! ZIP compression without prediction
55 #define PSDP_COMPRESSION_ZIP_PREDICTION 3 //! ZIP compression with prediction
56
57 /**
58 PSD image resources
59 */
60 enum {
61 //! Obsolete - Photoshop 2.0
62 PSDP_RES_RESOLUTION_INFO_V2 = 1000,
63 //! ResolutionInfo structure
64 PSDP_RES_RESOLUTION_INFO = 1005,
65 //! DisplayInfo structure
66 PSDP_RES_DISPLAY_INFO = 1007,
67 //! IPTC-NAA record
68 PSDP_RES_IPTC_NAA = 1028,
69 //! (Photoshop 4.0) Thumbnail resource for Photoshop 4.0 only
70 PSDP_RES_THUMBNAIL_PS4 = 1033,
71 //! (Photoshop 4.0) Copyright flag
72 PSDP_RES_COPYRIGHT = 1034,
73 //! (Photoshop 5.0) Thumbnail resource (supersedes resource 1033)
74 PSDP_RES_THUMBNAIL = 1036,
75 //! (Photoshop 5.0) Global Angle
76 PSDP_RES_GLOBAL_ANGLE = 1037,
77 //! ICC profile
78 PSDP_RES_ICC_PROFILE = 1039,
79 //! (Photoshop 6.0) Indexed Color Table Count; 2 bytes for the number of colors in table that are actually defined
80 PSDP_RES_INDEXED_COLORS = 1046,
81 //! (Photoshop 6.0) Transparency Index. 2 bytes for the index of transparent color, if any.
82 PSDP_RES_TRANSPARENCY_INDEX = 1047,
83 //! (Photoshop 7.0) EXIF data 1
84 PSDP_RES_EXIF1 = 1058,
85 //! (Photoshop 7.0) EXIF data 3
86 PSDP_RES_EXIF3 = 1059,
87 //! (Photoshop 7.0) XMP metadata
88 PSDP_RES_XMP = 1060,
89 //! (Photoshop CS3) DisplayInfo structure
90 PSDP_RES_DISPLAY_INFO_FLT = 1077,
91 };
92
93 #define SAFE_DELETE_ARRAY(_p_) { if (NULL != (_p_)) { delete [] (_p_); (_p_) = NULL; } }
94
95 // --------------------------------------------------------------------------
96
97 template <int N>
98 class PSDGetValue {
99 public:
get(const BYTE * iprBuffer)100 static inline int get(const BYTE * iprBuffer) {} // error
101 };
102
103 template <>
104 class PSDGetValue<1> {
105 public:
get(const BYTE * iprBuffer)106 static inline BYTE get(const BYTE * iprBuffer) { return iprBuffer[0]; }
107 };
108
109 template <>
110 class PSDGetValue<2> {
111 public:
get(const BYTE * iprBuffer)112 static inline WORD get(const BYTE * iprBuffer) {
113 WORD v = ((const WORD*)iprBuffer)[0];
114 #ifndef FREEIMAGE_BIGENDIAN
115 SwapShort(&v);
116 #endif
117 return (int)v;
118 }
119 };
120
121 template <>
122 class PSDGetValue<4> {
123 public:
get(const BYTE * iprBuffer)124 static inline DWORD get(const BYTE * iprBuffer) {
125 DWORD v = ((const DWORD*)iprBuffer)[0];
126 #ifndef FREEIMAGE_BIGENDIAN
127 SwapLong(&v);
128 #endif
129 return v;
130 }
131 };
132
133 template <>
134 class PSDGetValue<8> {
135 public:
get(const BYTE * iprBuffer)136 static inline UINT64 get(const BYTE * iprBuffer) {
137 UINT64 v = ((const UINT64*)iprBuffer)[0];
138 #ifndef FREEIMAGE_BIGENDIAN
139 SwapInt64(&v);
140 #endif
141 return v;
142 }
143 };
144
145 #define psdGetValue(PTR, SIZE) PSDGetValue<SIZE>::get((PTR))
146 #define psdGetLongValue(PTR, SIZE) PSDGetValue<SIZE>::get((PTR))
147
148 // --------------------------------------------------------------------------
149
150 static UINT64
psdReadSize(FreeImageIO * io,fi_handle handle,const psdHeaderInfo & header)151 psdReadSize(FreeImageIO *io, fi_handle handle, const psdHeaderInfo& header) {
152 if(header._Version == 1) {
153 BYTE Length[4];
154 io->read_proc(Length, sizeof(Length), 1, handle);
155 return psdGetLongValue(Length, sizeof(Length));
156 } else {
157 BYTE Length[8];
158 io->read_proc(Length, sizeof(Length), 1, handle);
159 return psdGetLongValue(Length, sizeof(Length));
160 }
161 }
162
163 // --------------------------------------------------------------------------
164
165 template <int N>
166 class PSDSetValue {
167 public:
set(BYTE * iprBuffer,int v)168 static inline void set(BYTE * iprBuffer, int v) {} // error
169 };
170
171 template <>
172 class PSDSetValue<1> {
173 public:
set(BYTE * iprBuffer,BYTE v)174 static inline void set(BYTE * iprBuffer, BYTE v) { iprBuffer[0] = v; }
175 };
176
177 template <>
178 class PSDSetValue<2> {
179 public:
set(BYTE * iprBuffer,WORD v)180 static inline void set(BYTE * iprBuffer, WORD v) {
181 #ifndef FREEIMAGE_BIGENDIAN
182 SwapShort(&v);
183 #endif
184 ((WORD*)iprBuffer)[0] = v;
185 }
186 };
187
188 template <>
189 class PSDSetValue<4> {
190 public:
set(const BYTE * iprBuffer,DWORD v)191 static inline void set(const BYTE * iprBuffer, DWORD v) {
192 #ifndef FREEIMAGE_BIGENDIAN
193 SwapLong(&v);
194 #endif
195 ((DWORD*)iprBuffer)[0] = v;
196 }
197 };
198
199 template <>
200 class PSDSetValue<8> {
201 public:
set(const BYTE * iprBuffer,UINT64 v)202 static inline void set(const BYTE * iprBuffer, UINT64 v) {
203 #ifndef FREEIMAGE_BIGENDIAN
204 SwapInt64(&v);
205 #endif
206 ((UINT64*)iprBuffer)[0] = v;
207 }
208 };
209
210 #define psdSetValue(PTR, SIZE, V) PSDSetValue<SIZE>::set((PTR), (V))
211 #define psdSetLongValue(PTR, SIZE, V) PSDSetValue<SIZE>::set((PTR), (V))
212
213 // --------------------------------------------------------------------------
214
215 static inline bool
psdWriteSize(FreeImageIO * io,fi_handle handle,const psdHeaderInfo & header,UINT64 v)216 psdWriteSize(FreeImageIO *io, fi_handle handle, const psdHeaderInfo& header, UINT64 v) {
217 if(header._Version == 1) {
218 BYTE Length[4];
219 psdSetLongValue(Length, sizeof(Length), (DWORD)v);
220 return (io->write_proc(Length, sizeof(Length), 1, handle) == 1);
221 } else {
222 BYTE Length[8];
223 psdSetLongValue(Length, sizeof(Length), v);
224 return (io->write_proc(Length, sizeof(Length), 1, handle) == 1);
225 }
226 }
227
228 /**
229 Return Exif metadata as a binary read-only buffer.
230 The buffer is owned by the function and MUST NOT be freed by the caller.
231 */
232 static BOOL
psd_write_exif_profile_raw(FIBITMAP * dib,BYTE ** profile,unsigned * profile_size)233 psd_write_exif_profile_raw(FIBITMAP *dib, BYTE **profile, unsigned *profile_size) {
234 // marker identifying string for Exif = "Exif\0\0"
235 // used by JPEG not PSD
236 BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
237
238 FITAG *tag_exif = NULL;
239 FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag_exif);
240
241 if(tag_exif) {
242 const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif);
243
244 // verify the identifying string
245 if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) {
246 // not an Exif profile
247 return FALSE;
248 }
249
250 *profile = (BYTE*)tag_value + sizeof(exif_signature);
251 *profile_size = (unsigned)FreeImage_GetTagLength(tag_exif) - sizeof(exif_signature);
252
253 return TRUE;
254 }
255
256 return FALSE;
257 }
258
259 static BOOL
psd_set_xmp_profile(FIBITMAP * dib,const BYTE * dataptr,unsigned int datalen)260 psd_set_xmp_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
261 // create a tag
262 FITAG *tag = FreeImage_CreateTag();
263 if (tag) {
264 FreeImage_SetTagID(tag, PSDP_RES_XMP);
265 FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
266 FreeImage_SetTagLength(tag, (DWORD)datalen);
267 FreeImage_SetTagCount(tag, (DWORD)datalen);
268 FreeImage_SetTagType(tag, FIDT_ASCII);
269 FreeImage_SetTagValue(tag, dataptr);
270
271 // store the tag
272 FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
273
274 // destroy the tag
275 FreeImage_DeleteTag(tag);
276 }
277
278 return TRUE;
279 }
280
281 /**
282 Return XMP metadata as a binary read-only buffer.
283 The buffer is owned by the function and MUST NOT be freed by the caller.
284 */
285 static BOOL
psd_get_xmp_profile(FIBITMAP * dib,BYTE ** profile,unsigned * profile_size)286 psd_get_xmp_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size) {
287 FITAG *tag_xmp = NULL;
288 FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp);
289
290 if(tag_xmp && (NULL != FreeImage_GetTagValue(tag_xmp))) {
291
292 *profile = (BYTE*)FreeImage_GetTagValue(tag_xmp);
293 *profile_size = (unsigned)FreeImage_GetTagLength(tag_xmp);
294
295 return TRUE;
296 }
297
298 return FALSE;
299 }
300
301 // --------------------------------------------------------------------------
302
psdHeaderInfo()303 psdHeaderInfo::psdHeaderInfo() : _Version(-1), _Channels(-1), _Height(-1), _Width(-1), _BitsPerChannel(-1), _ColourMode(-1) {
304 }
305
~psdHeaderInfo()306 psdHeaderInfo::~psdHeaderInfo() {
307 }
308
Read(FreeImageIO * io,fi_handle handle)309 bool psdHeaderInfo::Read(FreeImageIO *io, fi_handle handle) {
310 psdHeader header;
311
312 const int n = (int)io->read_proc(&header, sizeof(header), 1, handle);
313 if(!n) {
314 return false;
315 }
316
317 // check the signature
318 int nSignature = psdGetValue(header.Signature, sizeof(header.Signature));
319 if (PSD_SIGNATURE == nSignature) {
320 // check the version
321 short nVersion = (short)psdGetValue( header.Version, sizeof(header.Version) );
322 if (1 == nVersion || 2 == nVersion) {
323 _Version = nVersion;
324 // header.Reserved must be zero
325 BYTE psd_reserved[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
326 if(memcmp(header.Reserved, psd_reserved, 6) != 0) {
327 FreeImage_OutputMessageProc(FIF_PSD, "Warning: file header reserved member is not equal to zero");
328 }
329 // read the header
330 _Channels = (short)psdGetValue( header.Channels, sizeof(header.Channels) );
331 _Height = psdGetValue( header.Rows, sizeof(header.Rows) );
332 _Width = psdGetValue( header.Columns, sizeof(header.Columns) );
333 _BitsPerChannel = (short)psdGetValue( header.Depth, sizeof(header.Depth) );
334 _ColourMode = (short)psdGetValue( header.Mode, sizeof(header.Mode) );
335 if (_Version == 1 && (_Width > 30000 || _Height > 30000)) {
336 return false;
337 }
338
339 return true;
340 }
341 }
342
343 return false;
344 }
345
Write(FreeImageIO * io,fi_handle handle)346 bool psdHeaderInfo::Write(FreeImageIO *io, fi_handle handle) {
347 psdHeader header;
348
349 psdSetValue(header.Signature, sizeof(header.Signature), PSD_SIGNATURE);
350 psdSetValue(header.Version, sizeof(header.Version), _Version);
351 memset(header.Reserved, 0, sizeof(header.Reserved));
352 psdSetValue(header.Channels, sizeof(header.Channels), _Channels);
353 psdSetValue(header.Rows, sizeof(header.Rows), _Height);
354 psdSetValue(header.Columns, sizeof(header.Columns), _Width);
355 psdSetValue(header.Depth, sizeof(header.Depth), _BitsPerChannel);
356 psdSetValue(header.Mode, sizeof(header.Mode), _ColourMode);
357 return (io->write_proc(&header, sizeof(header), 1, handle) == 1);
358 }
359
360 // --------------------------------------------------------------------------
361
psdColourModeData()362 psdColourModeData::psdColourModeData() : _Length(-1), _plColourData(NULL) {
363 }
364
~psdColourModeData()365 psdColourModeData::~psdColourModeData() {
366 SAFE_DELETE_ARRAY(_plColourData);
367 }
368
Read(FreeImageIO * io,fi_handle handle)369 bool psdColourModeData::Read(FreeImageIO *io, fi_handle handle) {
370 if (0 < _Length) {
371 SAFE_DELETE_ARRAY(_plColourData);
372 }
373
374 BYTE Length[4];
375 io->read_proc(Length, sizeof(Length), 1, handle);
376
377 _Length = psdGetValue( Length, sizeof(_Length) );
378 if (0 < _Length) {
379 _plColourData = new BYTE[_Length];
380 io->read_proc(_plColourData, _Length, 1, handle);
381 }
382
383 return true;
384 }
385
Write(FreeImageIO * io,fi_handle handle)386 bool psdColourModeData::Write(FreeImageIO *io, fi_handle handle) {
387 if(io->write_proc(&_Length, sizeof(_Length), 1, handle) != 1) {
388 return false;
389 }
390 if(0 < _Length) {
391 if(io->write_proc(_plColourData, _Length, 1, handle) != 1) {
392 return false;
393 }
394 }
395 return true;
396 }
397
FillPalette(FIBITMAP * dib)398 bool psdColourModeData::FillPalette(FIBITMAP *dib) {
399 RGBQUAD *pal = FreeImage_GetPalette(dib);
400 if(pal) {
401 for (int i = 0; i < 256; i++) {
402 pal[i].rgbRed = _plColourData[i + 0*256];
403 pal[i].rgbGreen = _plColourData[i + 1*256];
404 pal[i].rgbBlue = _plColourData[i + 2*256];
405 }
406 return true;
407 }
408 return false;
409 }
410
411 // --------------------------------------------------------------------------
412
psdImageResource()413 psdImageResource::psdImageResource() : _plName (0) {
414 Reset();
415 }
416
~psdImageResource()417 psdImageResource::~psdImageResource() {
418 SAFE_DELETE_ARRAY(_plName);
419 }
420
Reset()421 void psdImageResource::Reset() {
422 _Length = -1;
423 memset( _OSType, '\0', sizeof(_OSType) );
424 _ID = -1;
425 SAFE_DELETE_ARRAY(_plName);
426 _Size = -1;
427 }
428
Write(FreeImageIO * io,fi_handle handle,int ID,int Size)429 bool psdImageResource::Write(FreeImageIO *io, fi_handle handle, int ID, int Size) {
430 BYTE ShortValue[2], IntValue[4];
431
432 _ID = ID;
433 _Size = Size;
434 psdSetValue((BYTE*)_OSType, sizeof(_OSType), PSD_RESOURCE);
435 if(io->write_proc(_OSType, sizeof(_OSType), 1, handle) != 1) {
436 return false;
437 }
438 psdSetValue(ShortValue, sizeof(ShortValue), _ID);
439 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
440 return false;
441 }
442 psdSetValue(ShortValue, sizeof(ShortValue), 0);
443 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
444 return false;
445 }
446 psdSetValue(IntValue, sizeof(IntValue), _Size);
447 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
448 return false;
449 }
450 return true;
451 }
452
453 // --------------------------------------------------------------------------
454
psdResolutionInfo()455 psdResolutionInfo::psdResolutionInfo() : _widthUnit(-1), _heightUnit(-1), _hRes(-1), _vRes(-1), _hResUnit(-1), _vResUnit(-1) {
456 }
457
~psdResolutionInfo()458 psdResolutionInfo::~psdResolutionInfo() {
459 }
460
Read(FreeImageIO * io,fi_handle handle)461 int psdResolutionInfo::Read(FreeImageIO *io, fi_handle handle) {
462 BYTE IntValue[4], ShortValue[2];
463 int nBytes=0, n;
464
465 // Horizontal resolution in pixels per inch.
466 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
467 nBytes += n * sizeof(ShortValue);
468 _hRes = (short)psdGetValue(ShortValue, sizeof(_hRes) );
469
470 // 1=display horizontal resolution in pixels per inch; 2=display horizontal resolution in pixels per cm.
471 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
472 nBytes += n * sizeof(IntValue);
473 _hResUnit = psdGetValue(IntValue, sizeof(_hResUnit) );
474
475 // Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
476 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
477 nBytes += n * sizeof(ShortValue);
478 _widthUnit = (short)psdGetValue(ShortValue, sizeof(_widthUnit) );
479
480 // Vertical resolution in pixels per inch.
481 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
482 nBytes += n * sizeof(ShortValue);
483 _vRes = (short)psdGetValue(ShortValue, sizeof(_vRes) );
484
485 // 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm.
486 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
487 nBytes += n * sizeof(IntValue);
488 _vResUnit = psdGetValue(IntValue, sizeof(_vResUnit) );
489
490 // Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
491 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
492 nBytes += n * sizeof(ShortValue);
493 _heightUnit = (short)psdGetValue(ShortValue, sizeof(_heightUnit) );
494
495 return nBytes;
496 }
497
Write(FreeImageIO * io,fi_handle handle)498 bool psdResolutionInfo::Write(FreeImageIO *io, fi_handle handle) {
499 BYTE IntValue[4], ShortValue[2];
500
501 if (!psdImageResource().Write(io, handle, PSDP_RES_RESOLUTION_INFO, 16)) {
502 return false;
503 }
504
505 // Horizontal resolution in pixels per inch.
506 psdSetValue(ShortValue, sizeof(ShortValue), _hRes);
507 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
508 return false;
509 }
510
511 // 1=display horizontal resolution in pixels per inch; 2=display horizontal resolution in pixels per cm.
512 psdSetValue(IntValue, sizeof(IntValue), _hResUnit);
513 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
514 return false;
515 }
516
517 // Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
518 psdSetValue(ShortValue, sizeof(ShortValue), _widthUnit);
519 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
520 return false;
521 }
522
523 // Vertical resolution in pixels per inch.
524 psdSetValue(ShortValue, sizeof(ShortValue), _vRes);
525 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
526 return false;
527 }
528
529 // 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm.
530 psdSetValue(IntValue, sizeof(IntValue), _vResUnit);
531 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
532 return false;
533 }
534
535 // Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
536 psdSetValue(ShortValue, sizeof(ShortValue), _heightUnit);
537 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
538 return false;
539 }
540
541 return true;
542 }
543
GetResolutionInfo(unsigned & res_x,unsigned & res_y)544 void psdResolutionInfo::GetResolutionInfo(unsigned &res_x, unsigned &res_y) {
545 if(_hResUnit == 1) {
546 // convert pixels / inch to pixel / m
547 res_x = (unsigned) (_hRes / 0.0254000 + 0.5);
548 } else if(_hResUnit == 2) {
549 // convert pixels / cm to pixel / m
550 res_x = (unsigned) (_hRes * 100.0 + 0.5);
551 }
552
553 if(_vResUnit == 1) {
554 // convert pixels / inch to pixel / m
555 res_y = (unsigned) (_vRes / 0.0254000 + 0.5);
556 } else if(_vResUnit == 2) {
557 // convert pixels / cm to pixel / m
558 res_y = (unsigned) (_vRes * 100.0 + 0.5);
559 }
560 }
561
562 // --------------------------------------------------------------------------
563
psdResolutionInfo_v2()564 psdResolutionInfo_v2::psdResolutionInfo_v2() {
565 _Channels = _Rows = _Columns = _Depth = _Mode = -1;
566 }
567
~psdResolutionInfo_v2()568 psdResolutionInfo_v2::~psdResolutionInfo_v2() {
569 }
570
Read(FreeImageIO * io,fi_handle handle)571 int psdResolutionInfo_v2::Read(FreeImageIO *io, fi_handle handle) {
572 BYTE ShortValue[2];
573 int nBytes=0, n;
574
575 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
576 nBytes += n * sizeof(ShortValue);
577 _Channels = (short)psdGetValue(ShortValue, sizeof(_Channels) );
578
579 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
580 nBytes += n * sizeof(ShortValue);
581 _Rows = (short)psdGetValue(ShortValue, sizeof(_Rows) );
582
583 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
584 nBytes += n * sizeof(ShortValue);
585 _Columns = (short)psdGetValue(ShortValue, sizeof(_Columns) );
586
587 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
588 nBytes += n * sizeof(ShortValue);
589 _Depth = (short)psdGetValue(ShortValue, sizeof(_Depth) );
590
591 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
592 nBytes += n * sizeof(ShortValue);
593 _Mode = (short)psdGetValue(ShortValue, sizeof(_Mode) );
594
595 return nBytes;
596 }
597
Write(FreeImageIO * io,fi_handle handle)598 bool psdResolutionInfo_v2::Write(FreeImageIO *io, fi_handle handle) {
599 BYTE ShortValue[2];
600
601 if(!psdImageResource().Write(io, handle, PSDP_RES_RESOLUTION_INFO_V2, 10))
602 return false;
603
604 psdSetValue(ShortValue, sizeof(ShortValue), _Channels);
605 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
606 return false;
607 }
608 psdSetValue(ShortValue, sizeof(ShortValue), _Rows);
609 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
610 return false;
611 }
612 psdSetValue(ShortValue, sizeof(ShortValue), _Columns);
613 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
614 return false;
615 }
616 psdSetValue(ShortValue, sizeof(ShortValue), _Depth);
617 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
618 return false;
619 }
620 psdSetValue(ShortValue, sizeof(ShortValue), _Mode);
621 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
622 return false;
623 }
624
625 return true;
626 }
627
628 // --------------------------------------------------------------------------
629
psdDisplayInfo()630 psdDisplayInfo::psdDisplayInfo() {
631 _Opacity = _ColourSpace = -1;
632 for (unsigned n = 0; n < 4; ++n) {
633 _Colour[n] = 0;
634 }
635 _Kind = 0;
636 _padding = '0';
637 }
638
~psdDisplayInfo()639 psdDisplayInfo::~psdDisplayInfo() {
640 }
641
Read(FreeImageIO * io,fi_handle handle)642 int psdDisplayInfo::Read(FreeImageIO *io, fi_handle handle) {
643 BYTE ShortValue[2];
644 int nBytes=0, n;
645
646 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
647 nBytes += n * sizeof(ShortValue);
648 _ColourSpace = (short)psdGetValue(ShortValue, sizeof(_ColourSpace) );
649
650 for (unsigned i = 0; i < 4; ++i) {
651 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
652 nBytes += n * sizeof(ShortValue);
653 _Colour[i] = (short)psdGetValue(ShortValue, sizeof(_Colour[i]) );
654 }
655
656 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
657 nBytes += n * sizeof(ShortValue);
658 _Opacity = (short)psdGetValue(ShortValue, sizeof(_Opacity) );
659 if((_Opacity < 0) || (_Opacity > 100)) {
660 throw "Invalid DisplayInfo::Opacity value";
661 }
662
663 BYTE c[1];
664 n = (int)io->read_proc(c, sizeof(c), 1, handle);
665 nBytes += n * sizeof(c);
666 _Kind = (BYTE)psdGetValue(c, sizeof(c));
667
668 n = (int)io->read_proc(c, sizeof(c), 1, handle);
669 nBytes += n * sizeof(c);
670
671 _padding = (BYTE)psdGetValue(c, sizeof(c));
672 if(_padding != 0) {
673 throw "Invalid DisplayInfo::Padding value";
674 }
675
676 return nBytes;
677 }
678
Write(FreeImageIO * io,fi_handle handle)679 bool psdDisplayInfo::Write(FreeImageIO *io, fi_handle handle) {
680 BYTE ShortValue[2];
681
682 if(!psdImageResource().Write(io, handle, PSDP_RES_DISPLAY_INFO, 14))
683 return false;
684
685 psdSetValue(ShortValue, sizeof(ShortValue), _ColourSpace);
686 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
687 return false;
688 }
689 for (unsigned i = 0; i < 4; ++i) {
690 psdSetValue(ShortValue, sizeof(ShortValue), _Colour[i]);
691 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
692 return false;
693 }
694 }
695 psdSetValue(ShortValue, sizeof(ShortValue), _Opacity);
696 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
697 return false;
698 }
699 BYTE c[1];
700 psdSetValue(c, sizeof(c), _Kind);
701 if(io->write_proc(c, sizeof(c), 1, handle) != 1) {
702 return false;
703 }
704 psdSetValue(c, sizeof(c), 0);
705 if(io->write_proc(c, sizeof(c), 1, handle) != 1) {
706 return false;
707 }
708
709 return true;
710 }
711
712 // --------------------------------------------------------------------------
713
psdThumbnail()714 psdThumbnail::psdThumbnail() :
715 _Format(-1), _Width(-1), _Height(-1), _WidthBytes(-1), _Size(-1), _CompressedSize(-1), _BitPerPixel(-1), _Planes(-1), _dib(NULL), _owned(true) {
716 }
717
~psdThumbnail()718 psdThumbnail::~psdThumbnail() {
719 if (_owned) FreeImage_Unload(_dib);
720 }
721
722 void
Init()723 psdThumbnail::Init() {
724 if (_dib != NULL) {
725 _Format = 1;
726 _Width = (int)FreeImage_GetWidth(_dib);
727 _Height = (int)FreeImage_GetHeight(_dib);
728 _BitPerPixel = 24;
729 _Planes = 1;
730 _WidthBytes = (_Width * _BitPerPixel + 31) / 32 * 4;
731 _Size = _WidthBytes * _Height * _Planes;
732 _CompressedSize = _Size;
733 }
734 }
735
Read(FreeImageIO * io,fi_handle handle,int iResourceSize,bool isBGR)736 int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR) {
737 BYTE ShortValue[2], IntValue[4];
738 int nBytes=0, n;
739
740 // remove the header size (28 bytes) from the total data size
741 int iTotalData = iResourceSize - 28;
742
743 const long block_end = io->tell_proc(handle) + iTotalData;
744
745 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
746 nBytes += n * sizeof(IntValue);
747 _Format = psdGetValue(IntValue, sizeof(_Format) );
748
749 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
750 nBytes += n * sizeof(IntValue);
751 _Width = psdGetValue(IntValue, sizeof(_Width) );
752
753 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
754 nBytes += n * sizeof(IntValue);
755 _Height = psdGetValue(IntValue, sizeof(_Height) );
756
757 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
758 nBytes += n * sizeof(IntValue);
759 _WidthBytes = psdGetValue(IntValue, sizeof(_WidthBytes) );
760
761 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
762 nBytes += n * sizeof(IntValue);
763 _Size = psdGetValue(IntValue, sizeof(_Size) );
764
765 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
766 nBytes += n * sizeof(IntValue);
767 _CompressedSize = psdGetValue(IntValue, sizeof(_CompressedSize) );
768
769 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
770 nBytes += n * sizeof(ShortValue);
771 _BitPerPixel = (short)psdGetValue(ShortValue, sizeof(_BitPerPixel) );
772
773 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
774 nBytes += n * sizeof(ShortValue);
775 _Planes = (short)psdGetValue(ShortValue, sizeof(_Planes) );
776
777 const long JFIF_startpos = io->tell_proc(handle);
778
779 if(_dib) {
780 FreeImage_Unload(_dib);
781 }
782
783 if(_Format == 1) {
784 // kJpegRGB thumbnail image
785 _dib = FreeImage_LoadFromHandle(FIF_JPEG, io, handle);
786 if(isBGR) {
787 SwapRedBlue32(_dib);
788 }
789 // HACK: manually go to end of thumbnail, because (for some reason) LoadFromHandle consumes more bytes then available!
790 io->seek_proc(handle, block_end, SEEK_SET);
791 }
792 else {
793 // kRawRGB thumbnail image
794 _dib = FreeImage_Allocate(_Width, _Height, _BitPerPixel);
795 BYTE* dst_line_start = FreeImage_GetScanLine(_dib, _Height - 1);//<*** flipped
796 BYTE* line_start = new BYTE[_WidthBytes];
797 const unsigned dstLineSize = FreeImage_GetPitch(_dib);
798 for(unsigned h = 0; h < (unsigned)_Height; ++h, dst_line_start -= dstLineSize) {//<*** flipped
799 io->read_proc(line_start, _WidthBytes, 1, handle);
800 iTotalData -= _WidthBytes;
801 memcpy(dst_line_start, line_start, _Width * _BitPerPixel / 8);
802 }
803 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
804 SwapRedBlue32(_dib);
805 #endif
806 SAFE_DELETE_ARRAY(line_start);
807
808 // skip any remaining data
809 io->seek_proc(handle, iTotalData, SEEK_CUR);
810 return iResourceSize;
811 }
812
813 nBytes += (block_end - JFIF_startpos);
814
815 return nBytes;
816 }
817
Write(FreeImageIO * io,fi_handle handle,bool isBGR)818 bool psdThumbnail::Write(FreeImageIO *io, fi_handle handle, bool isBGR) {
819 BYTE ShortValue[2], IntValue[4];
820
821 const long res_start_pos = io->tell_proc(handle);
822 const int ID = isBGR ? PSDP_RES_THUMBNAIL_PS4 : PSDP_RES_THUMBNAIL;
823 if(!psdImageResource().Write(io, handle, ID, 0))
824 return false;
825
826 psdSetValue(IntValue, sizeof(IntValue), _Format);
827 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
828 return false;
829 }
830 psdSetValue(IntValue, sizeof(IntValue), _Width);
831 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
832 return false;
833 }
834 psdSetValue(IntValue, sizeof(IntValue), _Height);
835 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
836 return false;
837 }
838 psdSetValue(IntValue, sizeof(IntValue), _WidthBytes);
839 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
840 return false;
841 }
842 psdSetValue(IntValue, sizeof(IntValue), _Size);
843 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
844 return false;
845 }
846 const long compressed_pos = io->tell_proc(handle);
847 psdSetValue(IntValue, sizeof(IntValue), _CompressedSize);
848 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
849 return false;
850 }
851 psdSetValue(ShortValue, sizeof(ShortValue), _BitPerPixel);
852 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
853 return false;
854 }
855 psdSetValue(ShortValue, sizeof(ShortValue), _Planes);
856 if(io->write_proc(ShortValue, sizeof(ShortValue), 1, handle) != 1) {
857 return false;
858 }
859 if(_Format == 1) {
860 // kJpegRGB thumbnail image
861 if(isBGR) {
862 SwapRedBlue32(_dib);
863 }
864 const long start_pos = io->tell_proc(handle);
865 FreeImage_SaveToHandle(FIF_JPEG, _dib, io, handle, JPEG_DEFAULT);
866 const long current_pos = io->tell_proc(handle);
867 _CompressedSize = (int)(current_pos - start_pos);
868 io->seek_proc(handle, compressed_pos, SEEK_SET);
869 psdSetValue(IntValue, sizeof(IntValue), _CompressedSize);
870 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
871 return false;
872 }
873 io->seek_proc(handle, current_pos, SEEK_SET);
874 }
875 else {
876 // kRawRGB thumbnail image
877 // ### Unimplemented (should be trivial)
878 _CompressedSize = 0;
879 }
880
881 int len = 28 + _CompressedSize;
882
883 // Fix length of resource
884 io->seek_proc(handle, res_start_pos + 8, SEEK_SET);
885 psdSetValue(IntValue, sizeof(IntValue), len);
886 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
887 return false;
888 }
889 io->seek_proc(handle, 0, SEEK_END);
890
891 if((len % 2) != 0) {
892 BYTE data[1];
893 data[0] = 0;
894 if(io->write_proc(data, sizeof(data), 1, handle) != 1) {
895 return false;
896 }
897 }
898
899 return true;
900 }
901
902 //---------------------------------------------------------------------------
903
psdICCProfile()904 psdICCProfile::psdICCProfile() : _ProfileSize(0), _ProfileData(NULL), _owned(true) {
905 }
906
~psdICCProfile()907 psdICCProfile::~psdICCProfile() {
908 clear();
909 }
910
clear()911 void psdICCProfile::clear() { if (_owned) { SAFE_DELETE_ARRAY(_ProfileData); } else { _ProfileData = NULL; } _ProfileSize = 0;}
912
Read(FreeImageIO * io,fi_handle handle,int size)913 int psdICCProfile::Read(FreeImageIO *io, fi_handle handle, int size) {
914 int nBytes = 0, n;
915
916 clear();
917
918 _ProfileData = new (std::nothrow) BYTE[size];
919 if(NULL != _ProfileData) {
920 n = (int)io->read_proc(_ProfileData, 1, size, handle);
921 _ProfileSize = size;
922 nBytes += n * sizeof(BYTE);
923 }
924
925 return nBytes;
926 }
927
Write(FreeImageIO * io,fi_handle handle)928 bool psdICCProfile::Write(FreeImageIO *io, fi_handle handle) {
929 if(!psdImageResource().Write(io, handle, PSDP_RES_ICC_PROFILE, _ProfileSize))
930 return false;
931
932 if(NULL != _ProfileData) {
933 if(io->write_proc(_ProfileData, 1, _ProfileSize, handle) != _ProfileSize) {
934 return false;
935 }
936 if((_ProfileSize % 2) != 0) {
937 BYTE data[1];
938 data[0] = 0;
939 if(io->write_proc(data, sizeof(data), 1, handle) != 1) {
940 return false;
941 }
942 }
943 }
944
945 return true;
946 }
947
948 //---------------------------------------------------------------------------
949
psdData()950 psdData::psdData() : _Size(0), _Data(NULL), _owned(true) {
951 }
952
~psdData()953 psdData::~psdData() {
954 clear();
955 }
956
clear()957 void psdData::clear() { if (_owned) { SAFE_DELETE_ARRAY(_Data); } else { _Data = NULL; } _Size = 0;}
958
Read(FreeImageIO * io,fi_handle handle,int size)959 int psdData::Read(FreeImageIO *io, fi_handle handle, int size) {
960 int nBytes = 0, n;
961
962 clear();
963
964 _Data = new (std::nothrow) BYTE[size];
965 if(NULL != _Data) {
966 n = (int)io->read_proc(_Data, 1, size, handle);
967 _Size = (unsigned)size;
968 nBytes += n * sizeof(BYTE);
969 }
970
971 return nBytes;
972 }
973
Write(FreeImageIO * io,fi_handle handle,int ID)974 bool psdData::Write(FreeImageIO *io, fi_handle handle, int ID) {
975 if(!psdImageResource().Write(io, handle, ID, _Size))
976 return false;
977
978 if(NULL != _Data) {
979 if(io->write_proc(_Data, 1, _Size, handle) != _Size) {
980 return false;
981 }
982 if((_Size % 2) != 0) {
983 BYTE data[1];
984 data[0] = 0;
985 if(io->write_proc(data, sizeof(data), 1, handle) != 1) {
986 return false;
987 }
988 }
989 }
990
991 return true;
992 }
993
994 //---------------------------------------------------------------------------
995
996 /**
997 Invert only color components, skipping Alpha/Black
998 (Can be useful as public/utility function)
999 */
1000 static
invertColor(FIBITMAP * dib)1001 BOOL invertColor(FIBITMAP* dib) {
1002 FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib);
1003 const unsigned Bpp = FreeImage_GetBPP(dib)/8;
1004
1005 if((type == FIT_BITMAP && Bpp == 4) || type == FIT_RGBA16) {
1006 const unsigned width = FreeImage_GetWidth(dib);
1007 const unsigned height = FreeImage_GetHeight(dib);
1008 BYTE *line_start = FreeImage_GetScanLine(dib, 0);
1009 const unsigned pitch = FreeImage_GetPitch(dib);
1010 const unsigned triBpp = Bpp - (Bpp == 4 ? 1 : 2);
1011
1012 for(unsigned y = 0; y < height; y++) {
1013 BYTE *line = line_start;
1014
1015 for(unsigned x = 0; x < width; x++) {
1016 for(unsigned b=0; b < triBpp; ++b) {
1017 line[b] = ~line[b];
1018 }
1019
1020 line += Bpp;
1021 }
1022 line_start += pitch;
1023 }
1024
1025 return TRUE;
1026 }
1027 else {
1028 return FreeImage_Invert(dib);
1029 }
1030 }
1031
1032 //---------------------------------------------------------------------------
1033
psdParser()1034 psdParser::psdParser() {
1035 _bThumbnailFilled = false;
1036 _bDisplayInfoFilled = false;
1037 _bResolutionInfoFilled = false;
1038 _bResolutionInfoFilled_v2 = false;
1039 _bCopyright = false;
1040 _GlobalAngle = 30;
1041 _ColourCount = -1;
1042 _TransparentIndex = -1;
1043 _fi_flags = 0;
1044 _fi_format_id = FIF_UNKNOWN;
1045 }
1046
~psdParser()1047 psdParser::~psdParser() {
1048 }
1049
GetChannelOffset(FIBITMAP * bitmap,unsigned c) const1050 unsigned psdParser::GetChannelOffset(FIBITMAP* bitmap, unsigned c) const {
1051 unsigned channelOffset = c;
1052 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
1053 // Swap R/B indices for BGR -> RGB
1054 if(FreeImage_GetImageType(bitmap) == FIT_BITMAP &&
1055 _headerInfo._ColourMode == PSDP_RGB &&
1056 (c == 0 || c == 2)) {
1057 channelOffset = (2 - c);
1058 }
1059 #endif
1060 return channelOffset;
1061 }
1062
ReadLayerAndMaskInfoSection(FreeImageIO * io,fi_handle handle)1063 bool psdParser::ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle) {
1064 bool bSuccess = true;
1065
1066 UINT64 nTotalBytes = psdReadSize(io, handle, _headerInfo);
1067
1068 // Hack to handle large PSB files without using fseeko().
1069 if (sizeof(long) < sizeof(UINT64)) {
1070 const long offset = 0x10000000;
1071 while (nTotalBytes > offset) {
1072 if (io->seek_proc(handle, offset, SEEK_CUR) != 0) {
1073 bSuccess = false;
1074 break;
1075 }
1076 nTotalBytes -= offset;
1077 }
1078 }
1079 if (bSuccess && nTotalBytes > 0) {
1080 if (io->seek_proc(handle, (long)nTotalBytes, SEEK_CUR) != 0)
1081 bSuccess = false;
1082 }
1083
1084 return bSuccess;
1085 }
1086
ReadImageResources(FreeImageIO * io,fi_handle handle,LONG length)1087 bool psdParser::ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length) {
1088 psdImageResource oResource;
1089 bool bSuccess = false;
1090
1091 if(length > 0) {
1092 oResource._Length = length;
1093 } else {
1094 BYTE Length[4];
1095 int n = (int)io->read_proc(Length, sizeof(Length), 1, handle);
1096
1097 oResource._Length = psdGetValue( Length, sizeof(oResource._Length) );
1098 }
1099
1100 int nBytes = 0;
1101 int nTotalBytes = oResource._Length;
1102
1103 while(nBytes < nTotalBytes) {
1104 int n = 0;
1105 oResource.Reset();
1106
1107 n = (int)io->read_proc(oResource._OSType, sizeof(oResource._OSType), 1, handle);
1108 if(n != 1) {
1109 FreeImage_OutputMessageProc(_fi_format_id, "This file contains damaged data causing an unexpected end-of-file - stop reading resources");
1110 return false;
1111 }
1112 nBytes += n * sizeof(oResource._OSType);
1113
1114 if( (nBytes % 2) != 0 ) {
1115 return false;
1116 }
1117
1118 int nOSType = psdGetValue((BYTE*)&oResource._OSType, sizeof(oResource._OSType));
1119
1120 if ( PSD_RESOURCE == nOSType ) {
1121 BYTE ID[2];
1122 n = (int)io->read_proc(ID, sizeof(ID), 1, handle);
1123 nBytes += n * sizeof(ID);
1124
1125 oResource._ID = (short)psdGetValue( ID, sizeof(ID) );
1126
1127 BYTE SizeOfName;
1128 n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle);
1129 nBytes += n * sizeof(SizeOfName);
1130
1131 int nSizeOfName = psdGetValue( &SizeOfName, sizeof(SizeOfName) );
1132 if ( 0 < nSizeOfName ) {
1133 oResource._plName = new BYTE[nSizeOfName];
1134 n = (int)io->read_proc(oResource._plName, nSizeOfName, 1, handle);
1135 nBytes += n * nSizeOfName;
1136 }
1137
1138 if ( 0 == (nSizeOfName % 2) ) {
1139 n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle);
1140 nBytes += n * sizeof(SizeOfName);
1141 }
1142
1143 BYTE Size[4];
1144 n = (int)io->read_proc(Size, sizeof(Size), 1, handle);
1145 nBytes += n * sizeof(Size);
1146
1147 oResource._Size = psdGetValue( Size, sizeof(oResource._Size) );
1148
1149 if ( 0 != (oResource._Size % 2) ) {
1150 // resource data must be even
1151 oResource._Size++;
1152 }
1153 if ( 0 < oResource._Size ) {
1154 BYTE IntValue[4];
1155 BYTE ShortValue[2];
1156
1157 switch( oResource._ID ) {
1158 case PSDP_RES_RESOLUTION_INFO_V2:
1159 // Obsolete - Photoshop 2.0
1160 _bResolutionInfoFilled_v2 = true;
1161 nBytes += _resolutionInfo_v2.Read(io, handle);
1162 break;
1163
1164 // ResolutionInfo structure
1165 case PSDP_RES_RESOLUTION_INFO:
1166 _bResolutionInfoFilled = true;
1167 nBytes += _resolutionInfo.Read(io, handle);
1168 break;
1169
1170 // DisplayInfo structure
1171 case PSDP_RES_DISPLAY_INFO:
1172 _bDisplayInfoFilled = true;
1173 nBytes += _displayInfo.Read(io, handle);
1174 break;
1175
1176 // IPTC-NAA record
1177 case PSDP_RES_IPTC_NAA:
1178 nBytes += _iptc.Read(io, handle, oResource._Size);
1179 break;
1180 // (Photoshop 4.0) Copyright flag
1181 // Boolean indicating whether image is copyrighted. Can be set via Property suite or by user in File Info...
1182 case PSDP_RES_COPYRIGHT:
1183 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
1184 nBytes += n * sizeof(ShortValue);
1185 _bCopyright = (1 == psdGetValue(ShortValue, sizeof(ShortValue)));
1186 break;
1187
1188 // (Photoshop 4.0) Thumbnail resource for Photoshop 4.0 only
1189 case PSDP_RES_THUMBNAIL_PS4:
1190 // (Photoshop 5.0) Thumbnail resource (supersedes resource 1033)
1191 case PSDP_RES_THUMBNAIL:
1192 {
1193 _bThumbnailFilled = true;
1194 bool bBGR = (PSDP_RES_THUMBNAIL_PS4 == oResource._ID);
1195 nBytes += _thumbnail.Read(io, handle, oResource._Size, bBGR);
1196 break;
1197 }
1198
1199 // (Photoshop 5.0) Global Angle
1200 // 4 bytes that contain an integer between 0 and 359, which is the global
1201 // lighting angle for effects layer. If not present, assumed to be 30.
1202 case PSDP_RES_GLOBAL_ANGLE:
1203 n = (int)io->read_proc(IntValue, sizeof(IntValue), 1, handle);
1204 nBytes += n * sizeof(IntValue);
1205 _GlobalAngle = psdGetValue(IntValue, sizeof(_GlobalAngle) );
1206 break;
1207
1208 // ICC profile
1209 case PSDP_RES_ICC_PROFILE:
1210 nBytes += _iccProfile.Read(io, handle, oResource._Size);
1211 break;
1212
1213 // (Photoshop 6.0) Indexed Color Table Count
1214 // 2 bytes for the number of colors in table that are actually defined
1215 case PSDP_RES_INDEXED_COLORS:
1216 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
1217 nBytes += n * sizeof(ShortValue);
1218 _ColourCount = (short)psdGetValue(ShortValue, sizeof(ShortValue) );
1219 break;
1220
1221 // (Photoshop 6.0) Transparency Index.
1222 // 2 bytes for the index of transparent color, if any.
1223 case PSDP_RES_TRANSPARENCY_INDEX:
1224 n = (int)io->read_proc(ShortValue, sizeof(ShortValue), 1, handle);
1225 nBytes += n * sizeof(ShortValue);
1226 _TransparentIndex = (short)psdGetValue(ShortValue, sizeof(ShortValue) );
1227 break;
1228
1229 // (Photoshop 7.0) EXIF data 1
1230 case PSDP_RES_EXIF1:
1231 nBytes += _exif1.Read(io, handle, oResource._Size);
1232 break;
1233 // (Photoshop 7.0) EXIF data 3
1234 case PSDP_RES_EXIF3:
1235 nBytes += _exif3.Read(io, handle, oResource._Size);
1236 break;
1237 // (Photoshop 7.0) XMP metadata
1238 case PSDP_RES_XMP:
1239 nBytes += _xmp.Read(io, handle, oResource._Size);
1240 break;
1241 default:
1242 {
1243 // skip resource
1244 unsigned skip_length = MIN(oResource._Size, nTotalBytes - nBytes);
1245 io->seek_proc(handle, skip_length, SEEK_CUR);
1246 nBytes += skip_length;
1247 }
1248 break;
1249 }
1250 }
1251 }
1252 }
1253
1254 if (nBytes == nTotalBytes) {
1255 bSuccess = true;
1256 }
1257
1258 return bSuccess;
1259
1260 }
1261
ReadImageLine(BYTE * dst,const BYTE * src,unsigned lineSize,unsigned dstBpp,unsigned bytes)1262 void psdParser::ReadImageLine(BYTE* dst, const BYTE* src, unsigned lineSize, unsigned dstBpp, unsigned bytes) {
1263 switch (bytes) {
1264 case 4:
1265 {
1266 DWORD* d = (DWORD*)dst;
1267 const DWORD* s = (const DWORD*)src;
1268 dstBpp /= 4;
1269 while (lineSize > 0) {
1270 DWORD v = *s++;
1271 #ifndef FREEIMAGE_BIGENDIAN
1272 SwapLong(&v);
1273 #endif
1274 *d = v;
1275 d += dstBpp;
1276 lineSize -= 4;
1277 }
1278 break;
1279 }
1280 case 2:
1281 {
1282 WORD* d = (WORD*)dst;
1283 const WORD* s = (const WORD*)src;
1284 dstBpp /= 2;
1285 while (lineSize > 0) {
1286 WORD v = *s++;
1287 #ifndef FREEIMAGE_BIGENDIAN
1288 SwapShort(&v);
1289 #endif
1290 *d = v;
1291 d += dstBpp;
1292 lineSize -= 2;
1293 }
1294 break;
1295 }
1296 default:
1297 if (dstBpp == 1) {
1298 memcpy(dst, src, lineSize);
1299 } else {
1300 while (lineSize > 0) {
1301 *dst = *src++;
1302 dst += dstBpp;
1303 lineSize--;
1304 }
1305 }
1306 break;
1307 }
1308 }
1309
UnpackRLE(BYTE * line,const BYTE * rle_line,BYTE * line_end,unsigned srcSize)1310 void psdParser::UnpackRLE(BYTE* line, const BYTE* rle_line, BYTE* line_end, unsigned srcSize) {
1311 while (srcSize > 0) {
1312
1313 int len = *rle_line++;
1314 srcSize--;
1315
1316 // NOTE len is signed byte in PackBits RLE
1317
1318 if ( len < 128 ) { //<- MSB is not set
1319 // uncompressed packet
1320
1321 // (len + 1) bytes of data are copied
1322 ++len;
1323
1324 // assert we don't write beyound eol
1325 memcpy(line, rle_line, line + len > line_end ? line_end - line : len);
1326 line += len;
1327 rle_line += len;
1328 srcSize -= len;
1329 }
1330 else if ( len > 128 ) { //< MSB is set
1331 // RLE compressed packet
1332
1333 // One byte of data is repeated (–len + 1) times
1334
1335 len ^= 0xFF; // same as (-len + 1) & 0xFF
1336 len += 2; //
1337
1338 // assert we don't write beyound eol
1339 memset(line, *rle_line++, line + len > line_end ? line_end - line : len);
1340 line += len;
1341 srcSize--;
1342 }
1343 else if ( 128 == len ) {
1344 // Do nothing
1345 }
1346 }//< rle_line
1347 }
1348
ReadImageData(FreeImageIO * io,fi_handle handle)1349 FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) {
1350 if (handle == NULL) {
1351 return NULL;
1352 }
1353
1354 bool header_only = (_fi_flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
1355
1356 WORD nCompression = 0;
1357 if (io->read_proc(&nCompression, sizeof(nCompression), 1, handle) != 1) {
1358 return NULL;
1359 }
1360
1361 #ifndef FREEIMAGE_BIGENDIAN
1362 SwapShort(&nCompression);
1363 #endif
1364
1365 // PSDP_COMPRESSION_ZIP and PSDP_COMPRESSION_ZIP_PREDICTION
1366 // are only valid for layer data, not the composited data.
1367 if(nCompression != PSDP_COMPRESSION_NONE &&
1368 nCompression != PSDP_COMPRESSION_RLE) {
1369 FreeImage_OutputMessageProc(_fi_format_id, "Unsupported compression %d", nCompression);
1370 return NULL;
1371 }
1372
1373 const unsigned nWidth = _headerInfo._Width;
1374 const unsigned nHeight = _headerInfo._Height;
1375 const unsigned nChannels = _headerInfo._Channels;
1376 const unsigned depth = _headerInfo._BitsPerChannel;
1377 const unsigned bytes = (depth == 1) ? 1 : depth / 8;
1378
1379 // channel(plane) line (BYTE aligned)
1380 const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes;
1381
1382 if(nCompression == PSDP_COMPRESSION_RLE && depth > 16) {
1383 FreeImage_OutputMessageProc(_fi_format_id, "Unsupported RLE with depth %d", depth);
1384 return NULL;
1385 }
1386
1387 // build output buffer
1388
1389 FIBITMAP* bitmap = NULL;
1390 unsigned dstCh = 0;
1391
1392 short mode = _headerInfo._ColourMode;
1393
1394 if(mode == PSDP_MULTICHANNEL && nChannels < 3) {
1395 // CM
1396 mode = PSDP_GRAYSCALE; // C as gray, M as extra channel
1397 }
1398
1399 bool needPalette = false;
1400 switch (mode) {
1401 case PSDP_BITMAP:
1402 case PSDP_DUOTONE:
1403 case PSDP_INDEXED:
1404 case PSDP_GRAYSCALE:
1405 dstCh = 1;
1406 switch(depth) {
1407 case 16:
1408 bitmap = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, nWidth, nHeight, depth*dstCh);
1409 break;
1410 case 32:
1411 bitmap = FreeImage_AllocateHeaderT(header_only, FIT_FLOAT, nWidth, nHeight, depth*dstCh);
1412 break;
1413 default: // 1-, 8-
1414 needPalette = true;
1415 bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh);
1416 break;
1417 }
1418 break;
1419 case PSDP_RGB:
1420 case PSDP_LAB:
1421 case PSDP_CMYK :
1422 case PSDP_MULTICHANNEL :
1423 // force PSDP_MULTICHANNEL CMY as CMYK
1424 dstCh = (mode == PSDP_MULTICHANNEL && !header_only) ? 4 : MIN<unsigned>(nChannels, 4);
1425 if(dstCh < 3) {
1426 throw "Invalid number of channels";
1427 }
1428
1429 switch(depth) {
1430 case 16:
1431 bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGB16 : FIT_RGBA16, nWidth, nHeight, depth*dstCh);
1432 break;
1433 case 32:
1434 bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGBF : FIT_RGBAF, nWidth, nHeight, depth*dstCh);
1435 break;
1436 default:
1437 bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh);
1438 break;
1439 }
1440 break;
1441 default:
1442 throw "Unsupported color mode";
1443 break;
1444 }
1445 if(!bitmap) {
1446 throw FI_MSG_ERROR_DIB_MEMORY;
1447 }
1448
1449 // write thumbnail
1450 FreeImage_SetThumbnail(bitmap, _thumbnail.getDib());
1451
1452 // @todo Add some metadata model
1453
1454 if(header_only) {
1455 return bitmap;
1456 }
1457
1458 // Load pixels data
1459
1460 const unsigned dstChannels = dstCh;
1461
1462 const unsigned dstBpp = (depth == 1) ? 1 : FreeImage_GetBPP(bitmap)/8;
1463 const unsigned dstLineSize = FreeImage_GetPitch(bitmap);
1464 BYTE* const dst_first_line = FreeImage_GetScanLine(bitmap, nHeight - 1);//<*** flipped
1465
1466 BYTE* line_start = new BYTE[lineSize]; //< fileline cache
1467
1468 switch ( nCompression ) {
1469 case PSDP_COMPRESSION_NONE: // raw data
1470 {
1471 for(unsigned c = 0; c < nChannels; c++) {
1472 if(c >= dstChannels) {
1473 // @todo write extra channels
1474 break;
1475 }
1476
1477 const unsigned channelOffset = GetChannelOffset(bitmap, c) * bytes;
1478
1479 BYTE* dst_line_start = dst_first_line + channelOffset;
1480 for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped
1481 io->read_proc(line_start, lineSize, 1, handle);
1482 ReadImageLine(dst_line_start, line_start, lineSize, dstBpp, bytes);
1483 } //< h
1484 }//< ch
1485
1486 SAFE_DELETE_ARRAY(line_start);
1487
1488 }
1489 break;
1490
1491 case PSDP_COMPRESSION_RLE: // RLE compression
1492 {
1493
1494 // The RLE-compressed data is preceeded by a 2-byte line size for each row in the data,
1495 // store an array of these
1496 // Version 2 has 4-byte line sizes.
1497
1498 // later use this array as DWORD rleLineSizeList[nChannels][nHeight];
1499 DWORD *rleLineSizeList = new (std::nothrow) DWORD[nChannels*nHeight];
1500
1501 if(!rleLineSizeList) {
1502 FreeImage_Unload(bitmap);
1503 SAFE_DELETE_ARRAY(line_start);
1504 throw std::bad_alloc();
1505 }
1506 if(_headerInfo._Version == 1) {
1507 WORD *rleLineSizeList2 = new (std::nothrow) WORD[nChannels*nHeight];
1508 if(!rleLineSizeList2) {
1509 FreeImage_Unload(bitmap);
1510 SAFE_DELETE_ARRAY(line_start);
1511 throw std::bad_alloc();
1512 }
1513 io->read_proc(rleLineSizeList2, 2, nChannels * nHeight, handle);
1514 for(unsigned index = 0; index < nChannels * nHeight; ++index) {
1515 #ifndef FREEIMAGE_BIGENDIAN
1516 SwapShort(&rleLineSizeList2[index]);
1517 #endif
1518 rleLineSizeList[index] = rleLineSizeList2[index];
1519 }
1520 SAFE_DELETE_ARRAY(rleLineSizeList2);
1521 } else {
1522 io->read_proc(rleLineSizeList, 4, nChannels * nHeight, handle);
1523 #ifndef FREEIMAGE_BIGENDIAN
1524 for(unsigned index = 0; index < nChannels * nHeight; ++index) {
1525 SwapLong(&rleLineSizeList[index]);
1526 }
1527 #endif
1528 }
1529
1530 DWORD largestRLELine = 0;
1531 for(unsigned ch = 0; ch < nChannels; ++ch) {
1532 for(unsigned h = 0; h < nHeight; ++h) {
1533 const unsigned index = ch * nHeight + h;
1534
1535 if(largestRLELine < rleLineSizeList[index]) {
1536 largestRLELine = rleLineSizeList[index];
1537 }
1538 }
1539 }
1540
1541 BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine];
1542 if(!rle_line_start) {
1543 FreeImage_Unload(bitmap);
1544 SAFE_DELETE_ARRAY(line_start);
1545 SAFE_DELETE_ARRAY(rleLineSizeList);
1546 throw std::bad_alloc();
1547 }
1548
1549 // Read the RLE data
1550 for (unsigned ch = 0; ch < nChannels; ch++) {
1551 if(ch >= dstChannels) {
1552 // @todo write to extra channels
1553 break;
1554 }
1555 const BYTE* const line_end = line_start + lineSize;
1556
1557 const unsigned channelOffset = GetChannelOffset(bitmap, ch) * bytes;
1558
1559 BYTE* dst_line_start = dst_first_line + channelOffset;
1560 for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped
1561 const unsigned index = ch * nHeight + h;
1562
1563 // - read and uncompress line -
1564
1565 const DWORD rleLineSize = rleLineSizeList[index];
1566
1567 io->read_proc(rle_line_start, rleLineSize, 1, handle);
1568
1569 // - write line to destination -
1570
1571 UnpackRLE(line_start, rle_line_start, line_start + lineSize, rleLineSize);
1572 ReadImageLine(dst_line_start, line_start, lineSize, dstBpp, bytes);
1573 }//< h
1574 }//< ch
1575
1576 SAFE_DELETE_ARRAY(line_start);
1577 SAFE_DELETE_ARRAY(rleLineSizeList);
1578 SAFE_DELETE_ARRAY(rle_line_start);
1579 }
1580 break;
1581
1582 /*
1583 * If layer data is ever supported, do something like this:
1584 * Compressed size comes from layer info section.
1585 * Prediction means unzip, then each pixel value is a delta from the previous pixel.
1586 * Horizontally only.
1587 */
1588 /*
1589 case PSDP_COMPRESSION_ZIP: // ZIP without prediction
1590 case PSDP_COMPRESSION_ZIP_PREDICTION: // ZIP with prediction
1591 {
1592 BYTE *compressed = NULL;
1593 size_t compressedSize = 0;
1594 BYTE *uncompressed = new (std::nothrow) BYTE[nHeight * lineSize];
1595 if(!uncompressed) {
1596 FreeImage_Unload(bitmap);
1597 SAFE_DELETE_ARRAY(line_start);
1598 throw std::bad_alloc();
1599 }
1600 DWORD size = FreeImage_ZLibGUnzip(uncompressed, nHeight * lineSize, compressed, compressedSize);
1601 }
1602 break;
1603 */
1604 default: // Unknown format
1605 break;
1606
1607 }
1608
1609 // --- Further process the bitmap ---
1610
1611 if((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) {
1612 // CMYK values are "inverted", invert them back
1613
1614 if(mode == PSDP_MULTICHANNEL) {
1615 invertColor(bitmap);
1616 } else {
1617 FreeImage_Invert(bitmap);
1618 }
1619
1620 if((_fi_flags & PSD_CMYK) == PSD_CMYK) {
1621 // keep as CMYK
1622
1623 if(mode == PSDP_MULTICHANNEL) {
1624 //### we force CMY to be CMYK, but CMY has no ICC.
1625 // Create empty profile and add the flag.
1626 FreeImage_CreateICCProfile(bitmap, NULL, 0);
1627 FreeImage_GetICCProfile(bitmap)->flags |= FIICC_COLOR_IS_CMYK;
1628 }
1629 }
1630 else {
1631 // convert to RGB
1632
1633 ConvertCMYKtoRGBA(bitmap);
1634
1635 // The ICC Profile is no longer valid
1636 _iccProfile.clear();
1637
1638 // remove the pending A if not present in source
1639 if(nChannels == 4 || nChannels == 3 ) {
1640 FIBITMAP* t = RemoveAlphaChannel(bitmap);
1641 if(t) {
1642 FreeImage_Unload(bitmap);
1643 bitmap = t;
1644 } // else: silently fail
1645 }
1646 }
1647 }
1648 else if ( mode == PSDP_LAB && !((_fi_flags & PSD_LAB) == PSD_LAB)) {
1649 ConvertLABtoRGB(bitmap);
1650 }
1651 else {
1652 if (needPalette && FreeImage_GetPalette(bitmap)) {
1653
1654 if(mode == PSDP_BITMAP) {
1655 CREATE_GREYSCALE_PALETTE_REVERSE(FreeImage_GetPalette(bitmap), 2);
1656 }
1657 else if(mode == PSDP_INDEXED) {
1658 if(!_colourModeData._plColourData || _colourModeData._Length != 768 || _ColourCount < 0) {
1659 FreeImage_OutputMessageProc(_fi_format_id, "Indexed image has no palette. Using the default grayscale one.");
1660 } else {
1661 _colourModeData.FillPalette(bitmap);
1662 }
1663 }
1664 // GRAYSCALE, DUOTONE - use default grayscale palette
1665 }
1666 }
1667
1668 return bitmap;
1669 }
1670
WriteLayerAndMaskInfoSection(FreeImageIO * io,fi_handle handle)1671 bool psdParser::WriteLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle) {
1672 // Short section with no layers.
1673 BYTE IntValue[4];
1674
1675 UINT64 size;
1676 if(_headerInfo._Version == 1) {
1677 size = 8;
1678 } else {
1679 size = 12;
1680 }
1681 // Length of whole info.
1682 if(!psdWriteSize(io, handle, _headerInfo, size)) {
1683 return false;
1684 }
1685 // Length of layers info section.
1686 if(!psdWriteSize(io, handle, _headerInfo, 0)) {
1687 return false;
1688 }
1689 // Length of global layer mask info section. Always 4 bytes.
1690 psdSetValue(IntValue, sizeof(IntValue), 0);
1691 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
1692 return false;
1693 }
1694 // Additional layer information.
1695 return true;
1696 }
1697
WriteImageLine(BYTE * dst,const BYTE * src,unsigned lineSize,unsigned srcBpp,unsigned bytes)1698 void psdParser::WriteImageLine(BYTE* dst, const BYTE* src, unsigned lineSize, unsigned srcBpp, unsigned bytes) {
1699 switch (bytes) {
1700 case 4:
1701 {
1702 DWORD* d = (DWORD*)dst;
1703 const DWORD* s = (const DWORD*)src;
1704 srcBpp /= 4;
1705 while (lineSize > 0) {
1706 DWORD v = *s;
1707 #ifndef FREEIMAGE_BIGENDIAN
1708 SwapLong(&v);
1709 #endif
1710 *d++ = v;
1711 s += srcBpp;
1712 lineSize -= 4;
1713 }
1714 break;
1715 }
1716 case 2:
1717 {
1718 WORD* d = (WORD*)dst;
1719 const WORD* s = (const WORD*)src;
1720 srcBpp /= 2;
1721 while (lineSize > 0) {
1722 WORD v = *s;
1723 #ifndef FREEIMAGE_BIGENDIAN
1724 SwapShort(&v);
1725 #endif
1726 *d++ = v;
1727 s += srcBpp;
1728 lineSize -= 2;
1729 }
1730 break;
1731 }
1732 default:
1733 if (srcBpp == 1) {
1734 memcpy(dst, src, lineSize);
1735 } else {
1736 while (lineSize > 0) {
1737 *dst++ = *src;
1738 src += srcBpp;
1739 lineSize--;
1740 }
1741 }
1742 break;
1743 }
1744 }
1745
PackRLE(BYTE * line_start,const BYTE * src_line,unsigned srcSize)1746 unsigned psdParser::PackRLE(BYTE* line_start, const BYTE* src_line, unsigned srcSize) {
1747 BYTE* line = line_start;
1748 while (srcSize > 0) {
1749 if(srcSize >= 2 && src_line[0] == src_line[1]) {
1750 int len = 2;
1751 while(len < 127 && len < (int)srcSize && src_line[0] == src_line[len])
1752 len++;
1753 *line++ = (BYTE)((-len + 1) & 0xFF);
1754 *line++ = src_line[0];
1755 src_line += len;
1756 srcSize -= len;
1757 } else {
1758 // uncompressed packet
1759 // (len + 1) bytes of data are copied
1760 int len = 1;
1761 while(len < 127 && len < (int)srcSize &&
1762 (len+2 >= (int)srcSize || // check to switch to a run instead
1763 src_line[len] != src_line[len+1] ||
1764 src_line[len] != src_line[len+2]))
1765 len++;
1766 *line++ = (BYTE)(len - 1);
1767 for(int i=0; i < len; i++) {
1768 *line++ = *src_line;
1769 src_line++;
1770 }
1771 srcSize -= len;
1772 }
1773 }
1774 return (unsigned)(line - line_start);
1775 }
1776
WriteImageData(FreeImageIO * io,fi_handle handle,FIBITMAP * dib)1777 bool psdParser::WriteImageData(FreeImageIO *io, fi_handle handle, FIBITMAP* dib) {
1778 if (handle == NULL) {
1779 return false;
1780 }
1781
1782 FIBITMAP* cmyk_dib = NULL;
1783
1784 if (_headerInfo._ColourMode == PSDP_CMYK) {
1785 // CMYK values must be "inverted"
1786 cmyk_dib = FreeImage_Clone(dib);
1787 if (cmyk_dib == NULL) {
1788 return false;
1789 }
1790 dib = cmyk_dib;
1791 FreeImage_Invert(dib);
1792 }
1793
1794 int nCompression = PSDP_COMPRESSION_RLE;
1795 if(_headerInfo._BitsPerChannel > 8) {
1796 // RLE is nearly useless for 16-bit, as it only looks at 8-bit data for runs.
1797 nCompression = PSDP_COMPRESSION_NONE;
1798 }
1799 if((_fi_flags & PSD_NONE) == PSD_NONE) {
1800 nCompression = PSDP_COMPRESSION_NONE;
1801 } else if((_fi_flags & PSD_RLE) == PSD_RLE) {
1802 nCompression = PSDP_COMPRESSION_RLE;
1803 if (_headerInfo._BitsPerChannel > 16) {
1804 nCompression = PSDP_COMPRESSION_NONE;
1805 }
1806 }
1807
1808 WORD CompressionValue = nCompression;
1809 #ifndef FREEIMAGE_BIGENDIAN
1810 SwapShort(&CompressionValue);
1811 #endif
1812
1813 if(io->write_proc(&CompressionValue, sizeof(CompressionValue), 1, handle) != 1) {
1814 return false;
1815 }
1816
1817 const unsigned nWidth = _headerInfo._Width;
1818 const unsigned nHeight = _headerInfo._Height;
1819 const unsigned nChannels = _headerInfo._Channels;
1820 const unsigned depth = _headerInfo._BitsPerChannel;
1821 const unsigned bytes = (depth == 1) ? 1 : depth / 8;
1822
1823 // channel(plane) line (BYTE aligned)
1824 const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes;
1825
1826 const unsigned srcBpp = (depth == 1) ? 1 : FreeImage_GetBPP(dib)/8;
1827 const unsigned srcLineSize = FreeImage_GetPitch(dib);
1828 BYTE* const src_first_line = FreeImage_GetScanLine(dib, nHeight - 1);//<*** flipped
1829 BYTE* line_start = new BYTE[lineSize]; //< fileline cache
1830
1831 switch ( nCompression ) {
1832 case PSDP_COMPRESSION_NONE: // raw data
1833 {
1834 for(unsigned c = 0; c < nChannels; c++) {
1835 const unsigned channelOffset = GetChannelOffset(dib, c) * bytes;
1836
1837 BYTE* src_line_start = src_first_line + channelOffset;
1838 for(unsigned h = 0; h < nHeight; ++h, src_line_start -= srcLineSize) {//<*** flipped
1839 WriteImageLine(line_start, src_line_start, lineSize, srcBpp, bytes);
1840 if(io->write_proc(line_start, lineSize, 1, handle) != 1) {
1841 return false;
1842 }
1843 } //< h
1844 }//< ch
1845 }
1846 break;
1847
1848 case PSDP_COMPRESSION_RLE: // RLE compression
1849 {
1850 // The RLE-compressed data is preceeded by a 2-byte line size for each row in the data,
1851 // store an array of these
1852 // Version 2 has 4-byte line sizes.
1853
1854 // later use this array as WORD rleLineSizeList[nChannels][nHeight];
1855 // Every 127 bytes needs a length byte.
1856 BYTE* rle_line_start = new BYTE[lineSize + ((nWidth + 126) / 127)]; //< RLE buffer
1857 DWORD *rleLineSizeList = new (std::nothrow) DWORD[nChannels*nHeight];
1858
1859 if(!rleLineSizeList) {
1860 SAFE_DELETE_ARRAY(line_start);
1861 throw std::bad_alloc();
1862 }
1863 memset(rleLineSizeList, 0, sizeof(DWORD)*nChannels*nHeight);
1864 const long offsets_pos = io->tell_proc(handle);
1865 if(_headerInfo._Version == 1) {
1866 if(io->write_proc(rleLineSizeList, nChannels*nHeight*2, 1, handle) != 1) {
1867 return false;
1868 }
1869 } else {
1870 if(io->write_proc(rleLineSizeList, nChannels*nHeight*4, 1, handle) != 1) {
1871 return false;
1872 }
1873 }
1874 for(unsigned c = 0; c < nChannels; c++) {
1875 const unsigned channelOffset = GetChannelOffset(dib, c) * bytes;
1876
1877 BYTE* src_line_start = src_first_line + channelOffset;
1878 for(unsigned h = 0; h < nHeight; ++h, src_line_start -= srcLineSize) {//<*** flipped
1879 WriteImageLine(line_start, src_line_start, lineSize, srcBpp, bytes);
1880 unsigned len = PackRLE(rle_line_start, line_start, lineSize);
1881 rleLineSizeList[c * nHeight + h] = len;
1882 if(io->write_proc(rle_line_start, len, 1, handle) != 1) {
1883 return false;
1884 }
1885 }
1886 }
1887 SAFE_DELETE_ARRAY(rle_line_start);
1888 // Fix length of resource
1889 io->seek_proc(handle, offsets_pos, SEEK_SET);
1890 if(_headerInfo._Version == 1) {
1891 WORD *rleLineSizeList2 = new (std::nothrow) WORD[nChannels*nHeight];
1892 if(!rleLineSizeList2) {
1893 SAFE_DELETE_ARRAY(line_start);
1894 throw std::bad_alloc();
1895 }
1896 for(unsigned index = 0; index < nChannels * nHeight; ++index) {
1897 rleLineSizeList2[index] = (WORD)rleLineSizeList[index];
1898 #ifndef FREEIMAGE_BIGENDIAN
1899 SwapShort(&rleLineSizeList2[index]);
1900 #endif
1901 }
1902 if(io->write_proc(rleLineSizeList2, nChannels*nHeight*2, 1, handle) != 1) {
1903 return false;
1904 }
1905 SAFE_DELETE_ARRAY(rleLineSizeList2);
1906 } else {
1907 #ifndef FREEIMAGE_BIGENDIAN
1908 for(unsigned index = 0; index < nChannels * nHeight; ++index) {
1909 SwapLong(&rleLineSizeList[index]);
1910 }
1911 #endif
1912 if(io->write_proc(rleLineSizeList, nChannels*nHeight*4, 1, handle) != 1) {
1913 return false;
1914 }
1915 }
1916 io->seek_proc(handle, 0, SEEK_END);
1917 }
1918 break;
1919
1920 case PSDP_COMPRESSION_ZIP: // ZIP without prediction
1921 case PSDP_COMPRESSION_ZIP_PREDICTION: // ZIP with prediction
1922 {
1923 }
1924 break;
1925
1926 default: // Unknown format
1927 break;
1928 }
1929
1930 SAFE_DELETE_ARRAY(line_start);
1931
1932 if (cmyk_dib != NULL) {
1933 FreeImage_Unload(cmyk_dib);
1934 }
1935
1936 return true;
1937 }
1938
Load(FreeImageIO * io,fi_handle handle,int s_format_id,int flags)1939 FIBITMAP* psdParser::Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags) {
1940 FIBITMAP *Bitmap = NULL;
1941
1942 _fi_flags = flags;
1943 _fi_format_id = s_format_id;
1944
1945 try {
1946 if (NULL == handle) {
1947 throw("Cannot open file");
1948 }
1949
1950 if (!_headerInfo.Read(io, handle)) {
1951 throw("Error in header");
1952 }
1953
1954 if (!_colourModeData.Read(io, handle)) {
1955 throw("Error in ColourMode Data");
1956 }
1957
1958 if (!ReadImageResources(io, handle)) {
1959 throw("Error in Image Resource");
1960 }
1961
1962 if (!ReadLayerAndMaskInfoSection(io, handle)) {
1963 throw("Error in Mask Info");
1964 }
1965
1966 Bitmap = ReadImageData(io, handle);
1967 if (NULL == Bitmap) {
1968 throw("Error in Image Data");
1969 }
1970
1971 // set resolution info
1972 if(NULL != Bitmap) {
1973 unsigned res_x = 2835; // 72 dpi
1974 unsigned res_y = 2835; // 72 dpi
1975 if (_bResolutionInfoFilled) {
1976 _resolutionInfo.GetResolutionInfo(res_x, res_y);
1977 }
1978 FreeImage_SetDotsPerMeterX(Bitmap, res_x);
1979 FreeImage_SetDotsPerMeterY(Bitmap, res_y);
1980 }
1981
1982 // set ICC profile
1983 if(NULL != _iccProfile._ProfileData) {
1984 FreeImage_CreateICCProfile(Bitmap, _iccProfile._ProfileData, _iccProfile._ProfileSize);
1985 if ((flags & PSD_CMYK) == PSD_CMYK) {
1986 short mode = _headerInfo._ColourMode;
1987 if((mode == PSDP_CMYK) || (mode == PSDP_MULTICHANNEL)) {
1988 FreeImage_GetICCProfile(Bitmap)->flags |= FIICC_COLOR_IS_CMYK;
1989 }
1990 }
1991 }
1992
1993 // Metadata
1994 if(NULL != _iptc._Data) {
1995 read_iptc_profile(Bitmap, _iptc._Data, _iptc._Size);
1996 }
1997 if(NULL != _exif1._Data) {
1998 psd_read_exif_profile(Bitmap, _exif1._Data, _exif1._Size);
1999 psd_read_exif_profile_raw(Bitmap, _exif1._Data, _exif1._Size);
2000 } else if(NULL != _exif3._Data) {
2001 // I have not found any files with this resource.
2002 // Assume that we only want one Exif resource.
2003 assert(false);
2004 psd_read_exif_profile(Bitmap, _exif3._Data, _exif3._Size);
2005 psd_read_exif_profile_raw(Bitmap, _exif3._Data, _exif3._Size);
2006 }
2007
2008 // XMP metadata
2009 if(NULL != _xmp._Data) {
2010 psd_set_xmp_profile(Bitmap, _xmp._Data, _xmp._Size);
2011 }
2012
2013 } catch(const char *text) {
2014 FreeImage_OutputMessageProc(s_format_id, text);
2015 }
2016 catch(const std::exception& e) {
2017 FreeImage_OutputMessageProc(s_format_id, "%s", e.what());
2018 }
2019
2020 return Bitmap;
2021 }
2022
Save(FreeImageIO * io,FIBITMAP * dib,fi_handle handle,int page,int flags,void * data)2023 bool psdParser::Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
2024 if (!dib || !handle) {
2025 return false;
2026 }
2027
2028 _fi_flags = flags;
2029
2030 const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
2031
2032 const unsigned width = FreeImage_GetWidth(dib);
2033 const unsigned height = FreeImage_GetHeight(dib);
2034 const unsigned bitsperpixel = FreeImage_GetBPP(dib);
2035
2036 const FIICCPROFILE* iccProfile = FreeImage_GetICCProfile(dib);
2037
2038 // setup out-variables based on dib and flag options
2039
2040 unsigned bitspersample;
2041 unsigned samplesperpixel;
2042 short colourMode = PSDP_RGB;
2043
2044 if(image_type == FIT_BITMAP) {
2045 // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
2046 if(bitsperpixel == 32) {
2047 // 32-bit images : check for CMYK or alpha transparency
2048
2049 if((((iccProfile->flags & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) || ((flags & PSD_CMYK) == PSD_CMYK))) {
2050 colourMode = PSDP_CMYK;
2051 }
2052 samplesperpixel = 4;
2053 } else if(bitsperpixel == 24) {
2054 samplesperpixel = 3;
2055 } else if(bitsperpixel == 8) {
2056 samplesperpixel = 1;
2057 colourMode = PSDP_INDEXED;
2058 } else if(bitsperpixel == 1) {
2059 samplesperpixel = 1;
2060 colourMode = PSDP_BITMAP;
2061 } else {
2062 return false;
2063 }
2064 bitspersample = bitsperpixel / samplesperpixel;
2065 } else if(image_type == FIT_UINT16 || image_type == FIT_INT16) {
2066 // Grayscale
2067 samplesperpixel = 1;
2068 bitspersample = bitsperpixel / samplesperpixel;
2069 colourMode = PSDP_GRAYSCALE;
2070 } else if(image_type == FIT_RGB16) {
2071 // 48-bit RGB
2072 samplesperpixel = 3;
2073 bitspersample = bitsperpixel / samplesperpixel;
2074 } else if(image_type == FIT_RGBA16) {
2075 // 64-bit RGBA
2076 samplesperpixel = 4;
2077 bitspersample = bitsperpixel / samplesperpixel;
2078 if((((iccProfile->flags & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) || ((flags & PSD_CMYK) == PSD_CMYK))) {
2079 colourMode = PSDP_CMYK;
2080 }
2081 } else if(image_type == FIT_RGBF) {
2082 // 96-bit RGBF
2083 samplesperpixel = 3;
2084 bitspersample = bitsperpixel / samplesperpixel;
2085 } else if (image_type == FIT_RGBAF) {
2086 // 128-bit RGBAF
2087 samplesperpixel = 4;
2088 bitspersample = bitsperpixel / samplesperpixel;
2089 } else {
2090 // special image type (int, long, double, ...)
2091 samplesperpixel = 1;
2092 bitspersample = bitsperpixel;
2093 }
2094
2095 _headerInfo._Version = (((flags & PSD_PSB) == PSD_PSB) || width > 30000 || height > 30000) ? 2 : 1;
2096 _headerInfo._Channels = samplesperpixel;
2097 _headerInfo._Height = height;
2098 _headerInfo._Width = width;
2099 _headerInfo._BitsPerChannel = bitsperpixel / samplesperpixel;
2100 _headerInfo._ColourMode = colourMode;
2101 if(!_headerInfo.Write(io, handle)) return false;
2102
2103 _colourModeData._Length = 0;
2104 _colourModeData._plColourData = NULL;
2105 if (FreeImage_GetPalette(dib) != NULL) {
2106 RGBQUAD *pal = FreeImage_GetPalette(dib);
2107 _colourModeData._Length = FreeImage_GetColorsUsed(dib) * 3;
2108 _colourModeData._plColourData = new BYTE[_colourModeData._Length];
2109 for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++ ) {
2110 _colourModeData._plColourData[i + 0*256] = pal[i].rgbRed;
2111 _colourModeData._plColourData[i + 1*256] = pal[i].rgbGreen;
2112 _colourModeData._plColourData[i + 2*256] = pal[i].rgbBlue;
2113 }
2114 }
2115
2116 if (!_colourModeData.Write(io, handle)) {
2117 return false;
2118 }
2119
2120 BYTE IntValue[4];
2121 const long res_start_pos = io->tell_proc(handle);
2122 psdSetValue(IntValue, sizeof(IntValue), 0);
2123 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
2124 return false;
2125 }
2126
2127 _resolutionInfo._hRes = (short) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib));
2128 _resolutionInfo._hResUnit = 1; // inches
2129 _resolutionInfo._widthUnit = 1; // inches
2130 _resolutionInfo._vRes = (short) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib));
2131 _resolutionInfo._vResUnit = 1; // inches
2132 _resolutionInfo._heightUnit = 1; // inches
2133 if (!_resolutionInfo.Write(io, handle)) {
2134 return false;
2135 }
2136
2137 // psdResolutionInfo_v2 is obsolete - Photoshop 2.0
2138
2139 _displayInfo._ColourSpace = (colourMode == PSDP_CMYK) ? 2 : 0;
2140 memset(_displayInfo._Colour, 0, sizeof(_displayInfo._Colour));
2141 _displayInfo._Opacity = 100;
2142 _displayInfo._Kind = 0;
2143 _displayInfo._padding = 0;
2144 if (!_displayInfo.Write(io, handle)) {
2145 return false;
2146 }
2147
2148 if(GetThumbnail() == NULL) {
2149 _thumbnail._owned = false;
2150 _thumbnail._dib = FreeImage_GetThumbnail(dib);
2151 }
2152 if(GetThumbnail() != NULL) {
2153 _thumbnail.Init();
2154 if (!_thumbnail.Write(io, handle, false)) {
2155 return false;
2156 }
2157 }
2158
2159 if(iccProfile != NULL && iccProfile->size > 0) {
2160 _iccProfile.clear();
2161 _iccProfile._owned = false;
2162 _iccProfile._ProfileSize = iccProfile->size;
2163 _iccProfile._ProfileData = (BYTE*)iccProfile->data;
2164 if (!_iccProfile.Write(io, handle)) {
2165 return false;
2166 }
2167 }
2168
2169 if(write_iptc_profile(dib, &_iptc._Data, &_iptc._Size)) {
2170 if (!_iptc.Write(io, handle, PSDP_RES_IPTC_NAA)) {
2171 return false;
2172 }
2173 }
2174
2175 if(psd_write_exif_profile_raw(dib, &_exif1._Data, &_exif1._Size)) {
2176 _exif1._owned = false;
2177 if (!_exif1.Write(io, handle, PSDP_RES_EXIF1)) {
2178 return false;
2179 }
2180 }
2181
2182 if(psd_get_xmp_profile(dib, &_xmp._Data, &_xmp._Size)) {
2183 _xmp._owned = false;
2184 if (!_xmp.Write(io, handle, PSDP_RES_XMP)) {
2185 return false;
2186 }
2187 }
2188
2189 // Fix length of resources
2190 const long current_pos = io->tell_proc(handle);
2191 psdSetValue(IntValue, sizeof(IntValue), (int)(current_pos - res_start_pos - 4));
2192 io->seek_proc(handle, res_start_pos, SEEK_SET);
2193 if(io->write_proc(IntValue, sizeof(IntValue), 1, handle) != 1) {
2194 return false;
2195 }
2196 io->seek_proc(handle, current_pos, SEEK_SET);
2197
2198 if (!WriteLayerAndMaskInfoSection(io, handle)) {
2199 return false;
2200 }
2201 if (!WriteImageData(io, handle, dib)) {
2202 return false;
2203 }
2204
2205 return true;
2206 }
2207