1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % PPPP SSSSS DDDD %
7 % P P SS D D %
8 % PPPP SSS D D %
9 % P SS D D %
10 % P SSSSS DDDD %
11 % %
12 % %
13 % Read/Write Adobe Photoshop Image Format %
14 % %
15 % Software Design %
16 % Cristy %
17 % Leonard Rosenthol %
18 % July 1992 %
19 % Dirk Lemstra %
20 % December 2013 %
21 % %
22 % %
23 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
24 % dedicated to making software imaging solutions freely available. %
25 % %
26 % You may not use this file except in compliance with the License. You may %
27 % obtain a copy of the License at %
28 % %
29 % http://www.imagemagick.org/script/license.php %
30 % %
31 % Unless required by applicable law or agreed to in writing, software %
32 % distributed under the License is distributed on an "AS IS" BASIS, %
33 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
34 % See the License for the specific language governing permissions and %
35 % limitations under the License. %
36 % %
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 %
39 %
40 */
41
42 /*
43 Include declarations.
44 */
45 #include "MagickCore/studio.h"
46 #include "MagickCore/artifact.h"
47 #include "MagickCore/attribute.h"
48 #include "MagickCore/blob.h"
49 #include "MagickCore/blob-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/channel.h"
52 #include "MagickCore/colormap.h"
53 #include "MagickCore/colormap-private.h"
54 #include "MagickCore/colorspace.h"
55 #include "MagickCore/colorspace-private.h"
56 #include "MagickCore/constitute.h"
57 #include "MagickCore/enhance.h"
58 #include "MagickCore/exception.h"
59 #include "MagickCore/exception-private.h"
60 #include "MagickCore/image.h"
61 #include "MagickCore/image-private.h"
62 #include "MagickCore/list.h"
63 #include "MagickCore/log.h"
64 #include "MagickCore/magick.h"
65 #include "MagickCore/memory_.h"
66 #include "MagickCore/module.h"
67 #include "MagickCore/monitor-private.h"
68 #include "MagickCore/option.h"
69 #include "MagickCore/pixel.h"
70 #include "MagickCore/pixel-accessor.h"
71 #include "MagickCore/profile.h"
72 #include "MagickCore/property.h"
73 #include "MagickCore/quantum-private.h"
74 #include "MagickCore/static.h"
75 #include "MagickCore/string_.h"
76 #include "MagickCore/thread-private.h"
77 #ifdef MAGICKCORE_ZLIB_DELEGATE
78 #include <zlib.h>
79 #endif
80 #include "psd-private.h"
81
82 /*
83 Define declaractions.
84 */
85 #define MaxPSDChannels 56
86 #define PSDQuantum(x) (((ssize_t) (x)+1) & -2)
87
88 /*
89 Enumerated declaractions.
90 */
91 typedef enum
92 {
93 Raw = 0,
94 RLE = 1,
95 ZipWithoutPrediction = 2,
96 ZipWithPrediction = 3
97 } PSDCompressionType;
98
99 typedef enum
100 {
101 BitmapMode = 0,
102 GrayscaleMode = 1,
103 IndexedMode = 2,
104 RGBMode = 3,
105 CMYKMode = 4,
106 MultichannelMode = 7,
107 DuotoneMode = 8,
108 LabMode = 9
109 } PSDImageType;
110
111 /*
112 Typedef declaractions.
113 */
114 typedef struct _ChannelInfo
115 {
116 short int
117 type;
118
119 size_t
120 size;
121 } ChannelInfo;
122
123 typedef struct _MaskInfo
124 {
125 Image
126 *image;
127
128 RectangleInfo
129 page;
130
131 unsigned char
132 background,
133 flags;
134 } MaskInfo;
135
136 typedef struct _LayerInfo
137 {
138 ChannelInfo
139 channel_info[MaxPSDChannels];
140
141 char
142 blendkey[4];
143
144 Image
145 *image;
146
147 MaskInfo
148 mask;
149
150 Quantum
151 opacity;
152
153 RectangleInfo
154 page;
155
156 size_t
157 offset_x,
158 offset_y;
159
160 unsigned char
161 clipping,
162 flags,
163 name[256],
164 visible;
165
166 unsigned short
167 channels;
168 } LayerInfo;
169
170 /*
171 Forward declarations.
172 */
173 static MagickBooleanType
174 WritePSDImage(const ImageInfo *,Image *,ExceptionInfo *);
175
176 /*
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 % %
179 % %
180 % %
181 % I s P S D %
182 % %
183 % %
184 % %
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 %
187 % IsPSD()() returns MagickTrue if the image format type, identified by the
188 % magick string, is PSD.
189 %
190 % The format of the IsPSD method is:
191 %
192 % MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
193 %
194 % A description of each parameter follows:
195 %
196 % o magick: compare image format pattern against these bytes.
197 %
198 % o length: Specifies the length of the magick string.
199 %
200 */
IsPSD(const unsigned char * magick,const size_t length)201 static MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
202 {
203 if (length < 4)
204 return(MagickFalse);
205 if (LocaleNCompare((const char *) magick,"8BPS",4) == 0)
206 return(MagickTrue);
207 return(MagickFalse);
208 }
209
210 /*
211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212 % %
213 % %
214 % %
215 % R e a d P S D I m a g e %
216 % %
217 % %
218 % %
219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220 %
221 % ReadPSDImage() reads an Adobe Photoshop image file and returns it. It
222 % allocates the memory necessary for the new Image structure and returns a
223 % pointer to the new image.
224 %
225 % The format of the ReadPSDImage method is:
226 %
227 % Image *ReadPSDImage(image_info,ExceptionInfo *exception)
228 %
229 % A description of each parameter follows:
230 %
231 % o image_info: the image info.
232 %
233 % o exception: return any errors or warnings in this structure.
234 %
235 */
236
CompositeOperatorToPSDBlendMode(CompositeOperator op)237 static const char *CompositeOperatorToPSDBlendMode(CompositeOperator op)
238 {
239 const char
240 *blend_mode;
241
242 switch (op)
243 {
244 case ColorBurnCompositeOp: blend_mode = "idiv"; break;
245 case ColorDodgeCompositeOp: blend_mode = "div "; break;
246 case ColorizeCompositeOp: blend_mode = "colr"; break;
247 case DarkenCompositeOp: blend_mode = "dark"; break;
248 case DifferenceCompositeOp: blend_mode = "diff"; break;
249 case DissolveCompositeOp: blend_mode = "diss"; break;
250 case ExclusionCompositeOp: blend_mode = "smud"; break;
251 case HardLightCompositeOp: blend_mode = "hLit"; break;
252 case HardMixCompositeOp: blend_mode = "hMix"; break;
253 case HueCompositeOp: blend_mode = "hue "; break;
254 case LightenCompositeOp: blend_mode = "lite"; break;
255 case LinearBurnCompositeOp: blend_mode = "lbrn"; break;
256 case LinearDodgeCompositeOp:blend_mode = "lddg"; break;
257 case LinearLightCompositeOp:blend_mode = "lLit"; break;
258 case LuminizeCompositeOp: blend_mode = "lum "; break;
259 case MultiplyCompositeOp: blend_mode = "mul "; break;
260 case OverCompositeOp: blend_mode = "norm"; break;
261 case OverlayCompositeOp: blend_mode = "over"; break;
262 case PinLightCompositeOp: blend_mode = "pLit"; break;
263 case SaturateCompositeOp: blend_mode = "sat "; break;
264 case ScreenCompositeOp: blend_mode = "scrn"; break;
265 case SoftLightCompositeOp: blend_mode = "sLit"; break;
266 case VividLightCompositeOp: blend_mode = "vLit"; break;
267 default: blend_mode = "norm";
268 }
269 return(blend_mode);
270 }
271
272 /*
273 For some reason Photoshop seems to blend semi-transparent pixels with white.
274 This method reverts the blending. This can be disabled by setting the
275 option 'psd:alpha-unblend' to off.
276 */
CorrectPSDAlphaBlend(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)277 static MagickBooleanType CorrectPSDAlphaBlend(const ImageInfo *image_info,
278 Image *image,ExceptionInfo* exception)
279 {
280 const char
281 *option;
282
283 MagickBooleanType
284 status;
285
286 ssize_t
287 y;
288
289 if (image->alpha_trait != BlendPixelTrait || image->colorspace != sRGBColorspace)
290 return(MagickTrue);
291 option=GetImageOption(image_info,"psd:alpha-unblend");
292 if (IsStringFalse(option) != MagickFalse)
293 return(MagickTrue);
294 status=MagickTrue;
295 #if defined(MAGICKCORE_OPENMP_SUPPORT)
296 #pragma omp parallel for schedule(static,4) shared(status) \
297 magick_threads(image,image,image->rows,1)
298 #endif
299 for (y=0; y < (ssize_t) image->rows; y++)
300 {
301 register Quantum
302 *magick_restrict q;
303
304 register ssize_t
305 x;
306
307 if (status == MagickFalse)
308 continue;
309 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
310 if (q == (Quantum *) NULL)
311 {
312 status=MagickFalse;
313 continue;
314 }
315 for (x=0; x < (ssize_t) image->columns; x++)
316 {
317 double
318 gamma;
319
320 register ssize_t
321 i;
322
323 gamma=QuantumScale*GetPixelAlpha(image, q);
324 if (gamma != 0.0 && gamma != 1.0)
325 {
326 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
327 {
328 PixelChannel channel=GetPixelChannelChannel(image,i);
329 if (channel != AlphaPixelChannel)
330 q[i]=ClampToQuantum((q[i]-((1.0-gamma)*QuantumRange))/gamma);
331 }
332 }
333 q+=GetPixelChannels(image);
334 }
335 if (SyncAuthenticPixels(image,exception) == MagickFalse)
336 status=MagickFalse;
337 }
338
339 return(status);
340 }
341
ConvertPSDCompression(PSDCompressionType compression)342 static inline CompressionType ConvertPSDCompression(
343 PSDCompressionType compression)
344 {
345 switch (compression)
346 {
347 case RLE:
348 return RLECompression;
349 case ZipWithPrediction:
350 case ZipWithoutPrediction:
351 return ZipCompression;
352 default:
353 return NoCompression;
354 }
355 }
356
CorrectPSDOpacity(LayerInfo * layer_info,ExceptionInfo * exception)357 static MagickBooleanType CorrectPSDOpacity(LayerInfo *layer_info,
358 ExceptionInfo *exception)
359 {
360 MagickBooleanType
361 status;
362
363 ssize_t
364 y;
365
366 if (layer_info->opacity == OpaqueAlpha)
367 return(MagickTrue);
368
369 layer_info->image->alpha_trait=BlendPixelTrait;
370 status=MagickTrue;
371 #if defined(MAGICKCORE_OPENMP_SUPPORT)
372 #pragma omp parallel for schedule(static,4) shared(status) \
373 magick_threads(layer_info->image,layer_info->image,layer_info->image->rows,1)
374 #endif
375 for (y=0; y < (ssize_t) layer_info->image->rows; y++)
376 {
377 register Quantum
378 *magick_restrict q;
379
380 register ssize_t
381 x;
382
383 if (status == MagickFalse)
384 continue;
385 q=GetAuthenticPixels(layer_info->image,0,y,layer_info->image->columns,1,
386 exception);
387 if (q == (Quantum *)NULL)
388 {
389 status=MagickFalse;
390 continue;
391 }
392 for (x=0; x < (ssize_t) layer_info->image->columns; x++)
393 {
394 SetPixelAlpha(layer_info->image,(Quantum) (QuantumScale*(GetPixelAlpha(
395 layer_info->image,q))*layer_info->opacity),q);
396 q+=GetPixelChannels(layer_info->image);
397 }
398 if (SyncAuthenticPixels(layer_info->image,exception) == MagickFalse)
399 status=MagickFalse;
400 }
401
402 return(status);
403 }
404
DecodePSDPixels(const size_t number_compact_pixels,const unsigned char * compact_pixels,const ssize_t depth,const size_t number_pixels,unsigned char * pixels)405 static ssize_t DecodePSDPixels(const size_t number_compact_pixels,
406 const unsigned char *compact_pixels,const ssize_t depth,
407 const size_t number_pixels,unsigned char *pixels)
408 {
409 #define CheckNumberCompactPixels \
410 if (packets == 0) \
411 return(i); \
412 packets--
413
414 #define CheckNumberPixels(count) \
415 if (((ssize_t) i + count) > (ssize_t) number_pixels) \
416 return(i); \
417 i+=count
418
419 int
420 pixel;
421
422 register ssize_t
423 i,
424 j;
425
426 size_t
427 length;
428
429 ssize_t
430 packets;
431
432 packets=(ssize_t) number_compact_pixels;
433 for (i=0; (packets > 1) && (i < (ssize_t) number_pixels); )
434 {
435 packets--;
436 length=(size_t) (*compact_pixels++);
437 if (length == 128)
438 continue;
439 if (length > 128)
440 {
441 length=256-length+1;
442 CheckNumberCompactPixels;
443 pixel=(*compact_pixels++);
444 for (j=0; j < (ssize_t) length; j++)
445 {
446 switch (depth)
447 {
448 case 1:
449 {
450 CheckNumberPixels(8);
451 *pixels++=(pixel >> 7) & 0x01 ? 0U : 255U;
452 *pixels++=(pixel >> 6) & 0x01 ? 0U : 255U;
453 *pixels++=(pixel >> 5) & 0x01 ? 0U : 255U;
454 *pixels++=(pixel >> 4) & 0x01 ? 0U : 255U;
455 *pixels++=(pixel >> 3) & 0x01 ? 0U : 255U;
456 *pixels++=(pixel >> 2) & 0x01 ? 0U : 255U;
457 *pixels++=(pixel >> 1) & 0x01 ? 0U : 255U;
458 *pixels++=(pixel >> 0) & 0x01 ? 0U : 255U;
459 break;
460 }
461 case 2:
462 {
463 CheckNumberPixels(4);
464 *pixels++=(unsigned char) ((pixel >> 6) & 0x03);
465 *pixels++=(unsigned char) ((pixel >> 4) & 0x03);
466 *pixels++=(unsigned char) ((pixel >> 2) & 0x03);
467 *pixels++=(unsigned char) ((pixel & 0x03) & 0x03);
468 break;
469 }
470 case 4:
471 {
472 CheckNumberPixels(2);
473 *pixels++=(unsigned char) ((pixel >> 4) & 0xff);
474 *pixels++=(unsigned char) ((pixel & 0x0f) & 0xff);
475 break;
476 }
477 default:
478 {
479 CheckNumberPixels(1);
480 *pixels++=(unsigned char) pixel;
481 break;
482 }
483 }
484 }
485 continue;
486 }
487 length++;
488 for (j=0; j < (ssize_t) length; j++)
489 {
490 CheckNumberCompactPixels;
491 switch (depth)
492 {
493 case 1:
494 {
495 CheckNumberPixels(8);
496 *pixels++=(*compact_pixels >> 7) & 0x01 ? 0U : 255U;
497 *pixels++=(*compact_pixels >> 6) & 0x01 ? 0U : 255U;
498 *pixels++=(*compact_pixels >> 5) & 0x01 ? 0U : 255U;
499 *pixels++=(*compact_pixels >> 4) & 0x01 ? 0U : 255U;
500 *pixels++=(*compact_pixels >> 3) & 0x01 ? 0U : 255U;
501 *pixels++=(*compact_pixels >> 2) & 0x01 ? 0U : 255U;
502 *pixels++=(*compact_pixels >> 1) & 0x01 ? 0U : 255U;
503 *pixels++=(*compact_pixels >> 0) & 0x01 ? 0U : 255U;
504 break;
505 }
506 case 2:
507 {
508 CheckNumberPixels(4);
509 *pixels++=(*compact_pixels >> 6) & 0x03;
510 *pixels++=(*compact_pixels >> 4) & 0x03;
511 *pixels++=(*compact_pixels >> 2) & 0x03;
512 *pixels++=(*compact_pixels & 0x03) & 0x03;
513 break;
514 }
515 case 4:
516 {
517 CheckNumberPixels(2);
518 *pixels++=(*compact_pixels >> 4) & 0xff;
519 *pixels++=(*compact_pixels & 0x0f) & 0xff;
520 break;
521 }
522 default:
523 {
524 CheckNumberPixels(1);
525 *pixels++=(*compact_pixels);
526 break;
527 }
528 }
529 compact_pixels++;
530 }
531 }
532 return(i);
533 }
534
DestroyLayerInfo(LayerInfo * layer_info,const ssize_t number_layers)535 static inline LayerInfo *DestroyLayerInfo(LayerInfo *layer_info,
536 const ssize_t number_layers)
537 {
538 ssize_t
539 i;
540
541 for (i=0; i<number_layers; i++)
542 {
543 if (layer_info[i].image != (Image *) NULL)
544 layer_info[i].image=DestroyImage(layer_info[i].image);
545 if (layer_info[i].mask.image != (Image *) NULL)
546 layer_info[i].mask.image=DestroyImage(layer_info[i].mask.image);
547 }
548
549 return (LayerInfo *) RelinquishMagickMemory(layer_info);
550 }
551
GetPSDPacketSize(Image * image)552 static inline size_t GetPSDPacketSize(Image *image)
553 {
554 if (image->storage_class == PseudoClass)
555 {
556 if (image->colors > 256)
557 return(2);
558 else if (image->depth > 8)
559 return(2);
560 }
561 else
562 if (image->depth > 8)
563 return(2);
564
565 return(1);
566 }
567
GetPSDSize(const PSDInfo * psd_info,Image * image)568 static inline MagickSizeType GetPSDSize(const PSDInfo *psd_info,Image *image)
569 {
570 if (psd_info->version == 1)
571 return((MagickSizeType) ReadBlobLong(image));
572 return((MagickSizeType) ReadBlobLongLong(image));
573 }
574
GetPSDRowSize(Image * image)575 static inline size_t GetPSDRowSize(Image *image)
576 {
577 if (image->depth == 1)
578 return(((image->columns+7)/8)*GetPSDPacketSize(image));
579 else
580 return(image->columns*GetPSDPacketSize(image));
581 }
582
ModeToString(PSDImageType type)583 static const char *ModeToString(PSDImageType type)
584 {
585 switch (type)
586 {
587 case BitmapMode: return "Bitmap";
588 case GrayscaleMode: return "Grayscale";
589 case IndexedMode: return "Indexed";
590 case RGBMode: return "RGB";
591 case CMYKMode: return "CMYK";
592 case MultichannelMode: return "Multichannel";
593 case DuotoneMode: return "Duotone";
594 case LabMode: return "L*A*B";
595 default: return "unknown";
596 }
597 }
598
NegateCMYK(Image * image,ExceptionInfo * exception)599 static MagickBooleanType NegateCMYK(Image *image,ExceptionInfo *exception)
600 {
601 ChannelType
602 channel_mask;
603
604 MagickBooleanType
605 status;
606
607 channel_mask=SetImageChannelMask(image,(ChannelType)(AllChannels &~
608 AlphaChannel));
609 status=NegateImage(image,MagickFalse,exception);
610 (void) SetImageChannelMask(image,channel_mask);
611 return(status);
612 }
613
ParseImageResourceBlocks(Image * image,const unsigned char * blocks,size_t length,MagickBooleanType * has_merged_image,ExceptionInfo * exception)614 static void ParseImageResourceBlocks(Image *image,
615 const unsigned char *blocks,size_t length,
616 MagickBooleanType *has_merged_image,ExceptionInfo *exception)
617 {
618 const unsigned char
619 *p;
620
621 StringInfo
622 *profile;
623
624 unsigned int
625 count,
626 long_sans;
627
628 unsigned short
629 id,
630 short_sans;
631
632 if (length < 16)
633 return;
634 profile=BlobToStringInfo((const unsigned char *) NULL,length);
635 SetStringInfoDatum(profile,blocks);
636 (void) SetImageProfile(image,"8bim",profile,exception);
637 profile=DestroyStringInfo(profile);
638 for (p=blocks; (p >= blocks) && (p < (blocks+length-16)); )
639 {
640 if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
641 break;
642 p=PushLongPixel(MSBEndian,p,&long_sans);
643 p=PushShortPixel(MSBEndian,p,&id);
644 p=PushShortPixel(MSBEndian,p,&short_sans);
645 p=PushLongPixel(MSBEndian,p,&count);
646 if ((p+count) > (blocks+length-16))
647 return;
648 switch (id)
649 {
650 case 0x03ed:
651 {
652 char
653 value[MagickPathExtent];
654
655 unsigned short
656 resolution;
657
658 /*
659 Resolution info.
660 */
661 p=PushShortPixel(MSBEndian,p,&resolution);
662 image->resolution.x=(double) resolution;
663 (void) FormatLocaleString(value,MagickPathExtent,"%g",image->resolution.x);
664 (void) SetImageProperty(image,"tiff:XResolution",value,exception);
665 p=PushShortPixel(MSBEndian,p,&short_sans);
666 p=PushShortPixel(MSBEndian,p,&short_sans);
667 p=PushShortPixel(MSBEndian,p,&short_sans);
668 p=PushShortPixel(MSBEndian,p,&resolution);
669 image->resolution.y=(double) resolution;
670 (void) FormatLocaleString(value,MagickPathExtent,"%g",image->resolution.y);
671 (void) SetImageProperty(image,"tiff:YResolution",value,exception);
672 p=PushShortPixel(MSBEndian,p,&short_sans);
673 p=PushShortPixel(MSBEndian,p,&short_sans);
674 p=PushShortPixel(MSBEndian,p,&short_sans);
675 image->units=PixelsPerInchResolution;
676 break;
677 }
678 case 0x0421:
679 {
680 if (*(p+4) == 0)
681 *has_merged_image=MagickFalse;
682 p+=count;
683 break;
684 }
685 default:
686 {
687 p+=count;
688 break;
689 }
690 }
691 if ((count & 0x01) != 0)
692 p++;
693 }
694 return;
695 }
696
PSDBlendModeToCompositeOperator(const char * mode)697 static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
698 {
699 if (mode == (const char *) NULL)
700 return(OverCompositeOp);
701 if (LocaleNCompare(mode,"norm",4) == 0)
702 return(OverCompositeOp);
703 if (LocaleNCompare(mode,"mul ",4) == 0)
704 return(MultiplyCompositeOp);
705 if (LocaleNCompare(mode,"diss",4) == 0)
706 return(DissolveCompositeOp);
707 if (LocaleNCompare(mode,"diff",4) == 0)
708 return(DifferenceCompositeOp);
709 if (LocaleNCompare(mode,"dark",4) == 0)
710 return(DarkenCompositeOp);
711 if (LocaleNCompare(mode,"lite",4) == 0)
712 return(LightenCompositeOp);
713 if (LocaleNCompare(mode,"hue ",4) == 0)
714 return(HueCompositeOp);
715 if (LocaleNCompare(mode,"sat ",4) == 0)
716 return(SaturateCompositeOp);
717 if (LocaleNCompare(mode,"colr",4) == 0)
718 return(ColorizeCompositeOp);
719 if (LocaleNCompare(mode,"lum ",4) == 0)
720 return(LuminizeCompositeOp);
721 if (LocaleNCompare(mode,"scrn",4) == 0)
722 return(ScreenCompositeOp);
723 if (LocaleNCompare(mode,"over",4) == 0)
724 return(OverlayCompositeOp);
725 if (LocaleNCompare(mode,"hLit",4) == 0)
726 return(HardLightCompositeOp);
727 if (LocaleNCompare(mode,"sLit",4) == 0)
728 return(SoftLightCompositeOp);
729 if (LocaleNCompare(mode,"smud",4) == 0)
730 return(ExclusionCompositeOp);
731 if (LocaleNCompare(mode,"div ",4) == 0)
732 return(ColorDodgeCompositeOp);
733 if (LocaleNCompare(mode,"idiv",4) == 0)
734 return(ColorBurnCompositeOp);
735 if (LocaleNCompare(mode,"lbrn",4) == 0)
736 return(LinearBurnCompositeOp);
737 if (LocaleNCompare(mode,"lddg",4) == 0)
738 return(LinearDodgeCompositeOp);
739 if (LocaleNCompare(mode,"lLit",4) == 0)
740 return(LinearLightCompositeOp);
741 if (LocaleNCompare(mode,"vLit",4) == 0)
742 return(VividLightCompositeOp);
743 if (LocaleNCompare(mode,"pLit",4) == 0)
744 return(PinLightCompositeOp);
745 if (LocaleNCompare(mode,"hMix",4) == 0)
746 return(HardMixCompositeOp);
747 return(OverCompositeOp);
748 }
749
ReversePSDString(Image * image,char * p,size_t length)750 static inline void ReversePSDString(Image *image,char *p,size_t length)
751 {
752 char
753 *q;
754
755 if (image->endian == MSBEndian)
756 return;
757
758 q=p+length;
759 for(--q; p < q; ++p, --q)
760 {
761 *p = *p ^ *q,
762 *q = *p ^ *q,
763 *p = *p ^ *q;
764 }
765 }
766
SetPSDPixel(Image * image,const size_t channels,const ssize_t type,const size_t packet_size,const Quantum pixel,Quantum * q,ExceptionInfo * exception)767 static inline void SetPSDPixel(Image *image,const size_t channels,
768 const ssize_t type,const size_t packet_size,const Quantum pixel,Quantum *q,
769 ExceptionInfo *exception)
770 {
771 if (image->storage_class == PseudoClass)
772 {
773 if (packet_size == 1)
774 SetPixelIndex(image,ScaleQuantumToChar(pixel),q);
775 else
776 SetPixelIndex(image,ScaleQuantumToShort(pixel),q);
777 SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
778 ConstrainColormapIndex(image,GetPixelIndex(image,q),exception),q);
779 return;
780 }
781 switch (type)
782 {
783 case -1:
784 {
785 SetPixelAlpha(image, pixel,q);
786 break;
787 }
788 case -2:
789 case 0:
790 {
791 SetPixelRed(image,pixel,q);
792 if (channels == 1 || type == -2)
793 SetPixelGray(image,pixel,q);
794 break;
795 }
796 case 1:
797 {
798 if (image->storage_class == PseudoClass)
799 SetPixelAlpha(image,pixel,q);
800 else
801 SetPixelGreen(image,pixel,q);
802 break;
803 }
804 case 2:
805 {
806 if (image->storage_class == PseudoClass)
807 SetPixelAlpha(image,pixel,q);
808 else
809 SetPixelBlue(image,pixel,q);
810 break;
811 }
812 case 3:
813 {
814 if (image->colorspace == CMYKColorspace)
815 SetPixelBlack(image,pixel,q);
816 else
817 if (image->alpha_trait != UndefinedPixelTrait)
818 SetPixelAlpha(image,pixel,q);
819 break;
820 }
821 case 4:
822 {
823 if ((IssRGBCompatibleColorspace(image->colorspace) != MagickFalse) &&
824 (channels > 3))
825 break;
826 if (image->alpha_trait != UndefinedPixelTrait)
827 SetPixelAlpha(image,pixel,q);
828 break;
829 }
830 }
831 }
832
ReadPSDChannelPixels(Image * image,const size_t channels,const size_t row,const ssize_t type,const unsigned char * pixels,ExceptionInfo * exception)833 static MagickBooleanType ReadPSDChannelPixels(Image *image,
834 const size_t channels,const size_t row,const ssize_t type,
835 const unsigned char *pixels,ExceptionInfo *exception)
836 {
837 Quantum
838 pixel;
839
840 register const unsigned char
841 *p;
842
843 register Quantum
844 *q;
845
846 register ssize_t
847 x;
848
849 size_t
850 packet_size;
851
852 unsigned short
853 nibble;
854
855 p=pixels;
856 q=GetAuthenticPixels(image,0,row,image->columns,1,exception);
857 if (q == (Quantum *) NULL)
858 return MagickFalse;
859 packet_size=GetPSDPacketSize(image);
860 for (x=0; x < (ssize_t) image->columns; x++)
861 {
862 if (packet_size == 1)
863 pixel=ScaleCharToQuantum(*p++);
864 else
865 {
866 p=PushShortPixel(MSBEndian,p,&nibble);
867 pixel=ScaleShortToQuantum(nibble);
868 }
869 if (image->depth > 1)
870 {
871 SetPSDPixel(image,channels,type,packet_size,pixel,q,exception);
872 q+=GetPixelChannels(image);
873 }
874 else
875 {
876 ssize_t
877 bit,
878 number_bits;
879
880 number_bits=image->columns-x;
881 if (number_bits > 8)
882 number_bits=8;
883 for (bit = 0; bit < number_bits; bit++)
884 {
885 SetPSDPixel(image,channels,type,packet_size,(((unsigned char) pixel)
886 & (0x01 << (7-bit))) != 0 ? 0 : QuantumRange,q,exception);
887 q+=GetPixelChannels(image);
888 x++;
889 }
890 if (x != (ssize_t) image->columns)
891 x--;
892 continue;
893 }
894 }
895 return(SyncAuthenticPixels(image,exception));
896 }
897
ReadPSDChannelRaw(Image * image,const size_t channels,const ssize_t type,ExceptionInfo * exception)898 static MagickBooleanType ReadPSDChannelRaw(Image *image,const size_t channels,
899 const ssize_t type,ExceptionInfo *exception)
900 {
901 MagickBooleanType
902 status;
903
904 size_t
905 count,
906 row_size;
907
908 ssize_t
909 y;
910
911 unsigned char
912 *pixels;
913
914 if (image->debug != MagickFalse)
915 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
916 " layer data is RAW");
917
918 row_size=GetPSDRowSize(image);
919 pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
920 if (pixels == (unsigned char *) NULL)
921 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
922 image->filename);
923
924 status=MagickTrue;
925 for (y=0; y < (ssize_t) image->rows; y++)
926 {
927 status=MagickFalse;
928
929 count=ReadBlob(image,row_size,pixels);
930 if (count != row_size)
931 break;
932
933 status=ReadPSDChannelPixels(image,channels,y,type,pixels,exception);
934 if (status == MagickFalse)
935 break;
936 }
937
938 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
939 return(status);
940 }
941
ReadPSDRLEOffsets(Image * image,const PSDInfo * psd_info,const size_t size)942 static inline MagickOffsetType *ReadPSDRLEOffsets(Image *image,
943 const PSDInfo *psd_info,const size_t size)
944 {
945 MagickOffsetType
946 *offsets;
947
948 ssize_t
949 y;
950
951 offsets=(MagickOffsetType *) AcquireQuantumMemory(size,sizeof(*offsets));
952 if(offsets != (MagickOffsetType *) NULL)
953 {
954 for (y=0; y < (ssize_t) size; y++)
955 {
956 if (psd_info->version == 1)
957 offsets[y]=(MagickOffsetType) ReadBlobShort(image);
958 else
959 offsets[y]=(MagickOffsetType) ReadBlobLong(image);
960 }
961 }
962 return offsets;
963 }
964
ReadPSDChannelRLE(Image * image,const PSDInfo * psd_info,const ssize_t type,MagickOffsetType * offsets,ExceptionInfo * exception)965 static MagickBooleanType ReadPSDChannelRLE(Image *image,const PSDInfo *psd_info,
966 const ssize_t type,MagickOffsetType *offsets,ExceptionInfo *exception)
967 {
968 MagickBooleanType
969 status;
970
971 size_t
972 length,
973 row_size;
974
975 ssize_t
976 count,
977 y;
978
979 unsigned char
980 *compact_pixels,
981 *pixels;
982
983 if (image->debug != MagickFalse)
984 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
985 " layer data is RLE compressed");
986
987 row_size=GetPSDRowSize(image);
988 pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
989 if (pixels == (unsigned char *) NULL)
990 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
991 image->filename);
992
993 length=0;
994 for (y=0; y < (ssize_t) image->rows; y++)
995 if ((MagickOffsetType) length < offsets[y])
996 length=(size_t) offsets[y];
997
998 if (length > row_size + 256) // arbitrary number
999 {
1000 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1001 ThrowBinaryException(ResourceLimitError,"InvalidLength",
1002 image->filename);
1003 }
1004
1005 compact_pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
1006 if (compact_pixels == (unsigned char *) NULL)
1007 {
1008 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1009 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1010 image->filename);
1011 }
1012
1013 (void) ResetMagickMemory(compact_pixels,0,length*sizeof(*compact_pixels));
1014
1015 status=MagickTrue;
1016 for (y=0; y < (ssize_t) image->rows; y++)
1017 {
1018 status=MagickFalse;
1019
1020 count=ReadBlob(image,(size_t) offsets[y],compact_pixels);
1021 if (count != (ssize_t) offsets[y])
1022 break;
1023
1024 count=DecodePSDPixels((size_t) offsets[y],compact_pixels,
1025 (ssize_t) (image->depth == 1 ? 123456 : image->depth),row_size,pixels);
1026 if (count != (ssize_t) row_size)
1027 break;
1028
1029 status=ReadPSDChannelPixels(image,psd_info->channels,y,type,pixels,
1030 exception);
1031 if (status == MagickFalse)
1032 break;
1033 }
1034
1035 compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
1036 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1037 return(status);
1038 }
1039
1040 #ifdef MAGICKCORE_ZLIB_DELEGATE
ReadPSDChannelZip(Image * image,const size_t channels,const ssize_t type,const PSDCompressionType compression,const size_t compact_size,ExceptionInfo * exception)1041 static MagickBooleanType ReadPSDChannelZip(Image *image,const size_t channels,
1042 const ssize_t type,const PSDCompressionType compression,
1043 const size_t compact_size,ExceptionInfo *exception)
1044 {
1045 MagickBooleanType
1046 status;
1047
1048 register unsigned char
1049 *p;
1050
1051 size_t
1052 count,
1053 length,
1054 packet_size,
1055 row_size;
1056
1057 ssize_t
1058 y;
1059
1060 unsigned char
1061 *compact_pixels,
1062 *pixels;
1063
1064 z_stream
1065 stream;
1066
1067 if (image->debug != MagickFalse)
1068 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1069 " layer data is ZIP compressed");
1070
1071 compact_pixels=(unsigned char *) AcquireQuantumMemory(compact_size,
1072 sizeof(*compact_pixels));
1073 if (compact_pixels == (unsigned char *) NULL)
1074 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1075 image->filename);
1076
1077 packet_size=GetPSDPacketSize(image);
1078 row_size=image->columns*packet_size;
1079 count=image->rows*row_size;
1080
1081 pixels=(unsigned char *) AcquireQuantumMemory(count,sizeof(*pixels));
1082 if (pixels == (unsigned char *) NULL)
1083 {
1084 compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
1085 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1086 image->filename);
1087 }
1088
1089 ResetMagickMemory(&stream, 0, sizeof(z_stream));
1090 stream.data_type=Z_BINARY;
1091 (void) ReadBlob(image,compact_size,compact_pixels);
1092
1093 stream.next_in=(Bytef *)compact_pixels;
1094 stream.avail_in=(unsigned int) compact_size;
1095 stream.next_out=(Bytef *)pixels;
1096 stream.avail_out=(unsigned int) count;
1097
1098 if(inflateInit(&stream) == Z_OK)
1099 {
1100 int
1101 ret;
1102
1103 while (stream.avail_out > 0)
1104 {
1105 ret=inflate(&stream, Z_SYNC_FLUSH);
1106 if (ret != Z_OK && ret != Z_STREAM_END)
1107 {
1108 compact_pixels=(unsigned char *) RelinquishMagickMemory(
1109 compact_pixels);
1110 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1111 return(MagickFalse);
1112 }
1113 }
1114 }
1115
1116 if (compression == ZipWithPrediction)
1117 {
1118 p=pixels;
1119 while(count > 0)
1120 {
1121 length=image->columns;
1122 while(--length)
1123 {
1124 if (packet_size == 2)
1125 {
1126 p[2]+=p[0]+((p[1]+p[3]) >> 8);
1127 p[3]+=p[1];
1128 }
1129 else
1130 *(p+1)+=*p;
1131 p+=packet_size;
1132 }
1133 p+=packet_size;
1134 count-=row_size;
1135 }
1136 }
1137
1138 status=MagickTrue;
1139 p=pixels;
1140 for (y=0; y < (ssize_t) image->rows; y++)
1141 {
1142 status=ReadPSDChannelPixels(image,channels,y,type,p,exception);
1143 if (status == MagickFalse)
1144 break;
1145
1146 p+=row_size;
1147 }
1148
1149 compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
1150 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1151 return(status);
1152 }
1153 #endif
1154
ReadPSDChannel(Image * image,const PSDInfo * psd_info,LayerInfo * layer_info,const size_t channel,const PSDCompressionType compression,ExceptionInfo * exception)1155 static MagickBooleanType ReadPSDChannel(Image *image,const PSDInfo *psd_info,
1156 LayerInfo* layer_info,const size_t channel,
1157 const PSDCompressionType compression,ExceptionInfo *exception)
1158 {
1159 Image
1160 *channel_image,
1161 *mask;
1162
1163 MagickOffsetType
1164 offset;
1165
1166 MagickBooleanType
1167 status;
1168
1169 channel_image=image;
1170 mask=(Image *) NULL;
1171 if (layer_info->channel_info[channel].type < -1)
1172 {
1173 /*
1174 Ignore mask that is not a user supplied layer mask, if the mask is
1175 disabled or if the flags have unsupported values.
1176 */
1177 if (layer_info->channel_info[channel].type != -2 ||
1178 (layer_info->mask.flags > 3) || (layer_info->mask.flags & 0x02))
1179 {
1180 SeekBlob(image,layer_info->channel_info[channel].size-2,SEEK_CUR);
1181 return(MagickTrue);
1182 }
1183 mask=CloneImage(image,layer_info->mask.page.width,
1184 layer_info->mask.page.height,MagickFalse,exception);
1185 SetImageType(mask,GrayscaleType,exception);
1186 channel_image=mask;
1187 }
1188
1189 offset=TellBlob(image);
1190 status=MagickTrue;
1191 switch(compression)
1192 {
1193 case Raw:
1194 status=ReadPSDChannelRaw(channel_image,psd_info->channels,
1195 layer_info->channel_info[channel].type,exception);
1196 break;
1197 case RLE:
1198 {
1199 MagickOffsetType
1200 *offsets;
1201
1202 offsets=ReadPSDRLEOffsets(channel_image,psd_info,channel_image->rows);
1203 if (offsets == (MagickOffsetType *) NULL)
1204 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1205 image->filename);
1206 status=ReadPSDChannelRLE(channel_image,psd_info,
1207 layer_info->channel_info[channel].type,offsets,exception);
1208 offsets=(MagickOffsetType *) RelinquishMagickMemory(offsets);
1209 }
1210 break;
1211 case ZipWithPrediction:
1212 case ZipWithoutPrediction:
1213 #ifdef MAGICKCORE_ZLIB_DELEGATE
1214 status=ReadPSDChannelZip(channel_image,layer_info->channels,
1215 layer_info->channel_info[channel].type,compression,
1216 layer_info->channel_info[channel].size-2,exception);
1217 #else
1218 (void) ThrowMagickException(exception,GetMagickModule(),
1219 MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
1220 "'%s' (ZLIB)",image->filename);
1221 #endif
1222 break;
1223 default:
1224 (void) ThrowMagickException(exception,GetMagickModule(),TypeWarning,
1225 "CompressionNotSupported","'%.20g'",(double) compression);
1226 break;
1227 }
1228
1229 SeekBlob(image,offset+layer_info->channel_info[channel].size-2,SEEK_SET);
1230 if (status == MagickFalse)
1231 {
1232 if (mask != (Image *) NULL)
1233 DestroyImage(mask);
1234 ThrowBinaryException(CoderError,"UnableToDecompressImage",
1235 image->filename);
1236 }
1237 if (mask != (Image *) NULL)
1238 {
1239 if (status != MagickFalse)
1240 {
1241 PixelInfo
1242 color;
1243
1244 layer_info->mask.image=CloneImage(image,image->columns,image->rows,
1245 MagickTrue,exception);
1246 layer_info->mask.image->alpha_trait=UndefinedPixelTrait;
1247 GetPixelInfo(layer_info->mask.image,&color);
1248 color.red=layer_info->mask.background == 0 ? 0 : QuantumRange;
1249 SetImageColor(layer_info->mask.image,&color,exception);
1250 (void) CompositeImage(layer_info->mask.image,mask,OverCompositeOp,
1251 MagickTrue,layer_info->mask.page.x,layer_info->mask.page.y,
1252 exception);
1253 }
1254 DestroyImage(mask);
1255 }
1256
1257 return(status);
1258 }
1259
ReadPSDLayer(Image * image,const PSDInfo * psd_info,LayerInfo * layer_info,ExceptionInfo * exception)1260 static MagickBooleanType ReadPSDLayer(Image *image,const PSDInfo *psd_info,
1261 LayerInfo* layer_info,ExceptionInfo *exception)
1262 {
1263 char
1264 message[MagickPathExtent];
1265
1266 MagickBooleanType
1267 status;
1268
1269 PSDCompressionType
1270 compression;
1271
1272 ssize_t
1273 j;
1274
1275 if (image->debug != MagickFalse)
1276 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1277 " setting up new layer image");
1278 (void) SetImageBackgroundColor(layer_info->image,exception);
1279 layer_info->image->compose=PSDBlendModeToCompositeOperator(
1280 layer_info->blendkey);
1281 if (layer_info->visible == MagickFalse)
1282 layer_info->image->compose=NoCompositeOp;
1283 if (psd_info->mode == CMYKMode)
1284 SetImageColorspace(layer_info->image,CMYKColorspace,exception);
1285 if ((psd_info->mode == BitmapMode) || (psd_info->mode == GrayscaleMode) ||
1286 (psd_info->mode == DuotoneMode))
1287 SetImageColorspace(layer_info->image,GRAYColorspace,exception);
1288 /*
1289 Set up some hidden attributes for folks that need them.
1290 */
1291 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
1292 (double) layer_info->page.x);
1293 (void) SetImageArtifact(layer_info->image,"psd:layer.x",message);
1294 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
1295 (double) layer_info->page.y);
1296 (void) SetImageArtifact(layer_info->image,"psd:layer.y",message);
1297 (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
1298 layer_info->opacity);
1299 (void) SetImageArtifact(layer_info->image,"psd:layer.opacity",message);
1300 (void) SetImageProperty(layer_info->image,"label",(char *) layer_info->name,
1301 exception);
1302
1303 status=MagickTrue;
1304 for (j=0; j < (ssize_t) layer_info->channels; j++)
1305 {
1306 if (image->debug != MagickFalse)
1307 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1308 " reading data for channel %.20g",(double) j);
1309
1310 compression=(PSDCompressionType) ReadBlobShort(layer_info->image);
1311 layer_info->image->compression=ConvertPSDCompression(compression);
1312 if (layer_info->channel_info[j].type == -1)
1313 layer_info->image->alpha_trait=BlendPixelTrait;
1314
1315 status=ReadPSDChannel(layer_info->image,psd_info,layer_info,j,
1316 compression,exception);
1317
1318 if (status == MagickFalse)
1319 break;
1320 }
1321
1322 if (status != MagickFalse)
1323 status=CorrectPSDOpacity(layer_info,exception);
1324
1325 if ((status != MagickFalse) &&
1326 (layer_info->image->colorspace == CMYKColorspace))
1327 status=NegateCMYK(layer_info->image,exception);
1328
1329 if ((status != MagickFalse) && (layer_info->mask.image != (Image *) NULL))
1330 {
1331 status=CompositeImage(layer_info->image,layer_info->mask.image,
1332 CopyAlphaCompositeOp,MagickTrue,0,0,exception);
1333 layer_info->mask.image=DestroyImage(layer_info->mask.image);
1334 }
1335
1336 return(status);
1337 }
1338
ReadPSDLayers(Image * image,const ImageInfo * image_info,const PSDInfo * psd_info,const MagickBooleanType skip_layers,ExceptionInfo * exception)1339 ModuleExport MagickBooleanType ReadPSDLayers(Image *image,
1340 const ImageInfo *image_info,const PSDInfo *psd_info,
1341 const MagickBooleanType skip_layers,ExceptionInfo *exception)
1342 {
1343 char
1344 type[4];
1345
1346 LayerInfo
1347 *layer_info;
1348
1349 MagickSizeType
1350 size;
1351
1352 MagickBooleanType
1353 status;
1354
1355 register ssize_t
1356 i;
1357
1358 ssize_t
1359 count,
1360 j,
1361 number_layers;
1362
1363 size=GetPSDSize(psd_info,image);
1364 if (size == 0)
1365 {
1366 /*
1367 Skip layers & masks.
1368 */
1369 (void) ReadBlobLong(image);
1370 count=ReadBlob(image,4,(unsigned char *) type);
1371 ReversePSDString(image,type,4);
1372 status=MagickFalse;
1373 if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
1374 return(MagickTrue);
1375 else
1376 {
1377 count=ReadBlob(image,4,(unsigned char *) type);
1378 ReversePSDString(image,type,4);
1379 if ((count != 0) && (LocaleNCompare(type,"Lr16",4) == 0))
1380 size=GetPSDSize(psd_info,image);
1381 else
1382 return(MagickTrue);
1383 }
1384 }
1385 status=MagickTrue;
1386 if (size != 0)
1387 {
1388 layer_info=(LayerInfo *) NULL;
1389 number_layers=(short) ReadBlobShort(image);
1390
1391 if (number_layers < 0)
1392 {
1393 /*
1394 The first alpha channel in the merged result contains the
1395 transparency data for the merged result.
1396 */
1397 number_layers=MagickAbsoluteValue(number_layers);
1398 if (image->debug != MagickFalse)
1399 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1400 " negative layer count corrected for");
1401 image->alpha_trait=BlendPixelTrait;
1402 }
1403
1404 /*
1405 We only need to know if the image has an alpha channel
1406 */
1407 if (skip_layers != MagickFalse)
1408 return(MagickTrue);
1409
1410 if (image->debug != MagickFalse)
1411 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1412 " image contains %.20g layers",(double) number_layers);
1413
1414 if (number_layers == 0)
1415 ThrowBinaryException(CorruptImageError,"InvalidNumberOfLayers",
1416 image->filename);
1417
1418 layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
1419 sizeof(*layer_info));
1420 if (layer_info == (LayerInfo *) NULL)
1421 {
1422 if (image->debug != MagickFalse)
1423 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1424 " allocation of LayerInfo failed");
1425 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1426 image->filename);
1427 }
1428 (void) ResetMagickMemory(layer_info,0,(size_t) number_layers*
1429 sizeof(*layer_info));
1430
1431 for (i=0; i < number_layers; i++)
1432 {
1433 ssize_t
1434 x,
1435 y;
1436
1437 if (image->debug != MagickFalse)
1438 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1439 " reading layer #%.20g",(double) i+1);
1440 layer_info[i].page.y=ReadBlobSignedLong(image);
1441 layer_info[i].page.x=ReadBlobSignedLong(image);
1442 y=ReadBlobSignedLong(image);
1443 x=ReadBlobSignedLong(image);
1444 layer_info[i].page.width=(size_t) (x-layer_info[i].page.x);
1445 layer_info[i].page.height=(size_t) (y-layer_info[i].page.y);
1446 layer_info[i].channels=ReadBlobShort(image);
1447 if (layer_info[i].channels > MaxPSDChannels)
1448 {
1449 layer_info=DestroyLayerInfo(layer_info,number_layers);
1450 ThrowBinaryException(CorruptImageError,"MaximumChannelsExceeded",
1451 image->filename);
1452 }
1453 if (image->debug != MagickFalse)
1454 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1455 " offset(%.20g,%.20g), size(%.20g,%.20g), channels=%.20g",
1456 (double) layer_info[i].page.x,(double) layer_info[i].page.y,
1457 (double) layer_info[i].page.height,(double)
1458 layer_info[i].page.width,(double) layer_info[i].channels);
1459 for (j=0; j < (ssize_t) layer_info[i].channels; j++)
1460 {
1461 layer_info[i].channel_info[j].type=(short) ReadBlobShort(image);
1462 layer_info[i].channel_info[j].size=(size_t) GetPSDSize(psd_info,
1463 image);
1464 if (image->debug != MagickFalse)
1465 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1466 " channel[%.20g]: type=%.20g, size=%.20g",(double) j,
1467 (double) layer_info[i].channel_info[j].type,
1468 (double) layer_info[i].channel_info[j].size);
1469 }
1470 count=ReadBlob(image,4,(unsigned char *) type);
1471 ReversePSDString(image,type,4);
1472 if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
1473 {
1474 if (image->debug != MagickFalse)
1475 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1476 " layer type was %.4s instead of 8BIM", type);
1477 layer_info=DestroyLayerInfo(layer_info,number_layers);
1478 ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
1479 image->filename);
1480 }
1481 count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
1482 ReversePSDString(image,layer_info[i].blendkey,4);
1483 layer_info[i].opacity=(Quantum) ScaleCharToQuantum((unsigned char)
1484 ReadBlobByte(image));
1485 layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
1486 layer_info[i].flags=(unsigned char) ReadBlobByte(image);
1487 layer_info[i].visible=!(layer_info[i].flags & 0x02);
1488 if (image->debug != MagickFalse)
1489 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1490 " blend=%.4s, opacity=%.20g, clipping=%s, flags=%d, visible=%s",
1491 layer_info[i].blendkey,(double) layer_info[i].opacity,
1492 layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
1493 layer_info[i].visible ? "true" : "false");
1494 (void) ReadBlobByte(image); /* filler */
1495
1496 size=ReadBlobLong(image);
1497 if (size != 0)
1498 {
1499 MagickSizeType
1500 combined_length,
1501 length;
1502
1503 if (image->debug != MagickFalse)
1504 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1505 " layer contains additional info");
1506 length=ReadBlobLong(image);
1507 combined_length=length+4;
1508 if (length != 0)
1509 {
1510 /*
1511 Layer mask info.
1512 */
1513 layer_info[i].mask.page.y=ReadBlobSignedLong(image);
1514 layer_info[i].mask.page.x=ReadBlobSignedLong(image);
1515 layer_info[i].mask.page.height=(size_t) (ReadBlobLong(image)-
1516 layer_info[i].mask.page.y);
1517 layer_info[i].mask.page.width=(size_t) (ReadBlobLong(image)-
1518 layer_info[i].mask.page.x);
1519 layer_info[i].mask.background=(unsigned char) ReadBlobByte(
1520 image);
1521 layer_info[i].mask.flags=(unsigned char) ReadBlobByte(image);
1522 if (!(layer_info[i].mask.flags & 0x01))
1523 {
1524 layer_info[i].mask.page.y=layer_info[i].mask.page.y-
1525 layer_info[i].page.y;
1526 layer_info[i].mask.page.x=layer_info[i].mask.page.x-
1527 layer_info[i].page.x;
1528 }
1529 if (image->debug != MagickFalse)
1530 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1531 " layer mask: offset(%.20g,%.20g), size(%.20g,%.20g), length=%.20g",
1532 (double) layer_info[i].mask.page.x,(double)
1533 layer_info[i].mask.page.y,(double) layer_info[i].mask.page.width,
1534 (double) layer_info[i].mask.page.height,(double)
1535 ((MagickOffsetType) length)-18);
1536 /*
1537 Skip over the rest of the layer mask information.
1538 */
1539 if (DiscardBlobBytes(image,(MagickSizeType) (length-18)) == MagickFalse)
1540 {
1541 layer_info=DestroyLayerInfo(layer_info,number_layers);
1542 ThrowBinaryException(CorruptImageError,"UnexpectedEndOfFile",
1543 image->filename);
1544 }
1545 }
1546 length=ReadBlobLong(image);
1547 combined_length+=length+4;
1548 if (length != 0)
1549 {
1550 /*
1551 Layer blending ranges info.
1552 */
1553 if (image->debug != MagickFalse)
1554 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1555 " layer blending ranges: length=%.20g",(double)
1556 ((MagickOffsetType) length));
1557 /*
1558 We read it, but don't use it...
1559 */
1560 for (j=0; j < (ssize_t) (length); j+=8)
1561 {
1562 size_t blend_source=ReadBlobLong(image);
1563 size_t blend_dest=ReadBlobLong(image);
1564 if (image->debug != MagickFalse)
1565 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1566 " source(%x), dest(%x)",(unsigned int)
1567 blend_source,(unsigned int) blend_dest);
1568 }
1569 }
1570 /*
1571 Layer name.
1572 */
1573 length=(size_t) ReadBlobByte(image);
1574 combined_length+=length+1;
1575 if (length > 0)
1576 (void) ReadBlob(image,(size_t) length++,layer_info[i].name);
1577 layer_info[i].name[length]='\0';
1578 if (image->debug != MagickFalse)
1579 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1580 " layer name: %s",layer_info[i].name);
1581 /*
1582 Skip the rest of the variable data until we support it.
1583 */
1584 if (image->debug != MagickFalse)
1585 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1586 " unsupported data: length=%.20g",(double)
1587 ((MagickOffsetType) (size-combined_length)));
1588 if (DiscardBlobBytes(image,(MagickSizeType) (size-combined_length)) == MagickFalse)
1589 {
1590 layer_info=DestroyLayerInfo(layer_info,number_layers);
1591 ThrowBinaryException(CorruptImageError,
1592 "UnexpectedEndOfFile",image->filename);
1593 }
1594 }
1595 }
1596
1597 for (i=0; i < number_layers; i++)
1598 {
1599 if ((layer_info[i].page.width == 0) ||
1600 (layer_info[i].page.height == 0))
1601 {
1602 if (image->debug != MagickFalse)
1603 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1604 " layer data is empty");
1605 continue;
1606 }
1607
1608 /*
1609 Allocate layered image.
1610 */
1611 layer_info[i].image=CloneImage(image,layer_info[i].page.width,
1612 layer_info[i].page.height,MagickFalse,exception);
1613 if (layer_info[i].image == (Image *) NULL)
1614 {
1615 layer_info=DestroyLayerInfo(layer_info,number_layers);
1616 if (image->debug != MagickFalse)
1617 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1618 " allocation of image for layer %.20g failed",(double) i);
1619 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1620 image->filename);
1621 }
1622 }
1623
1624 if (image_info->ping == MagickFalse)
1625 {
1626 for (i=0; i < number_layers; i++)
1627 {
1628 if (layer_info[i].image == (Image *) NULL)
1629 {
1630 for (j=0; j < layer_info[i].channels; j++)
1631 {
1632 if (DiscardBlobBytes(image,(MagickSizeType)
1633 layer_info[i].channel_info[j].size) == MagickFalse)
1634 {
1635 layer_info=DestroyLayerInfo(layer_info,number_layers);
1636 ThrowBinaryException(CorruptImageError,
1637 "UnexpectedEndOfFile",image->filename);
1638 }
1639 }
1640 continue;
1641 }
1642
1643 if (image->debug != MagickFalse)
1644 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1645 " reading data for layer %.20g",(double) i);
1646
1647 status=ReadPSDLayer(image,psd_info,&layer_info[i],exception);
1648 if (status == MagickFalse)
1649 break;
1650
1651 status=SetImageProgress(image,LoadImagesTag,i,(MagickSizeType)
1652 number_layers);
1653 if (status == MagickFalse)
1654 break;
1655 }
1656 }
1657
1658 if (status != MagickFalse)
1659 {
1660 for (i=0; i < number_layers; i++)
1661 {
1662 if (layer_info[i].image == (Image *) NULL)
1663 {
1664 for (j=i; j < number_layers - 1; j++)
1665 layer_info[j] = layer_info[j+1];
1666 number_layers--;
1667 i--;
1668 }
1669 }
1670
1671 if (number_layers > 0)
1672 {
1673 for (i=0; i < number_layers; i++)
1674 {
1675 if (i > 0)
1676 layer_info[i].image->previous=layer_info[i-1].image;
1677 if (i < (number_layers-1))
1678 layer_info[i].image->next=layer_info[i+1].image;
1679 layer_info[i].image->page=layer_info[i].page;
1680 }
1681 image->next=layer_info[0].image;
1682 layer_info[0].image->previous=image;
1683 }
1684 layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
1685 }
1686 else
1687 layer_info=DestroyLayerInfo(layer_info,number_layers);
1688 }
1689
1690 return(status);
1691 }
1692
ReadPSDMergedImage(const ImageInfo * image_info,Image * image,const PSDInfo * psd_info,ExceptionInfo * exception)1693 static MagickBooleanType ReadPSDMergedImage(const ImageInfo *image_info,
1694 Image *image,const PSDInfo *psd_info,ExceptionInfo *exception)
1695 {
1696 MagickOffsetType
1697 *offsets;
1698
1699 MagickBooleanType
1700 status;
1701
1702 PSDCompressionType
1703 compression;
1704
1705 register ssize_t
1706 i;
1707
1708 compression=(PSDCompressionType) ReadBlobMSBShort(image);
1709 image->compression=ConvertPSDCompression(compression);
1710
1711 if (compression != Raw && compression != RLE)
1712 {
1713 (void) ThrowMagickException(exception,GetMagickModule(),
1714 TypeWarning,"CompressionNotSupported","'%.20g'",(double) compression);
1715 return(MagickFalse);
1716 }
1717
1718 offsets=(MagickOffsetType *) NULL;
1719 if (compression == RLE)
1720 {
1721 offsets=ReadPSDRLEOffsets(image,psd_info,image->rows*psd_info->channels);
1722 if (offsets == (MagickOffsetType *) NULL)
1723 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1724 image->filename);
1725 }
1726
1727 status=MagickTrue;
1728 for (i=0; i < (ssize_t) psd_info->channels; i++)
1729 {
1730 if (compression == RLE)
1731 status=ReadPSDChannelRLE(image,psd_info,i,offsets+(i*image->rows),
1732 exception);
1733 else
1734 status=ReadPSDChannelRaw(image,psd_info->channels,i,exception);
1735
1736 if (status != MagickFalse)
1737 status=SetImageProgress(image,LoadImagesTag,i,psd_info->channels);
1738
1739 if (status == MagickFalse)
1740 break;
1741 }
1742
1743 if ((status != MagickFalse) && (image->colorspace == CMYKColorspace))
1744 status=NegateCMYK(image,exception);
1745
1746 if (status != MagickFalse)
1747 status=CorrectPSDAlphaBlend(image_info,image,exception);
1748
1749 if (offsets != (MagickOffsetType *) NULL)
1750 offsets=(MagickOffsetType *) RelinquishMagickMemory(offsets);
1751
1752 return(status);
1753 }
1754
ReadPSDImage(const ImageInfo * image_info,ExceptionInfo * exception)1755 static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
1756 {
1757 Image
1758 *image;
1759
1760 MagickBooleanType
1761 has_merged_image,
1762 skip_layers;
1763
1764 MagickOffsetType
1765 offset;
1766
1767 MagickSizeType
1768 length;
1769
1770 MagickBooleanType
1771 status;
1772
1773 PSDInfo
1774 psd_info;
1775
1776 register ssize_t
1777 i;
1778
1779 ssize_t
1780 count;
1781
1782 unsigned char
1783 *data;
1784
1785 /*
1786 Open image file.
1787 */
1788 assert(image_info != (const ImageInfo *) NULL);
1789 assert(image_info->signature == MagickCoreSignature);
1790 if (image_info->debug != MagickFalse)
1791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1792 image_info->filename);
1793 assert(exception != (ExceptionInfo *) NULL);
1794 assert(exception->signature == MagickCoreSignature);
1795
1796 image=AcquireImage(image_info,exception);
1797 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1798 if (status == MagickFalse)
1799 {
1800 image=DestroyImageList(image);
1801 return((Image *) NULL);
1802 }
1803 /*
1804 Read image header.
1805 */
1806 image->endian=MSBEndian;
1807 count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
1808 psd_info.version=ReadBlobMSBShort(image);
1809 if ((count == 0) || (LocaleNCompare(psd_info.signature,"8BPS",4) != 0) ||
1810 ((psd_info.version != 1) && (psd_info.version != 2)))
1811 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1812 (void) ReadBlob(image,6,psd_info.reserved);
1813 psd_info.channels=ReadBlobMSBShort(image);
1814 if (psd_info.channels > MaxPSDChannels)
1815 ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
1816 psd_info.rows=ReadBlobMSBLong(image);
1817 psd_info.columns=ReadBlobMSBLong(image);
1818 if ((psd_info.version == 1) && ((psd_info.rows > 30000) ||
1819 (psd_info.columns > 30000)))
1820 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1821 psd_info.depth=ReadBlobMSBShort(image);
1822 if ((psd_info.depth != 1) && (psd_info.depth != 8) && (psd_info.depth != 16))
1823 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1824 psd_info.mode=ReadBlobMSBShort(image);
1825 if (image->debug != MagickFalse)
1826 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1827 " Image is %.20g x %.20g with channels=%.20g, depth=%.20g, mode=%s",
1828 (double) psd_info.columns,(double) psd_info.rows,(double)
1829 psd_info.channels,(double) psd_info.depth,ModeToString((PSDImageType)
1830 psd_info.mode));
1831 /*
1832 Initialize image.
1833 */
1834 image->depth=psd_info.depth;
1835 image->columns=psd_info.columns;
1836 image->rows=psd_info.rows;
1837 status=SetImageExtent(image,image->columns,image->rows,exception);
1838 if (status == MagickFalse)
1839 return(DestroyImageList(image));
1840 if (SetImageBackgroundColor(image,exception) == MagickFalse)
1841 {
1842 image=DestroyImageList(image);
1843 return((Image *) NULL);
1844 }
1845 if (psd_info.mode == LabMode)
1846 SetImageColorspace(image,LabColorspace,exception);
1847 if (psd_info.mode == CMYKMode)
1848 {
1849 SetImageColorspace(image,CMYKColorspace,exception);
1850 image->alpha_trait=psd_info.channels > 4 ? BlendPixelTrait :
1851 UndefinedPixelTrait;
1852 }
1853 else if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
1854 (psd_info.mode == DuotoneMode))
1855 {
1856 status=AcquireImageColormap(image,psd_info.depth != 16 ? 256 : 65536,
1857 exception);
1858 if (status == MagickFalse)
1859 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1860 if (image->debug != MagickFalse)
1861 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1862 " Image colormap allocated");
1863 SetImageColorspace(image,GRAYColorspace,exception);
1864 image->alpha_trait=psd_info.channels > 1 ? BlendPixelTrait :
1865 UndefinedPixelTrait;
1866 }
1867 else
1868 image->alpha_trait=psd_info.channels > 3 ? BlendPixelTrait :
1869 UndefinedPixelTrait;
1870 /*
1871 Read PSD raster colormap only present for indexed and duotone images.
1872 */
1873 length=ReadBlobMSBLong(image);
1874 if (length != 0)
1875 {
1876 if (image->debug != MagickFalse)
1877 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1878 " reading colormap");
1879 if (psd_info.mode == DuotoneMode)
1880 {
1881 /*
1882 Duotone image data; the format of this data is undocumented.
1883 */
1884 data=(unsigned char *) AcquireQuantumMemory((size_t) length,
1885 sizeof(*data));
1886 if (data == (unsigned char *) NULL)
1887 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1888 (void) ReadBlob(image,(size_t) length,data);
1889 data=(unsigned char *) RelinquishMagickMemory(data);
1890 }
1891 else
1892 {
1893 size_t
1894 number_colors;
1895
1896 /*
1897 Read PSD raster colormap.
1898 */
1899 number_colors=length/3;
1900 if (number_colors > 65536)
1901 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1902 if (AcquireImageColormap(image,number_colors,exception) == MagickFalse)
1903 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1904 for (i=0; i < (ssize_t) image->colors; i++)
1905 image->colormap[i].red=ScaleCharToQuantum((unsigned char)
1906 ReadBlobByte(image));
1907 for (i=0; i < (ssize_t) image->colors; i++)
1908 image->colormap[i].green=ScaleCharToQuantum((unsigned char)
1909 ReadBlobByte(image));
1910 for (i=0; i < (ssize_t) image->colors; i++)
1911 image->colormap[i].blue=ScaleCharToQuantum((unsigned char)
1912 ReadBlobByte(image));
1913 image->alpha_trait=UndefinedPixelTrait;
1914 }
1915 }
1916 if ((image->depth == 1) && (image->storage_class != PseudoClass))
1917 ThrowReaderException(CorruptImageError, "ImproperImageHeader");
1918 has_merged_image=MagickTrue;
1919 length=ReadBlobMSBLong(image);
1920 if (length != 0)
1921 {
1922 unsigned char
1923 *blocks;
1924
1925 /*
1926 Image resources block.
1927 */
1928 if (image->debug != MagickFalse)
1929 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1930 " reading image resource blocks - %.20g bytes",(double)
1931 ((MagickOffsetType) length));
1932 blocks=(unsigned char *) AcquireQuantumMemory((size_t) length,
1933 sizeof(*blocks));
1934 if (blocks == (unsigned char *) NULL)
1935 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1936 count=ReadBlob(image,(size_t) length,blocks);
1937 if ((count != (ssize_t) length) || (length < 4) ||
1938 (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
1939 {
1940 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
1941 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1942 }
1943 ParseImageResourceBlocks(image,blocks,(size_t) length,&has_merged_image,
1944 exception);
1945 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
1946 }
1947 /*
1948 Layer and mask block.
1949 */
1950 length=GetPSDSize(&psd_info,image);
1951 if (length == 8)
1952 {
1953 length=ReadBlobMSBLong(image);
1954 length=ReadBlobMSBLong(image);
1955 }
1956 offset=TellBlob(image);
1957 skip_layers=MagickFalse;
1958 if ((image_info->number_scenes == 1) && (image_info->scene == 0) &&
1959 (has_merged_image != MagickFalse))
1960 {
1961 if (image->debug != MagickFalse)
1962 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1963 " read composite only");
1964 skip_layers=MagickTrue;
1965 }
1966 if (length == 0)
1967 {
1968 if (image->debug != MagickFalse)
1969 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1970 " image has no layers");
1971 }
1972 else
1973 {
1974 if (ReadPSDLayers(image,image_info,&psd_info,skip_layers,exception) !=
1975 MagickTrue)
1976 {
1977 (void) CloseBlob(image);
1978 image=DestroyImageList(image);
1979 return((Image *) NULL);
1980 }
1981
1982 /*
1983 Skip the rest of the layer and mask information.
1984 */
1985 SeekBlob(image,offset+length,SEEK_SET);
1986 }
1987 /*
1988 If we are only "pinging" the image, then we're done - so return.
1989 */
1990 if (image_info->ping != MagickFalse)
1991 {
1992 (void) CloseBlob(image);
1993 return(GetFirstImageInList(image));
1994 }
1995 /*
1996 Read the precombined layer, present for PSD < 4 compatibility.
1997 */
1998 if (image->debug != MagickFalse)
1999 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2000 " reading the precombined layer");
2001 if ((has_merged_image != MagickFalse) || (GetImageListLength(image) == 1))
2002 has_merged_image=(MagickBooleanType) ReadPSDMergedImage(image_info,image,
2003 &psd_info,exception);
2004 if ((has_merged_image == MagickFalse) && (GetImageListLength(image) == 1) &&
2005 (length != 0))
2006 {
2007 SeekBlob(image,offset,SEEK_SET);
2008 status=ReadPSDLayers(image,image_info,&psd_info,MagickFalse,exception);
2009 if (status != MagickTrue)
2010 {
2011 (void) CloseBlob(image);
2012 image=DestroyImageList(image);
2013 return((Image *) NULL);
2014 }
2015 }
2016 if ((has_merged_image == MagickFalse) && (GetImageListLength(image) > 1))
2017 {
2018 Image
2019 *merged;
2020
2021 SetImageAlphaChannel(image,TransparentAlphaChannel,exception);
2022 image->background_color.alpha=TransparentAlpha;
2023 image->background_color.alpha_trait=BlendPixelTrait;
2024 merged=MergeImageLayers(image,FlattenLayer,exception);
2025 ReplaceImageInList(&image,merged);
2026 }
2027 (void) CloseBlob(image);
2028 return(GetFirstImageInList(image));
2029 }
2030
2031 /*
2032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2033 % %
2034 % %
2035 % %
2036 % R e g i s t e r P S D I m a g e %
2037 % %
2038 % %
2039 % %
2040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2041 %
2042 % RegisterPSDImage() adds properties for the PSD image format to
2043 % the list of supported formats. The properties include the image format
2044 % tag, a method to read and/or write the format, whether the format
2045 % supports the saving of more than one frame to the same file or blob,
2046 % whether the format supports native in-memory I/O, and a brief
2047 % description of the format.
2048 %
2049 % The format of the RegisterPSDImage method is:
2050 %
2051 % size_t RegisterPSDImage(void)
2052 %
2053 */
RegisterPSDImage(void)2054 ModuleExport size_t RegisterPSDImage(void)
2055 {
2056 MagickInfo
2057 *entry;
2058
2059 entry=AcquireMagickInfo("PSD","PSB","Adobe Large Document Format");
2060 entry->decoder=(DecodeImageHandler *) ReadPSDImage;
2061 entry->encoder=(EncodeImageHandler *) WritePSDImage;
2062 entry->magick=(IsImageFormatHandler *) IsPSD;
2063 entry->flags|=CoderSeekableStreamFlag;
2064 (void) RegisterMagickInfo(entry);
2065 entry=AcquireMagickInfo("PSD","PSD","Adobe Photoshop bitmap");
2066 entry->decoder=(DecodeImageHandler *) ReadPSDImage;
2067 entry->encoder=(EncodeImageHandler *) WritePSDImage;
2068 entry->magick=(IsImageFormatHandler *) IsPSD;
2069 entry->flags|=CoderSeekableStreamFlag;
2070 (void) RegisterMagickInfo(entry);
2071 return(MagickImageCoderSignature);
2072 }
2073
2074 /*
2075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2076 % %
2077 % %
2078 % %
2079 % U n r e g i s t e r P S D I m a g e %
2080 % %
2081 % %
2082 % %
2083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2084 %
2085 % UnregisterPSDImage() removes format registrations made by the
2086 % PSD module from the list of supported formats.
2087 %
2088 % The format of the UnregisterPSDImage method is:
2089 %
2090 % UnregisterPSDImage(void)
2091 %
2092 */
UnregisterPSDImage(void)2093 ModuleExport void UnregisterPSDImage(void)
2094 {
2095 (void) UnregisterMagickInfo("PSB");
2096 (void) UnregisterMagickInfo("PSD");
2097 }
2098
2099 /*
2100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2101 % %
2102 % %
2103 % %
2104 % W r i t e P S D I m a g e %
2105 % %
2106 % %
2107 % %
2108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2109 %
2110 % WritePSDImage() writes an image in the Adobe Photoshop encoded image format.
2111 %
2112 % The format of the WritePSDImage method is:
2113 %
2114 % MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image,
2115 % ExceptionInfo *exception)
2116 %
2117 % A description of each parameter follows.
2118 %
2119 % o image_info: the image info.
2120 %
2121 % o image: The image.
2122 %
2123 % o exception: return any errors or warnings in this structure.
2124 %
2125 */
2126
SetPSDOffset(const PSDInfo * psd_info,Image * image,const size_t offset)2127 static inline ssize_t SetPSDOffset(const PSDInfo *psd_info,Image *image,
2128 const size_t offset)
2129 {
2130 if (psd_info->version == 1)
2131 return(WriteBlobMSBShort(image,(unsigned short) offset));
2132 return(WriteBlobMSBLong(image,(unsigned short) offset));
2133 }
2134
SetPSDSize(const PSDInfo * psd_info,Image * image,const MagickSizeType size)2135 static inline ssize_t SetPSDSize(const PSDInfo *psd_info,Image *image,
2136 const MagickSizeType size)
2137 {
2138 if (psd_info->version == 1)
2139 return(WriteBlobMSBLong(image,(unsigned int) size));
2140 return(WriteBlobMSBLongLong(image,size));
2141 }
2142
PSDPackbitsEncodeImage(Image * image,const size_t length,const unsigned char * pixels,unsigned char * compact_pixels,ExceptionInfo * exception)2143 static size_t PSDPackbitsEncodeImage(Image *image,const size_t length,
2144 const unsigned char *pixels,unsigned char *compact_pixels,
2145 ExceptionInfo *exception)
2146 {
2147 int
2148 count;
2149
2150 register ssize_t
2151 i,
2152 j;
2153
2154 register unsigned char
2155 *q;
2156
2157 unsigned char
2158 *packbits;
2159
2160 /*
2161 Compress pixels with Packbits encoding.
2162 */
2163 assert(image != (Image *) NULL);
2164 assert(image->signature == MagickCoreSignature);
2165 if (image->debug != MagickFalse)
2166 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2167 assert(pixels != (unsigned char *) NULL);
2168 packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
2169 if (packbits == (unsigned char *) NULL)
2170 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2171 image->filename);
2172 q=compact_pixels;
2173 for (i=(ssize_t) length; i != 0; )
2174 {
2175 switch (i)
2176 {
2177 case 1:
2178 {
2179 i--;
2180 *q++=(unsigned char) 0;
2181 *q++=(*pixels);
2182 break;
2183 }
2184 case 2:
2185 {
2186 i-=2;
2187 *q++=(unsigned char) 1;
2188 *q++=(*pixels);
2189 *q++=pixels[1];
2190 break;
2191 }
2192 case 3:
2193 {
2194 i-=3;
2195 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
2196 {
2197 *q++=(unsigned char) ((256-3)+1);
2198 *q++=(*pixels);
2199 break;
2200 }
2201 *q++=(unsigned char) 2;
2202 *q++=(*pixels);
2203 *q++=pixels[1];
2204 *q++=pixels[2];
2205 break;
2206 }
2207 default:
2208 {
2209 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
2210 {
2211 /*
2212 Packed run.
2213 */
2214 count=3;
2215 while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
2216 {
2217 count++;
2218 if (count >= 127)
2219 break;
2220 }
2221 i-=count;
2222 *q++=(unsigned char) ((256-count)+1);
2223 *q++=(*pixels);
2224 pixels+=count;
2225 break;
2226 }
2227 /*
2228 Literal run.
2229 */
2230 count=0;
2231 while ((*(pixels+count) != *(pixels+count+1)) ||
2232 (*(pixels+count+1) != *(pixels+count+2)))
2233 {
2234 packbits[count+1]=pixels[count];
2235 count++;
2236 if (((ssize_t) count >= (i-3)) || (count >= 127))
2237 break;
2238 }
2239 i-=count;
2240 *packbits=(unsigned char) (count-1);
2241 for (j=0; j <= (ssize_t) count; j++)
2242 *q++=packbits[j];
2243 pixels+=count;
2244 break;
2245 }
2246 }
2247 }
2248 *q++=(unsigned char) 128; /* EOD marker */
2249 packbits=(unsigned char *) RelinquishMagickMemory(packbits);
2250 return((size_t) (q-compact_pixels));
2251 }
2252
WritePackbitsLength(const PSDInfo * psd_info,const ImageInfo * image_info,Image * image,Image * next_image,unsigned char * compact_pixels,const QuantumType quantum_type,ExceptionInfo * exception)2253 static void WritePackbitsLength(const PSDInfo *psd_info,
2254 const ImageInfo *image_info,Image *image,Image *next_image,
2255 unsigned char *compact_pixels,const QuantumType quantum_type,
2256 ExceptionInfo *exception)
2257 {
2258 QuantumInfo
2259 *quantum_info;
2260
2261 register const Quantum
2262 *p;
2263
2264 size_t
2265 length,
2266 packet_size;
2267
2268 ssize_t
2269 y;
2270
2271 unsigned char
2272 *pixels;
2273
2274 if (next_image->depth > 8)
2275 next_image->depth=16;
2276 packet_size=next_image->depth > 8UL ? 2UL : 1UL;
2277 (void) packet_size;
2278 quantum_info=AcquireQuantumInfo(image_info,image);
2279 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
2280 for (y=0; y < (ssize_t) next_image->rows; y++)
2281 {
2282 p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception);
2283 if (p == (const Quantum *) NULL)
2284 break;
2285 length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info,
2286 quantum_type,pixels,exception);
2287 length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels,
2288 exception);
2289 (void) SetPSDOffset(psd_info,image,length);
2290 }
2291 quantum_info=DestroyQuantumInfo(quantum_info);
2292 }
2293
WriteOneChannel(const PSDInfo * psd_info,const ImageInfo * image_info,Image * image,Image * next_image,unsigned char * compact_pixels,const QuantumType quantum_type,const MagickBooleanType compression_flag,ExceptionInfo * exception)2294 static void WriteOneChannel(const PSDInfo *psd_info,const ImageInfo *image_info,
2295 Image *image,Image *next_image,unsigned char *compact_pixels,
2296 const QuantumType quantum_type,const MagickBooleanType compression_flag,
2297 ExceptionInfo *exception)
2298 {
2299 int
2300 y;
2301
2302 MagickBooleanType
2303 monochrome;
2304
2305 QuantumInfo
2306 *quantum_info;
2307
2308 register const Quantum
2309 *p;
2310
2311 register ssize_t
2312 i;
2313
2314 size_t
2315 length,
2316 packet_size;
2317
2318 unsigned char
2319 *pixels;
2320
2321 (void) psd_info;
2322 if ((compression_flag != MagickFalse) &&
2323 (next_image->compression != RLECompression))
2324 (void) WriteBlobMSBShort(image,0);
2325 if (next_image->depth > 8)
2326 next_image->depth=16;
2327 monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
2328 MagickTrue : MagickFalse;
2329 packet_size=next_image->depth > 8UL ? 2UL : 1UL;
2330 (void) packet_size;
2331 quantum_info=AcquireQuantumInfo(image_info,image);
2332 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
2333 for (y=0; y < (ssize_t) next_image->rows; y++)
2334 {
2335 p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception);
2336 if (p == (const Quantum *) NULL)
2337 break;
2338 length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info,
2339 quantum_type,pixels,exception);
2340 if (monochrome != MagickFalse)
2341 for (i=0; i < (ssize_t) length; i++)
2342 pixels[i]=(~pixels[i]);
2343 if (next_image->compression != RLECompression)
2344 (void) WriteBlob(image,length,pixels);
2345 else
2346 {
2347 length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels,
2348 exception);
2349 (void) WriteBlob(image,length,compact_pixels);
2350 }
2351 }
2352 quantum_info=DestroyQuantumInfo(quantum_info);
2353 }
2354
WriteImageChannels(const PSDInfo * psd_info,const ImageInfo * image_info,Image * image,Image * next_image,const MagickBooleanType separate,ExceptionInfo * exception)2355 static MagickBooleanType WriteImageChannels(const PSDInfo *psd_info,
2356 const ImageInfo *image_info,Image *image,Image *next_image,
2357 const MagickBooleanType separate,ExceptionInfo *exception)
2358 {
2359 size_t
2360 channels,
2361 packet_size;
2362
2363 unsigned char
2364 *compact_pixels;
2365
2366 /*
2367 Write uncompressed pixels as separate planes.
2368 */
2369 channels=1;
2370 packet_size=next_image->depth > 8UL ? 2UL : 1UL;
2371 compact_pixels=(unsigned char *) NULL;
2372 if (next_image->compression == RLECompression)
2373 {
2374 compact_pixels=(unsigned char *) AcquireQuantumMemory((9*channels*
2375 next_image->columns)+1,packet_size*sizeof(*compact_pixels));
2376 if (compact_pixels == (unsigned char *) NULL)
2377 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2378 }
2379 if (IsImageGray(next_image) != MagickFalse)
2380 {
2381 if (next_image->compression == RLECompression)
2382 {
2383 /*
2384 Packbits compression.
2385 */
2386 (void) WriteBlobMSBShort(image,1);
2387 WritePackbitsLength(psd_info,image_info,image,next_image,
2388 compact_pixels,GrayQuantum,exception);
2389 if (next_image->alpha_trait != UndefinedPixelTrait)
2390 WritePackbitsLength(psd_info,image_info,image,next_image,
2391 compact_pixels,AlphaQuantum,exception);
2392 }
2393 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2394 GrayQuantum,MagickTrue,exception);
2395 if (next_image->alpha_trait != UndefinedPixelTrait)
2396 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2397 AlphaQuantum,separate,exception);
2398 (void) SetImageProgress(image,SaveImagesTag,0,1);
2399 }
2400 else
2401 if (next_image->storage_class == PseudoClass)
2402 {
2403 if (next_image->compression == RLECompression)
2404 {
2405 /*
2406 Packbits compression.
2407 */
2408 (void) WriteBlobMSBShort(image,1);
2409 WritePackbitsLength(psd_info,image_info,image,next_image,
2410 compact_pixels,IndexQuantum,exception);
2411 if (next_image->alpha_trait != UndefinedPixelTrait)
2412 WritePackbitsLength(psd_info,image_info,image,next_image,
2413 compact_pixels,AlphaQuantum,exception);
2414 }
2415 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2416 IndexQuantum,MagickTrue,exception);
2417 if (next_image->alpha_trait != UndefinedPixelTrait)
2418 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2419 AlphaQuantum,separate,exception);
2420 (void) SetImageProgress(image,SaveImagesTag,0,1);
2421 }
2422 else
2423 {
2424 if (next_image->colorspace == CMYKColorspace)
2425 (void) NegateCMYK(next_image,exception);
2426 if (next_image->compression == RLECompression)
2427 {
2428 /*
2429 Packbits compression.
2430 */
2431 (void) WriteBlobMSBShort(image,1);
2432 WritePackbitsLength(psd_info,image_info,image,next_image,
2433 compact_pixels,RedQuantum,exception);
2434 WritePackbitsLength(psd_info,image_info,image,next_image,
2435 compact_pixels,GreenQuantum,exception);
2436 WritePackbitsLength(psd_info,image_info,image,next_image,
2437 compact_pixels,BlueQuantum,exception);
2438 if (next_image->colorspace == CMYKColorspace)
2439 WritePackbitsLength(psd_info,image_info,image,next_image,
2440 compact_pixels,BlackQuantum,exception);
2441 if (next_image->alpha_trait != UndefinedPixelTrait)
2442 WritePackbitsLength(psd_info,image_info,image,next_image,
2443 compact_pixels,AlphaQuantum,exception);
2444 }
2445 (void) SetImageProgress(image,SaveImagesTag,0,6);
2446 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2447 RedQuantum,MagickTrue,exception);
2448 (void) SetImageProgress(image,SaveImagesTag,1,6);
2449 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2450 GreenQuantum,separate,exception);
2451 (void) SetImageProgress(image,SaveImagesTag,2,6);
2452 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2453 BlueQuantum,separate,exception);
2454 (void) SetImageProgress(image,SaveImagesTag,3,6);
2455 if (next_image->colorspace == CMYKColorspace)
2456 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2457 BlackQuantum,separate,exception);
2458 (void) SetImageProgress(image,SaveImagesTag,4,6);
2459 if (next_image->alpha_trait != UndefinedPixelTrait)
2460 WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
2461 AlphaQuantum,separate,exception);
2462 (void) SetImageProgress(image,SaveImagesTag,5,6);
2463 if (next_image->colorspace == CMYKColorspace)
2464 (void) NegateCMYK(next_image,exception);
2465 }
2466 if (next_image->compression == RLECompression)
2467 compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
2468 return(MagickTrue);
2469 }
2470
WritePascalString(Image * inImage,const char * inString,int inPad)2471 static void WritePascalString(Image* inImage,const char *inString,int inPad)
2472 {
2473 size_t
2474 length;
2475
2476 register ssize_t
2477 i;
2478
2479 /*
2480 Max length is 255.
2481 */
2482 length=(strlen(inString) > 255UL ) ? 255UL : strlen(inString);
2483 if (length == 0)
2484 (void) WriteBlobByte(inImage,0);
2485 else
2486 {
2487 (void) WriteBlobByte(inImage,(unsigned char) length);
2488 (void) WriteBlob(inImage, length, (const unsigned char *) inString);
2489 }
2490 length++;
2491 if ((length % inPad) == 0)
2492 return;
2493 for (i=0; i < (ssize_t) (inPad-(length % inPad)); i++)
2494 (void) WriteBlobByte(inImage,0);
2495 }
2496
WriteResolutionResourceBlock(Image * image)2497 static void WriteResolutionResourceBlock(Image *image)
2498 {
2499 double
2500 x_resolution,
2501 y_resolution;
2502
2503 unsigned short
2504 units;
2505
2506 if (image->units == PixelsPerCentimeterResolution)
2507 {
2508 x_resolution=2.54*65536.0*image->resolution.x+0.5;
2509 y_resolution=2.54*65536.0*image->resolution.y+0.5;
2510 units=2;
2511 }
2512 else
2513 {
2514 x_resolution=65536.0*image->resolution.x+0.5;
2515 y_resolution=65536.0*image->resolution.y+0.5;
2516 units=1;
2517 }
2518 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
2519 (void) WriteBlobMSBShort(image,0x03ED);
2520 (void) WriteBlobMSBShort(image,0);
2521 (void) WriteBlobMSBLong(image,16); /* resource size */
2522 (void) WriteBlobMSBLong(image,(unsigned int) (x_resolution+0.5));
2523 (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
2524 (void) WriteBlobMSBShort(image,units); /* width unit */
2525 (void) WriteBlobMSBLong(image,(unsigned int) (y_resolution+0.5));
2526 (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
2527 (void) WriteBlobMSBShort(image,units); /* height unit */
2528 }
2529
RemoveICCProfileFromResourceBlock(StringInfo * bim_profile)2530 static void RemoveICCProfileFromResourceBlock(StringInfo *bim_profile)
2531 {
2532 register const unsigned char
2533 *p;
2534
2535 size_t
2536 length;
2537
2538 unsigned char
2539 *datum;
2540
2541 unsigned int
2542 count,
2543 long_sans;
2544
2545 unsigned short
2546 id,
2547 short_sans;
2548
2549 length=GetStringInfoLength(bim_profile);
2550 if (length < 16)
2551 return;
2552 datum=GetStringInfoDatum(bim_profile);
2553 for (p=datum; (p >= datum) && (p < (datum+length-16)); )
2554 {
2555 register unsigned char
2556 *q;
2557
2558 q=(unsigned char *) p;
2559 if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
2560 break;
2561 p=PushLongPixel(MSBEndian,p,&long_sans);
2562 p=PushShortPixel(MSBEndian,p,&id);
2563 p=PushShortPixel(MSBEndian,p,&short_sans);
2564 p=PushLongPixel(MSBEndian,p,&count);
2565 if (id == 0x0000040f)
2566 {
2567 ssize_t
2568 quantum;
2569
2570 quantum=PSDQuantum(count)+12;
2571 if ((quantum >= 12) && (q+quantum < (datum+length-16)))
2572 {
2573 (void) CopyMagickMemory(q,q+quantum,length-quantum-(q-datum));
2574 SetStringInfoLength(bim_profile,length-quantum);
2575 }
2576 break;
2577 }
2578 p+=count;
2579 if ((count & 0x01) != 0)
2580 p++;
2581 }
2582 }
2583
RemoveResolutionFromResourceBlock(StringInfo * bim_profile)2584 static void RemoveResolutionFromResourceBlock(StringInfo *bim_profile)
2585 {
2586 register const unsigned char
2587 *p;
2588
2589 size_t
2590 length;
2591
2592 unsigned char
2593 *datum;
2594
2595 unsigned int
2596 count,
2597 long_sans;
2598
2599 unsigned short
2600 id,
2601 short_sans;
2602
2603 length=GetStringInfoLength(bim_profile);
2604 if (length < 16)
2605 return;
2606 datum=GetStringInfoDatum(bim_profile);
2607 for (p=datum; (p >= datum) && (p < (datum+length-16)); )
2608 {
2609 register unsigned char
2610 *q;
2611
2612 ssize_t
2613 cnt;
2614
2615 q=(unsigned char *) p;
2616 if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
2617 return;
2618 p=PushLongPixel(MSBEndian,p,&long_sans);
2619 p=PushShortPixel(MSBEndian,p,&id);
2620 p=PushShortPixel(MSBEndian,p,&short_sans);
2621 p=PushLongPixel(MSBEndian,p,&count);
2622 cnt=PSDQuantum(count);
2623 if (cnt < 0)
2624 return;
2625 if ((id == 0x000003ed) && (cnt < (ssize_t) (length-12)))
2626 {
2627 (void) CopyMagickMemory(q,q+cnt+12,length-(cnt+12)-(q-datum));
2628 SetStringInfoLength(bim_profile,length-(cnt+12));
2629 break;
2630 }
2631 p+=count;
2632 if ((count & 0x01) != 0)
2633 p++;
2634 }
2635 }
2636
WritePSDImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)2637 static MagickBooleanType WritePSDImage(const ImageInfo *image_info,
2638 Image *image,ExceptionInfo *exception)
2639 {
2640 const char
2641 *property;
2642
2643 const StringInfo
2644 *icc_profile;
2645
2646 Image
2647 *base_image,
2648 *next_image;
2649
2650 MagickBooleanType
2651 status;
2652
2653 PSDInfo
2654 psd_info;
2655
2656 register ssize_t
2657 i;
2658
2659 size_t
2660 channel_size,
2661 channelLength,
2662 layer_count,
2663 layer_info_size,
2664 length,
2665 num_channels,
2666 packet_size,
2667 rounded_layer_info_size;
2668
2669 StringInfo
2670 *bim_profile;
2671
2672 /*
2673 Open image file.
2674 */
2675 assert(image_info != (const ImageInfo *) NULL);
2676 assert(image_info->signature == MagickCoreSignature);
2677 assert(image != (Image *) NULL);
2678 assert(image->signature == MagickCoreSignature);
2679 if (image->debug != MagickFalse)
2680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2681 assert(exception != (ExceptionInfo *) NULL);
2682 assert(exception->signature == MagickCoreSignature);
2683 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2684 if (status == MagickFalse)
2685 return(status);
2686 packet_size=(size_t) (image->depth > 8 ? 6 : 3);
2687 if (image->alpha_trait != UndefinedPixelTrait)
2688 packet_size+=image->depth > 8 ? 2 : 1;
2689 psd_info.version=1;
2690 if ((LocaleCompare(image_info->magick,"PSB") == 0) ||
2691 (image->columns > 30000) || (image->rows > 30000))
2692 psd_info.version=2;
2693 (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
2694 (void) WriteBlobMSBShort(image,psd_info.version); /* version */
2695 for (i=1; i <= 6; i++)
2696 (void) WriteBlobByte(image, 0); /* 6 bytes of reserved */
2697 if (SetImageGray(image,exception) != MagickFalse)
2698 num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
2699 else
2700 if ((image_info->type != TrueColorType) && (image_info->type !=
2701 TrueColorAlphaType) && (image->storage_class == PseudoClass))
2702 num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
2703 else
2704 {
2705 if (image->storage_class == PseudoClass)
2706 (void) SetImageStorageClass(image,DirectClass,exception);
2707 if (image->colorspace != CMYKColorspace)
2708 num_channels=(image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL);
2709 else
2710 num_channels=(image->alpha_trait != UndefinedPixelTrait ? 5UL : 4UL);
2711 }
2712 (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
2713 (void) WriteBlobMSBLong(image,(unsigned int) image->rows);
2714 (void) WriteBlobMSBLong(image,(unsigned int) image->columns);
2715 if (IsImageGray(image) != MagickFalse)
2716 {
2717 MagickBooleanType
2718 monochrome;
2719
2720 /*
2721 Write depth & mode.
2722 */
2723 monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
2724 MagickTrue : MagickFalse;
2725 (void) WriteBlobMSBShort(image,(unsigned short)
2726 (monochrome != MagickFalse ? 1 : image->depth > 8 ? 16 : 8));
2727 (void) WriteBlobMSBShort(image,(unsigned short)
2728 (monochrome != MagickFalse ? BitmapMode : GrayscaleMode));
2729 }
2730 else
2731 {
2732 (void) WriteBlobMSBShort(image,(unsigned short) (image->storage_class ==
2733 PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
2734
2735 if (((image_info->colorspace != UndefinedColorspace) ||
2736 (image->colorspace != CMYKColorspace)) &&
2737 (image_info->colorspace != CMYKColorspace))
2738 {
2739 (void) TransformImageColorspace(image,sRGBColorspace,exception);
2740 (void) WriteBlobMSBShort(image,(unsigned short)
2741 (image->storage_class == PseudoClass ? IndexedMode : RGBMode));
2742 }
2743 else
2744 {
2745 if (image->colorspace != CMYKColorspace)
2746 (void) TransformImageColorspace(image,CMYKColorspace,exception);
2747 (void) WriteBlobMSBShort(image,CMYKMode);
2748 }
2749 }
2750 if ((IsImageGray(image) != MagickFalse) ||
2751 (image->storage_class == DirectClass) || (image->colors > 256))
2752 (void) WriteBlobMSBLong(image,0);
2753 else
2754 {
2755 /*
2756 Write PSD raster colormap.
2757 */
2758 (void) WriteBlobMSBLong(image,768);
2759 for (i=0; i < (ssize_t) image->colors; i++)
2760 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
2761 for ( ; i < 256; i++)
2762 (void) WriteBlobByte(image,0);
2763 for (i=0; i < (ssize_t) image->colors; i++)
2764 (void) WriteBlobByte(image,ScaleQuantumToChar(
2765 image->colormap[i].green));
2766 for ( ; i < 256; i++)
2767 (void) WriteBlobByte(image,0);
2768 for (i=0; i < (ssize_t) image->colors; i++)
2769 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
2770 for ( ; i < 256; i++)
2771 (void) WriteBlobByte(image,0);
2772 }
2773 /*
2774 Image resource block.
2775 */
2776 length=28; /* 0x03EB */
2777 bim_profile=(StringInfo *) GetImageProfile(image,"8bim");
2778 icc_profile=GetImageProfile(image,"icc");
2779 if (bim_profile != (StringInfo *) NULL)
2780 {
2781 bim_profile=CloneStringInfo(bim_profile);
2782 if (icc_profile != (StringInfo *) NULL)
2783 RemoveICCProfileFromResourceBlock(bim_profile);
2784 RemoveResolutionFromResourceBlock(bim_profile);
2785 length+=PSDQuantum(GetStringInfoLength(bim_profile));
2786 }
2787 if (icc_profile != (const StringInfo *) NULL)
2788 length+=PSDQuantum(GetStringInfoLength(icc_profile))+12;
2789 (void) WriteBlobMSBLong(image,(unsigned int) length);
2790 WriteResolutionResourceBlock(image);
2791 if (bim_profile != (StringInfo *) NULL)
2792 {
2793 (void) WriteBlob(image,GetStringInfoLength(bim_profile),
2794 GetStringInfoDatum(bim_profile));
2795 bim_profile=DestroyStringInfo(bim_profile);
2796 }
2797 if (icc_profile != (StringInfo *) NULL)
2798 {
2799 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
2800 (void) WriteBlobMSBShort(image,0x0000040F);
2801 (void) WriteBlobMSBShort(image,0);
2802 (void) WriteBlobMSBLong(image,(unsigned int) GetStringInfoLength(
2803 icc_profile));
2804 (void) WriteBlob(image,GetStringInfoLength(icc_profile),
2805 GetStringInfoDatum(icc_profile));
2806 if ((MagickOffsetType) GetStringInfoLength(icc_profile) !=
2807 PSDQuantum(GetStringInfoLength(icc_profile)))
2808 (void) WriteBlobByte(image,0);
2809 }
2810 layer_count=0;
2811 layer_info_size=2;
2812 base_image=GetNextImageInList(image);
2813 if (base_image == (Image *) NULL)
2814 base_image=image;
2815 next_image=base_image;
2816 while (next_image != (Image *) NULL)
2817 {
2818 packet_size=next_image->depth > 8 ? 2UL : 1UL;
2819 if (IsImageGray(next_image) != MagickFalse)
2820 num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL;
2821 else
2822 if (next_image->storage_class == PseudoClass)
2823 num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL;
2824 else
2825 if (next_image->colorspace != CMYKColorspace)
2826 num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL;
2827 else
2828 num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 5UL : 4UL;
2829 channelLength=(size_t) (next_image->columns*next_image->rows*packet_size+2);
2830 layer_info_size+=(size_t) (4*4+2+num_channels*6+(psd_info.version == 1 ? 8 :
2831 16)+4*1+4+num_channels*channelLength);
2832 property=(const char *) GetImageProperty(next_image,"label",exception);
2833 if (property == (const char *) NULL)
2834 layer_info_size+=16;
2835 else
2836 {
2837 size_t
2838 layer_length;
2839
2840 layer_length=strlen(property);
2841 layer_info_size+=8+layer_length+(4-(layer_length % 4));
2842 }
2843 layer_count++;
2844 next_image=GetNextImageInList(next_image);
2845 }
2846 if (layer_count == 0)
2847 (void) SetPSDSize(&psd_info,image,0);
2848 else
2849 {
2850 CompressionType
2851 compression;
2852
2853 (void) SetPSDSize(&psd_info,image,layer_info_size+
2854 (psd_info.version == 1 ? 8 : 16));
2855 if ((layer_info_size/2) != ((layer_info_size+1)/2))
2856 rounded_layer_info_size=layer_info_size+1;
2857 else
2858 rounded_layer_info_size=layer_info_size;
2859 (void) SetPSDSize(&psd_info,image,rounded_layer_info_size);
2860 if (image->alpha_trait != UndefinedPixelTrait)
2861 (void) WriteBlobMSBShort(image,-(unsigned short) layer_count);
2862 else
2863 (void) WriteBlobMSBShort(image,(unsigned short) layer_count);
2864 layer_count=1;
2865 compression=base_image->compression;
2866 for (next_image=base_image; next_image != NULL; )
2867 {
2868 next_image->compression=NoCompression;
2869 (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.y);
2870 (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.x);
2871 (void) WriteBlobMSBLong(image,(unsigned int) (next_image->page.y+
2872 next_image->rows));
2873 (void) WriteBlobMSBLong(image,(unsigned int) (next_image->page.x+
2874 next_image->columns));
2875 packet_size=next_image->depth > 8 ? 2UL : 1UL;
2876 channel_size=(unsigned int) ((packet_size*next_image->rows*
2877 next_image->columns)+2);
2878 if ((IsImageGray(next_image) != MagickFalse) ||
2879 (next_image->storage_class == PseudoClass))
2880 {
2881 (void) WriteBlobMSBShort(image,(unsigned short)
2882 (next_image->alpha_trait != UndefinedPixelTrait ? 2 : 1));
2883 (void) WriteBlobMSBShort(image,0);
2884 (void) SetPSDSize(&psd_info,image,channel_size);
2885 if (next_image->alpha_trait != UndefinedPixelTrait)
2886 {
2887 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2888 (void) SetPSDSize(&psd_info,image,channel_size);
2889 }
2890 }
2891 else
2892 if (next_image->colorspace != CMYKColorspace)
2893 {
2894 (void) WriteBlobMSBShort(image,(unsigned short)
2895 (next_image->alpha_trait != UndefinedPixelTrait ? 4 : 3));
2896 (void) WriteBlobMSBShort(image,0);
2897 (void) SetPSDSize(&psd_info,image,channel_size);
2898 (void) WriteBlobMSBShort(image,1);
2899 (void) SetPSDSize(&psd_info,image,channel_size);
2900 (void) WriteBlobMSBShort(image,2);
2901 (void) SetPSDSize(&psd_info,image,channel_size);
2902 if (next_image->alpha_trait != UndefinedPixelTrait)
2903 {
2904 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2905 (void) SetPSDSize(&psd_info,image,channel_size);
2906 }
2907 }
2908 else
2909 {
2910 (void) WriteBlobMSBShort(image,(unsigned short)
2911 (next_image->alpha_trait ? 5 : 4));
2912 (void) WriteBlobMSBShort(image,0);
2913 (void) SetPSDSize(&psd_info,image,channel_size);
2914 (void) WriteBlobMSBShort(image,1);
2915 (void) SetPSDSize(&psd_info,image,channel_size);
2916 (void) WriteBlobMSBShort(image,2);
2917 (void) SetPSDSize(&psd_info,image,channel_size);
2918 (void) WriteBlobMSBShort(image,3);
2919 (void) SetPSDSize(&psd_info,image,channel_size);
2920 if (next_image->alpha_trait)
2921 {
2922 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2923 (void) SetPSDSize(&psd_info,image,channel_size);
2924 }
2925 }
2926 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
2927 (void) WriteBlob(image,4,(const unsigned char *)
2928 CompositeOperatorToPSDBlendMode(next_image->compose));
2929 (void) WriteBlobByte(image,255); /* layer opacity */
2930 (void) WriteBlobByte(image,0);
2931 (void) WriteBlobByte(image,next_image->compose==NoCompositeOp ?
2932 1 << 0x02 : 1); /* layer properties - visible, etc. */
2933 (void) WriteBlobByte(image,0);
2934 property=(const char *) GetImageProperty(next_image,"label",exception);
2935 if (property == (const char *) NULL)
2936 {
2937 char
2938 layer_name[MagickPathExtent];
2939
2940 (void) WriteBlobMSBLong(image,16);
2941 (void) WriteBlobMSBLong(image,0);
2942 (void) WriteBlobMSBLong(image,0);
2943 (void) FormatLocaleString(layer_name,MagickPathExtent,"L%04ld",(long)
2944 layer_count++);
2945 WritePascalString(image,layer_name,4);
2946 }
2947 else
2948 {
2949 size_t
2950 label_length;
2951
2952 label_length=strlen(property);
2953 (void) WriteBlobMSBLong(image,(unsigned int) (label_length+(4-
2954 (label_length % 4))+8));
2955 (void) WriteBlobMSBLong(image,0);
2956 (void) WriteBlobMSBLong(image,0);
2957 WritePascalString(image,property,4);
2958 }
2959 next_image=GetNextImageInList(next_image);
2960 }
2961 /*
2962 Now the image data!
2963 */
2964 next_image=base_image;
2965 while (next_image != NULL)
2966 {
2967 status=WriteImageChannels(&psd_info,image_info,image,next_image,
2968 MagickTrue,exception);
2969 next_image=GetNextImageInList(next_image);
2970 }
2971 (void) WriteBlobMSBLong(image,0); /* user mask data */
2972 base_image->compression=compression;
2973 }
2974 /*
2975 Write composite image.
2976 */
2977 if (status != MagickFalse)
2978 status=WriteImageChannels(&psd_info,image_info,image,image,MagickFalse,
2979 exception);
2980 (void) CloseBlob(image);
2981 return(status);
2982 }
2983