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