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-2021 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 %    https://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 % Photoshop spec @ https://www.adobe.com/devnet-apps/photoshop/fileformatashtml
40 %
41 */
42 
43 /*
44   Include declarations.
45 */
46 #include "MagickCore/studio.h"
47 #include "MagickCore/artifact.h"
48 #include "MagickCore/attribute.h"
49 #include "MagickCore/blob.h"
50 #include "MagickCore/blob-private.h"
51 #include "MagickCore/cache.h"
52 #include "MagickCore/channel.h"
53 #include "MagickCore/colormap.h"
54 #include "MagickCore/colormap-private.h"
55 #include "MagickCore/colorspace.h"
56 #include "MagickCore/colorspace-private.h"
57 #include "MagickCore/constitute.h"
58 #include "MagickCore/enhance.h"
59 #include "MagickCore/exception.h"
60 #include "MagickCore/exception-private.h"
61 #include "MagickCore/image.h"
62 #include "MagickCore/image-private.h"
63 #include "MagickCore/list.h"
64 #include "MagickCore/log.h"
65 #include "MagickCore/magick.h"
66 #include "MagickCore/memory_.h"
67 #include "MagickCore/module.h"
68 #include "MagickCore/monitor-private.h"
69 #include "MagickCore/option.h"
70 #include "MagickCore/pixel.h"
71 #include "MagickCore/pixel-accessor.h"
72 #include "MagickCore/pixel-private.h"
73 #include "MagickCore/policy.h"
74 #include "MagickCore/profile.h"
75 #include "MagickCore/property.h"
76 #include "MagickCore/registry.h"
77 #include "MagickCore/quantum-private.h"
78 #include "MagickCore/static.h"
79 #include "MagickCore/string_.h"
80 #include "MagickCore/string-private.h"
81 #include "MagickCore/thread-private.h"
82 #include "coders/coders-private.h"
83 #ifdef MAGICKCORE_ZLIB_DELEGATE
84 #include <zlib.h>
85 #endif
86 #include "psd-private.h"
87 
88 /*
89   Define declaractions.
90 */
91 #define MaxPSDChannels  56
92 #define PSDQuantum(x) (((ssize_t) (x)+1) & -2)
93 
94 /*
95   Enumerated declaractions.
96 */
97 typedef enum
98 {
99   Raw = 0,
100   RLE = 1,
101   ZipWithoutPrediction = 2,
102   ZipWithPrediction = 3
103 } PSDCompressionType;
104 
105 typedef enum
106 {
107   BitmapMode = 0,
108   GrayscaleMode = 1,
109   IndexedMode = 2,
110   RGBMode = 3,
111   CMYKMode = 4,
112   MultichannelMode = 7,
113   DuotoneMode = 8,
114   LabMode = 9
115 } PSDImageType;
116 
117 /*
118   Typedef declaractions.
119 */
120 typedef struct _ChannelInfo
121 {
122   MagickBooleanType
123     supported;
124 
125   PixelChannel
126     channel;
127 
128   size_t
129     size;
130 } ChannelInfo;
131 
132 typedef struct _MaskInfo
133 {
134   Image
135     *image;
136 
137   RectangleInfo
138     page;
139 
140   unsigned char
141     background,
142     flags;
143 } MaskInfo;
144 
145 typedef struct _LayerInfo
146 {
147   ChannelInfo
148     channel_info[MaxPSDChannels];
149 
150   char
151     blendkey[4];
152 
153   Image
154     *image;
155 
156   MaskInfo
157     mask;
158 
159   Quantum
160     opacity;
161 
162   RectangleInfo
163     page;
164 
165   size_t
166     offset_x,
167     offset_y;
168 
169   unsigned char
170     clipping,
171     flags,
172     name[257],
173     visible;
174 
175   unsigned short
176     channels;
177 
178   StringInfo
179     *info;
180 } LayerInfo;
181 
182 /*
183   Forward declarations.
184 */
185 static MagickBooleanType
186   WritePSDImage(const ImageInfo *,Image *,ExceptionInfo *);
187 
188 /*
189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 %                                                                             %
191 %                                                                             %
192 %                                                                             %
193 %   I s P S D                                                                 %
194 %                                                                             %
195 %                                                                             %
196 %                                                                             %
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 %
199 %  IsPSD()() returns MagickTrue if the image format type, identified by the
200 %  magick string, is PSD.
201 %
202 %  The format of the IsPSD method is:
203 %
204 %      MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
205 %
206 %  A description of each parameter follows:
207 %
208 %    o magick: compare image format pattern against these bytes.
209 %
210 %    o length: Specifies the length of the magick string.
211 %
212 */
IsPSD(const unsigned char * magick,const size_t length)213 static MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
214 {
215   if (length < 4)
216     return(MagickFalse);
217   if (LocaleNCompare((const char *) magick,"8BPS",4) == 0)
218     return(MagickTrue);
219   return(MagickFalse);
220 }
221 
222 /*
223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224 %                                                                             %
225 %                                                                             %
226 %                                                                             %
227 %   R e a d P S D I m a g e                                                   %
228 %                                                                             %
229 %                                                                             %
230 %                                                                             %
231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 %
233 %  ReadPSDImage() reads an Adobe Photoshop image file and returns it.  It
234 %  allocates the memory necessary for the new Image structure and returns a
235 %  pointer to the new image.
236 %
237 %  The format of the ReadPSDImage method is:
238 %
239 %      Image *ReadPSDImage(image_info,ExceptionInfo *exception)
240 %
241 %  A description of each parameter follows:
242 %
243 %    o image_info: the image info.
244 %
245 %    o exception: return any errors or warnings in this structure.
246 %
247 */
248 
CompositeOperatorToPSDBlendMode(Image * image)249 static const char *CompositeOperatorToPSDBlendMode(Image *image)
250 {
251   switch (image->compose)
252   {
253     case ColorBurnCompositeOp:
254       return(image->endian == LSBEndian ? "vidi" : "idiv");
255     case ColorDodgeCompositeOp:
256       return(image->endian == LSBEndian ? " vid" : "div ");
257     case ColorizeCompositeOp:
258       return(image->endian == LSBEndian ? "rloc" : "colr");
259     case DarkenCompositeOp:
260       return(image->endian == LSBEndian ? "krad" : "dark");
261     case DifferenceCompositeOp:
262       return(image->endian == LSBEndian ? "ffid" : "diff");
263     case DissolveCompositeOp:
264       return(image->endian == LSBEndian ? "ssid" : "diss");
265     case ExclusionCompositeOp:
266       return(image->endian == LSBEndian ? "dums" : "smud");
267     case HardLightCompositeOp:
268       return(image->endian == LSBEndian ? "tiLh" : "hLit");
269     case HardMixCompositeOp:
270       return(image->endian == LSBEndian ? "xiMh" : "hMix");
271     case HueCompositeOp:
272       return(image->endian == LSBEndian ? " euh" : "hue ");
273     case LightenCompositeOp:
274       return(image->endian == LSBEndian ? "etil" : "lite");
275     case LinearBurnCompositeOp:
276       return(image->endian == LSBEndian ? "nrbl" : "lbrn");
277     case LinearDodgeCompositeOp:
278       return(image->endian == LSBEndian ? "gddl" : "lddg");
279     case LinearLightCompositeOp:
280       return(image->endian == LSBEndian ? "tiLl" : "lLit");
281     case LuminizeCompositeOp:
282       return(image->endian == LSBEndian ? " mul" : "lum ");
283     case MultiplyCompositeOp:
284       return(image->endian == LSBEndian ? " lum" : "mul ");
285     case OverlayCompositeOp:
286       return(image->endian == LSBEndian ? "revo" : "over");
287     case PinLightCompositeOp:
288       return(image->endian == LSBEndian ? "tiLp" : "pLit");
289     case SaturateCompositeOp:
290       return(image->endian == LSBEndian ? " tas" : "sat ");
291     case ScreenCompositeOp:
292       return(image->endian == LSBEndian ? "nrcs" : "scrn");
293     case SoftLightCompositeOp:
294       return(image->endian == LSBEndian ? "tiLs" : "sLit");
295     case VividLightCompositeOp:
296       return(image->endian == LSBEndian ? "tiLv" : "vLit");
297     case OverCompositeOp:
298     default:
299       return(image->endian == LSBEndian ? "mron" : "norm");
300   }
301 }
302 
303 /*
304   For some reason Photoshop seems to blend semi-transparent pixels with white.
305   This method reverts the blending. This can be disabled by setting the
306   option 'psd:alpha-unblend' to off.
307 */
CorrectPSDAlphaBlend(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)308 static MagickBooleanType CorrectPSDAlphaBlend(const ImageInfo *image_info,
309   Image *image,ExceptionInfo* exception)
310 {
311   const char
312     *option;
313 
314   MagickBooleanType
315     status;
316 
317   ssize_t
318     y;
319 
320   if ((image->alpha_trait != BlendPixelTrait) ||
321       (image->colorspace != sRGBColorspace))
322     return(MagickTrue);
323   option=GetImageOption(image_info,"psd:alpha-unblend");
324   if (IsStringFalse(option) != MagickFalse)
325     return(MagickTrue);
326   status=MagickTrue;
327 #if defined(MAGICKCORE_OPENMP_SUPPORT)
328 #pragma omp parallel for schedule(static) shared(status) \
329   magick_number_threads(image,image,image->rows,1)
330 #endif
331   for (y=0; y < (ssize_t) image->rows; y++)
332   {
333     Quantum
334       *magick_restrict q;
335 
336     ssize_t
337       x;
338 
339     if (status == MagickFalse)
340       continue;
341     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
342     if (q == (Quantum *) NULL)
343       {
344         status=MagickFalse;
345         continue;
346       }
347     for (x=0; x < (ssize_t) image->columns; x++)
348     {
349       double
350         gamma;
351 
352       ssize_t
353         i;
354 
355       gamma=QuantumScale*GetPixelAlpha(image, q);
356       if (gamma != 0.0 && gamma != 1.0)
357         {
358           for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
359           {
360             PixelChannel channel = GetPixelChannelChannel(image,i);
361             if (channel != AlphaPixelChannel)
362               q[i]=ClampToQuantum((q[i]-((1.0-gamma)*QuantumRange))/gamma);
363           }
364         }
365       q+=GetPixelChannels(image);
366     }
367     if (SyncAuthenticPixels(image,exception) == MagickFalse)
368       status=MagickFalse;
369   }
370 
371   return(status);
372 }
373 
ConvertPSDCompression(PSDCompressionType compression)374 static inline CompressionType ConvertPSDCompression(
375   PSDCompressionType compression)
376 {
377   switch (compression)
378   {
379     case RLE:
380       return RLECompression;
381     case ZipWithPrediction:
382     case ZipWithoutPrediction:
383       return ZipCompression;
384     default:
385       return NoCompression;
386   }
387 }
388 
ApplyPSDLayerOpacity(Image * image,Quantum opacity,MagickBooleanType revert,ExceptionInfo * exception)389 static MagickBooleanType ApplyPSDLayerOpacity(Image *image,Quantum opacity,
390   MagickBooleanType revert,ExceptionInfo *exception)
391 {
392   MagickBooleanType
393     status;
394 
395   ssize_t
396     y;
397 
398   if (image->debug != MagickFalse)
399     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
400       "  applying layer opacity %.20g", (double) opacity);
401   if (opacity == OpaqueAlpha)
402     return(MagickTrue);
403   if (image->alpha_trait != BlendPixelTrait)
404     (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
405   status=MagickTrue;
406 #if defined(MAGICKCORE_OPENMP_SUPPORT)
407 #pragma omp parallel for schedule(static) shared(status) \
408   magick_number_threads(image,image,image->rows,1)
409 #endif
410   for (y=0; y < (ssize_t) image->rows; y++)
411   {
412     Quantum
413       *magick_restrict q;
414 
415     ssize_t
416       x;
417 
418     if (status == MagickFalse)
419       continue;
420     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
421     if (q == (Quantum *) NULL)
422       {
423         status=MagickFalse;
424         continue;
425       }
426     for (x=0; x < (ssize_t) image->columns; x++)
427     {
428       if (revert == MagickFalse)
429         SetPixelAlpha(image,ClampToQuantum(QuantumScale*
430           GetPixelAlpha(image,q)*opacity),q);
431       else if (opacity > 0)
432         SetPixelAlpha(image,ClampToQuantum((double) QuantumRange*
433           GetPixelAlpha(image,q)/(MagickRealType) opacity),q);
434       q+=GetPixelChannels(image);
435     }
436     if (SyncAuthenticPixels(image,exception) == MagickFalse)
437       status=MagickFalse;
438   }
439 
440   return(status);
441 }
442 
ApplyPSDOpacityMask(Image * image,const Image * mask,Quantum background,MagickBooleanType revert,ExceptionInfo * exception)443 static MagickBooleanType ApplyPSDOpacityMask(Image *image,const Image *mask,
444   Quantum background,MagickBooleanType revert,ExceptionInfo *exception)
445 {
446   Image
447     *complete_mask;
448 
449   MagickBooleanType
450     status;
451 
452   PixelInfo
453     color;
454 
455   ssize_t
456     y;
457 
458   if (image->alpha_trait == UndefinedPixelTrait)
459     return(MagickTrue);
460   if (image->debug != MagickFalse)
461     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
462       "  applying opacity mask");
463   complete_mask=CloneImage(image,0,0,MagickTrue,exception);
464   if (complete_mask == (Image *) NULL)
465     return(MagickFalse);
466   complete_mask->alpha_trait=BlendPixelTrait;
467   GetPixelInfo(complete_mask,&color);
468   color.red=(MagickRealType) background;
469   (void) SetImageColor(complete_mask,&color,exception);
470   status=CompositeImage(complete_mask,mask,OverCompositeOp,MagickTrue,
471     mask->page.x-image->page.x,mask->page.y-image->page.y,exception);
472   if (status == MagickFalse)
473     {
474       complete_mask=DestroyImage(complete_mask);
475       return(status);
476     }
477 
478 #if defined(MAGICKCORE_OPENMP_SUPPORT)
479 #pragma omp parallel for schedule(static) shared(status) \
480   magick_number_threads(image,image,image->rows,1)
481 #endif
482   for (y=0; y < (ssize_t) image->rows; y++)
483   {
484     Quantum
485       *magick_restrict q;
486 
487     Quantum
488       *p;
489 
490     ssize_t
491       x;
492 
493     if (status == MagickFalse)
494       continue;
495     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
496     p=GetAuthenticPixels(complete_mask,0,y,complete_mask->columns,1,exception);
497     if ((q == (Quantum *) NULL) || (p == (Quantum *) NULL))
498       {
499         status=MagickFalse;
500         continue;
501       }
502     for (x=0; x < (ssize_t) image->columns; x++)
503     {
504       MagickRealType
505         alpha,
506         intensity;
507 
508       alpha=(MagickRealType) GetPixelAlpha(image,q);
509       intensity=GetPixelIntensity(complete_mask,p);
510       if (revert == MagickFalse)
511         SetPixelAlpha(image,ClampToQuantum(intensity*(QuantumScale*alpha)),q);
512       else if (intensity > 0)
513         SetPixelAlpha(image,ClampToQuantum((alpha/intensity)*QuantumRange),q);
514       q+=GetPixelChannels(image);
515       p+=GetPixelChannels(complete_mask);
516     }
517     if (SyncAuthenticPixels(image,exception) == MagickFalse)
518       status=MagickFalse;
519   }
520   complete_mask=DestroyImage(complete_mask);
521   return(status);
522 }
523 
PreservePSDOpacityMask(Image * image,LayerInfo * layer_info,ExceptionInfo * exception)524 static void PreservePSDOpacityMask(Image *image,LayerInfo* layer_info,
525   ExceptionInfo *exception)
526 {
527   char
528     *key;
529 
530   RandomInfo
531     *random_info;
532 
533   StringInfo
534     *key_info;
535 
536   if (image->debug != MagickFalse)
537     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
538       "  preserving opacity mask");
539   random_info=AcquireRandomInfo();
540   key_info=GetRandomKey(random_info,2+1);
541   key=(char *) GetStringInfoDatum(key_info);
542   key[8]=(char) layer_info->mask.background;
543   key[9]='\0';
544   layer_info->mask.image->page.x+=layer_info->page.x;
545   layer_info->mask.image->page.y+=layer_info->page.y;
546   (void) SetImageRegistry(ImageRegistryType,(const char *) key,
547     layer_info->mask.image,exception);
548   (void) SetImageArtifact(layer_info->image,"psd:opacity-mask",
549     (const char *) key);
550   key_info=DestroyStringInfo(key_info);
551   random_info=DestroyRandomInfo(random_info);
552 }
553 
DecodePSDPixels(const size_t number_compact_pixels,const unsigned char * compact_pixels,const ssize_t depth,const size_t number_pixels,unsigned char * pixels)554 static ssize_t DecodePSDPixels(const size_t number_compact_pixels,
555   const unsigned char *compact_pixels,const ssize_t depth,
556   const size_t number_pixels,unsigned char *pixels)
557 {
558 #define CheckNumberCompactPixels \
559   if (packets == 0) \
560     return(i); \
561   packets--
562 
563 #define CheckNumberPixels(count) \
564   if (((ssize_t) i + count) > (ssize_t) number_pixels) \
565     return(i); \
566   i+=count
567 
568   int
569     pixel;
570 
571   ssize_t
572     i,
573     j;
574 
575   size_t
576     length;
577 
578   ssize_t
579     packets;
580 
581   packets=(ssize_t) number_compact_pixels;
582   for (i=0; (packets > 1) && (i < (ssize_t) number_pixels); )
583   {
584     packets--;
585     length=(size_t) (*compact_pixels++);
586     if (length == 128)
587       continue;
588     if (length > 128)
589       {
590         length=256-length+1;
591         CheckNumberCompactPixels;
592         pixel=(*compact_pixels++);
593         for (j=0; j < (ssize_t) length; j++)
594         {
595           switch (depth)
596           {
597             case 1:
598             {
599               CheckNumberPixels(8);
600               *pixels++=(pixel >> 7) & 0x01 ? 0U : 255U;
601               *pixels++=(pixel >> 6) & 0x01 ? 0U : 255U;
602               *pixels++=(pixel >> 5) & 0x01 ? 0U : 255U;
603               *pixels++=(pixel >> 4) & 0x01 ? 0U : 255U;
604               *pixels++=(pixel >> 3) & 0x01 ? 0U : 255U;
605               *pixels++=(pixel >> 2) & 0x01 ? 0U : 255U;
606               *pixels++=(pixel >> 1) & 0x01 ? 0U : 255U;
607               *pixels++=(pixel >> 0) & 0x01 ? 0U : 255U;
608               break;
609             }
610             case 2:
611             {
612               CheckNumberPixels(4);
613               *pixels++=(unsigned char) ((pixel >> 6) & 0x03);
614               *pixels++=(unsigned char) ((pixel >> 4) & 0x03);
615               *pixels++=(unsigned char) ((pixel >> 2) & 0x03);
616               *pixels++=(unsigned char) ((pixel & 0x03) & 0x03);
617               break;
618             }
619             case 4:
620             {
621               CheckNumberPixels(2);
622               *pixels++=(unsigned char) ((pixel >> 4) & 0xff);
623               *pixels++=(unsigned char) ((pixel & 0x0f) & 0xff);
624               break;
625             }
626             default:
627             {
628               CheckNumberPixels(1);
629               *pixels++=(unsigned char) pixel;
630               break;
631             }
632           }
633         }
634         continue;
635       }
636     length++;
637     for (j=0; j < (ssize_t) length; j++)
638     {
639       CheckNumberCompactPixels;
640       switch (depth)
641       {
642         case 1:
643         {
644           CheckNumberPixels(8);
645           *pixels++=(*compact_pixels >> 7) & 0x01 ? 0U : 255U;
646           *pixels++=(*compact_pixels >> 6) & 0x01 ? 0U : 255U;
647           *pixels++=(*compact_pixels >> 5) & 0x01 ? 0U : 255U;
648           *pixels++=(*compact_pixels >> 4) & 0x01 ? 0U : 255U;
649           *pixels++=(*compact_pixels >> 3) & 0x01 ? 0U : 255U;
650           *pixels++=(*compact_pixels >> 2) & 0x01 ? 0U : 255U;
651           *pixels++=(*compact_pixels >> 1) & 0x01 ? 0U : 255U;
652           *pixels++=(*compact_pixels >> 0) & 0x01 ? 0U : 255U;
653           break;
654         }
655         case 2:
656         {
657           CheckNumberPixels(4);
658           *pixels++=(*compact_pixels >> 6) & 0x03;
659           *pixels++=(*compact_pixels >> 4) & 0x03;
660           *pixels++=(*compact_pixels >> 2) & 0x03;
661           *pixels++=(*compact_pixels & 0x03) & 0x03;
662           break;
663         }
664         case 4:
665         {
666           CheckNumberPixels(2);
667           *pixels++=(*compact_pixels >> 4) & 0xff;
668           *pixels++=(*compact_pixels & 0x0f) & 0xff;
669           break;
670         }
671         default:
672         {
673           CheckNumberPixels(1);
674           *pixels++=(*compact_pixels);
675           break;
676         }
677       }
678       compact_pixels++;
679     }
680   }
681   return(i);
682 }
683 
DestroyLayerInfo(LayerInfo * layer_info,const ssize_t number_layers)684 static inline LayerInfo *DestroyLayerInfo(LayerInfo *layer_info,
685   const ssize_t number_layers)
686 {
687   ssize_t
688     i;
689 
690   for (i=0; i<number_layers; i++)
691   {
692     if (layer_info[i].image != (Image *) NULL)
693       layer_info[i].image=DestroyImage(layer_info[i].image);
694     if (layer_info[i].mask.image != (Image *) NULL)
695       layer_info[i].mask.image=DestroyImage(layer_info[i].mask.image);
696     if (layer_info[i].info != (StringInfo *) NULL)
697       layer_info[i].info=DestroyStringInfo(layer_info[i].info);
698   }
699 
700   return (LayerInfo *) RelinquishMagickMemory(layer_info);
701 }
702 
GetPSDPacketSize(const Image * image)703 static inline size_t GetPSDPacketSize(const Image *image)
704 {
705   if (image->storage_class == PseudoClass)
706     {
707       if (image->colors > 256)
708         return(2);
709     }
710   if (image->depth > 16)
711     return(4);
712   if (image->depth > 8)
713     return(2);
714 
715   return(1);
716 }
717 
GetPSDSize(const PSDInfo * psd_info,Image * image)718 static inline MagickSizeType GetPSDSize(const PSDInfo *psd_info,Image *image)
719 {
720   if (psd_info->version == 1)
721     return((MagickSizeType) ReadBlobLong(image));
722   return((MagickSizeType) ReadBlobLongLong(image));
723 }
724 
GetPSDRowSize(Image * image)725 static inline size_t GetPSDRowSize(Image *image)
726 {
727   if (image->depth == 1)
728     return(((image->columns+7)/8)*GetPSDPacketSize(image));
729   else
730     return(image->columns*GetPSDPacketSize(image));
731 }
732 
ModeToString(PSDImageType type)733 static const char *ModeToString(PSDImageType type)
734 {
735   switch (type)
736   {
737     case BitmapMode: return "Bitmap";
738     case GrayscaleMode: return "Grayscale";
739     case IndexedMode: return "Indexed";
740     case RGBMode: return "RGB";
741     case CMYKMode:  return "CMYK";
742     case MultichannelMode: return "Multichannel";
743     case DuotoneMode: return "Duotone";
744     case LabMode: return "L*A*B";
745     default: return "unknown";
746   }
747 }
748 
NegateCMYK(Image * image,ExceptionInfo * exception)749 static MagickBooleanType NegateCMYK(Image *image,ExceptionInfo *exception)
750 {
751   ChannelType
752     channel_mask;
753 
754   MagickBooleanType
755     status;
756 
757   channel_mask=SetImageChannelMask(image,(ChannelType)(AllChannels &~
758     AlphaChannel));
759   status=NegateImage(image,MagickFalse,exception);
760   (void) SetImageChannelMask(image,channel_mask);
761   return(status);
762 }
763 
ParseImageResourceBlocks(PSDInfo * psd_info,Image * image,const unsigned char * blocks,size_t length)764 static StringInfo *ParseImageResourceBlocks(PSDInfo *psd_info,Image *image,
765   const unsigned char *blocks,size_t length)
766 {
767   const unsigned char
768     *p;
769 
770   ssize_t
771     offset;
772 
773   StringInfo
774     *profile;
775 
776   unsigned char
777     name_length;
778 
779   unsigned int
780     count;
781 
782   unsigned short
783     id,
784     short_sans;
785 
786   if (length < 16)
787     return((StringInfo *) NULL);
788   profile=BlobToStringInfo((const unsigned char *) NULL,length);
789   SetStringInfoDatum(profile,blocks);
790   SetStringInfoName(profile,"8bim");
791   for (p=blocks; (p >= blocks) && (p < (blocks+length-7)); )
792   {
793     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
794       break;
795     p+=4;
796     p=PushShortPixel(MSBEndian,p,&id);
797     p=PushCharPixel(p,&name_length);
798     if ((name_length % 2) == 0)
799       name_length++;
800     p+=name_length;
801     if (p > (blocks+length-4))
802       break;
803     p=PushLongPixel(MSBEndian,p,&count);
804     offset=(ssize_t) count;
805     if (((p+offset) < blocks) || ((p+offset) > (blocks+length)))
806       break;
807     switch (id)
808     {
809       case 0x03ed:
810       {
811         unsigned short
812           resolution;
813 
814         /*
815           Resolution info.
816         */
817         if (offset < 16)
818           break;
819         p=PushShortPixel(MSBEndian,p,&resolution);
820         image->resolution.x=(double) resolution;
821         (void) FormatImageProperty(image,"tiff:XResolution","%*g",
822           GetMagickPrecision(),image->resolution.x);
823         p=PushShortPixel(MSBEndian,p,&short_sans);
824         p=PushShortPixel(MSBEndian,p,&short_sans);
825         p=PushShortPixel(MSBEndian,p,&short_sans);
826         p=PushShortPixel(MSBEndian,p,&resolution);
827         image->resolution.y=(double) resolution;
828         (void) FormatImageProperty(image,"tiff:YResolution","%*g",
829           GetMagickPrecision(),image->resolution.y);
830         p=PushShortPixel(MSBEndian,p,&short_sans);
831         p=PushShortPixel(MSBEndian,p,&short_sans);
832         p=PushShortPixel(MSBEndian,p,&short_sans);
833         image->units=PixelsPerInchResolution;
834         break;
835       }
836       case 0x0421:
837       {
838         if ((offset > 4) && (*(p+4) == 0))
839           psd_info->has_merged_image=MagickFalse;
840         p+=offset;
841         break;
842       }
843       default:
844       {
845         p+=offset;
846         break;
847       }
848     }
849     if ((offset & 0x01) != 0)
850       p++;
851   }
852   return(profile);
853 }
854 
PSDBlendModeToCompositeOperator(const char * mode)855 static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
856 {
857   if (mode == (const char *) NULL)
858     return(OverCompositeOp);
859   if (LocaleNCompare(mode,"norm",4) == 0)
860     return(OverCompositeOp);
861   if (LocaleNCompare(mode,"mul ",4) == 0)
862     return(MultiplyCompositeOp);
863   if (LocaleNCompare(mode,"diss",4) == 0)
864     return(DissolveCompositeOp);
865   if (LocaleNCompare(mode,"diff",4) == 0)
866     return(DifferenceCompositeOp);
867   if (LocaleNCompare(mode,"dark",4) == 0)
868     return(DarkenCompositeOp);
869   if (LocaleNCompare(mode,"lite",4) == 0)
870     return(LightenCompositeOp);
871   if (LocaleNCompare(mode,"hue ",4) == 0)
872     return(HueCompositeOp);
873   if (LocaleNCompare(mode,"sat ",4) == 0)
874     return(SaturateCompositeOp);
875   if (LocaleNCompare(mode,"colr",4) == 0)
876     return(ColorizeCompositeOp);
877   if (LocaleNCompare(mode,"lum ",4) == 0)
878     return(LuminizeCompositeOp);
879   if (LocaleNCompare(mode,"scrn",4) == 0)
880     return(ScreenCompositeOp);
881   if (LocaleNCompare(mode,"over",4) == 0)
882     return(OverlayCompositeOp);
883   if (LocaleNCompare(mode,"hLit",4) == 0)
884     return(HardLightCompositeOp);
885   if (LocaleNCompare(mode,"sLit",4) == 0)
886     return(SoftLightCompositeOp);
887   if (LocaleNCompare(mode,"smud",4) == 0)
888     return(ExclusionCompositeOp);
889   if (LocaleNCompare(mode,"div ",4) == 0)
890     return(ColorDodgeCompositeOp);
891   if (LocaleNCompare(mode,"idiv",4) == 0)
892     return(ColorBurnCompositeOp);
893   if (LocaleNCompare(mode,"lbrn",4) == 0)
894     return(LinearBurnCompositeOp);
895   if (LocaleNCompare(mode,"lddg",4) == 0)
896     return(LinearDodgeCompositeOp);
897   if (LocaleNCompare(mode,"lLit",4) == 0)
898     return(LinearLightCompositeOp);
899   if (LocaleNCompare(mode,"vLit",4) == 0)
900     return(VividLightCompositeOp);
901   if (LocaleNCompare(mode,"pLit",4) == 0)
902     return(PinLightCompositeOp);
903   if (LocaleNCompare(mode,"hMix",4) == 0)
904     return(HardMixCompositeOp);
905   return(OverCompositeOp);
906 }
907 
ReadPSDString(Image * image,char * p,const size_t length)908 static inline ssize_t ReadPSDString(Image *image,char *p,const size_t length)
909 {
910   ssize_t
911     count;
912 
913   count=ReadBlob(image,length,(unsigned char *) p);
914   if ((count == (ssize_t) length) && (image->endian != MSBEndian))
915     {
916       char
917         *q;
918 
919       q=p+length;
920       for(--q; p < q; ++p, --q)
921       {
922         *p = *p ^ *q,
923         *q = *p ^ *q,
924         *p = *p ^ *q;
925       }
926     }
927   return(count);
928 }
929 
SetPSDPixel(Image * image,const PixelChannel channel,const size_t packet_size,const Quantum pixel,Quantum * q,ExceptionInfo * exception)930 static inline void SetPSDPixel(Image *image,const PixelChannel channel,
931   const size_t packet_size,const Quantum pixel,Quantum *q,
932   ExceptionInfo *exception)
933 {
934   if (image->storage_class == PseudoClass)
935     {
936       PixelInfo
937         *color;
938 
939       ssize_t
940         index;
941 
942       if (channel == GrayPixelChannel)
943         {
944           index=(ssize_t) pixel;
945           if (packet_size == 1)
946             index=(ssize_t) ScaleQuantumToChar((Quantum) index);
947           index=ConstrainColormapIndex(image,index,exception);
948           SetPixelIndex(image,(Quantum) index,q);
949         }
950       else
951         {
952           index=(ssize_t) GetPixelIndex(image,q);
953           index=ConstrainColormapIndex(image,index,exception);
954         }
955       color=image->colormap+index;
956       if (channel == AlphaPixelChannel)
957         color->alpha=(MagickRealType) pixel;
958       SetPixelViaPixelInfo(image,color,q);
959     }
960   else
961     SetPixelChannel(image,channel,pixel,q);
962 }
963 
ReadPSDChannelPixels(Image * image,const ssize_t row,const PixelChannel channel,const unsigned char * pixels,ExceptionInfo * exception)964 static MagickBooleanType ReadPSDChannelPixels(Image *image,const ssize_t row,
965   const PixelChannel channel,const unsigned char *pixels,
966   ExceptionInfo *exception)
967 {
968   Quantum
969     pixel;
970 
971   const unsigned char
972     *p;
973 
974   Quantum
975     *q;
976 
977   ssize_t
978     x;
979 
980   size_t
981     packet_size;
982 
983   p=pixels;
984   q=GetAuthenticPixels(image,0,row,image->columns,1,exception);
985   if (q == (Quantum *) NULL)
986     return MagickFalse;
987   packet_size=GetPSDPacketSize(image);
988   for (x=0; x < (ssize_t) image->columns; x++)
989   {
990     if (packet_size == 1)
991       pixel=ScaleCharToQuantum(*p++);
992     else
993       if (packet_size == 2)
994         {
995           unsigned short
996             nibble;
997 
998           p=PushShortPixel(MSBEndian,p,&nibble);
999           pixel=ScaleShortToQuantum(nibble);
1000         }
1001       else
1002         {
1003           MagickFloatType
1004             nibble;
1005 
1006           p=PushFloatPixel(MSBEndian,p,&nibble);
1007           pixel=ClampToQuantum(((MagickRealType) QuantumRange)*nibble);
1008         }
1009     if (image->depth > 1)
1010       {
1011         SetPSDPixel(image,channel,packet_size,pixel,q,exception);
1012         q+=GetPixelChannels(image);
1013       }
1014     else
1015       {
1016         ssize_t
1017           bit,
1018           number_bits;
1019 
1020         number_bits=(ssize_t) image->columns-x;
1021         if (number_bits > 8)
1022           number_bits=8;
1023         for (bit = 0; bit < (ssize_t) number_bits; bit++)
1024         {
1025           SetPSDPixel(image,channel,packet_size,(((unsigned char) pixel)
1026             & (0x01 << (7-bit))) != 0 ? 0 : QuantumRange,q,exception);
1027           q+=GetPixelChannels(image);
1028           x++;
1029         }
1030         if (x != (ssize_t) image->columns)
1031           x--;
1032         continue;
1033       }
1034   }
1035   return(SyncAuthenticPixels(image,exception));
1036 }
1037 
ReadPSDChannelRaw(Image * image,const PixelChannel channel,ExceptionInfo * exception)1038 static MagickBooleanType ReadPSDChannelRaw(Image *image,const PixelChannel channel,
1039   ExceptionInfo *exception)
1040 {
1041   MagickBooleanType
1042     status;
1043 
1044   size_t
1045     row_size;
1046 
1047   ssize_t
1048     count,
1049     y;
1050 
1051   unsigned char
1052     *pixels;
1053 
1054   if (image->debug != MagickFalse)
1055     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1056        "      layer data is RAW");
1057 
1058   row_size=GetPSDRowSize(image);
1059   pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
1060   if (pixels == (unsigned char *) NULL)
1061     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1062       image->filename);
1063   (void) memset(pixels,0,row_size*sizeof(*pixels));
1064 
1065   status=MagickTrue;
1066   for (y=0; y < (ssize_t) image->rows; y++)
1067   {
1068     status=MagickFalse;
1069 
1070     count=ReadBlob(image,row_size,pixels);
1071     if (count != (ssize_t) row_size)
1072       break;
1073 
1074     status=ReadPSDChannelPixels(image,y,channel,pixels,exception);
1075     if (status == MagickFalse)
1076       break;
1077   }
1078 
1079   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1080   return(status);
1081 }
1082 
ReadPSDRLESizes(Image * image,const PSDInfo * psd_info,const size_t size)1083 static inline MagickOffsetType *ReadPSDRLESizes(Image *image,
1084   const PSDInfo *psd_info,const size_t size)
1085 {
1086   MagickOffsetType
1087     *sizes;
1088 
1089   ssize_t
1090     y;
1091 
1092   sizes=(MagickOffsetType *) AcquireQuantumMemory(size,sizeof(*sizes));
1093   if(sizes != (MagickOffsetType *) NULL)
1094     {
1095       for (y=0; y < (ssize_t) size; y++)
1096       {
1097         if (psd_info->version == 1)
1098           sizes[y]=(MagickOffsetType) ReadBlobShort(image);
1099         else
1100           sizes[y]=(MagickOffsetType) ReadBlobLong(image);
1101       }
1102     }
1103   return sizes;
1104 }
1105 
ReadPSDChannelRLE(Image * image,const PixelChannel channel,MagickOffsetType * sizes,ExceptionInfo * exception)1106 static MagickBooleanType ReadPSDChannelRLE(Image *image,
1107   const PixelChannel channel,MagickOffsetType *sizes,
1108   ExceptionInfo *exception)
1109 {
1110   MagickBooleanType
1111     status;
1112 
1113   size_t
1114     length,
1115     row_size;
1116 
1117   ssize_t
1118     count,
1119     y;
1120 
1121   unsigned char
1122     *compact_pixels,
1123     *pixels;
1124 
1125   if (image->debug != MagickFalse)
1126     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1127        "      layer data is RLE compressed");
1128 
1129   row_size=GetPSDRowSize(image);
1130   pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
1131   if (pixels == (unsigned char *) NULL)
1132     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1133       image->filename);
1134 
1135   length=0;
1136   for (y=0; y < (ssize_t) image->rows; y++)
1137     if ((MagickOffsetType) length < sizes[y])
1138       length=(size_t) sizes[y];
1139 
1140   if (length > (row_size+2048)) /* arbitrary number */
1141     {
1142       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1143       ThrowBinaryException(ResourceLimitError,"InvalidLength",image->filename);
1144     }
1145 
1146   compact_pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
1147   if (compact_pixels == (unsigned char *) NULL)
1148     {
1149       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1150       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1151         image->filename);
1152     }
1153 
1154   (void) memset(compact_pixels,0,length*sizeof(*compact_pixels));
1155 
1156   status=MagickTrue;
1157   for (y=0; y < (ssize_t) image->rows; y++)
1158   {
1159     status=MagickFalse;
1160 
1161     count=ReadBlob(image,(size_t) sizes[y],compact_pixels);
1162     if (count != (ssize_t) sizes[y])
1163       break;
1164 
1165     count=DecodePSDPixels((size_t) sizes[y],compact_pixels,
1166       (ssize_t) (image->depth == 1 ? 123456 : image->depth),row_size,pixels);
1167     if (count != (ssize_t) row_size)
1168       break;
1169 
1170     status=ReadPSDChannelPixels(image,y,channel,pixels,exception);
1171     if (status == MagickFalse)
1172       break;
1173   }
1174 
1175   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
1176   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1177   return(status);
1178 }
1179 
1180 #ifdef MAGICKCORE_ZLIB_DELEGATE
Unpredict8Bit(const Image * image,unsigned char * pixels,const size_t count,const size_t row_size)1181 static void Unpredict8Bit(const Image *image,unsigned char *pixels,
1182   const size_t count,const size_t row_size)
1183 {
1184   unsigned char
1185     *p;
1186 
1187   size_t
1188     length,
1189     remaining;
1190 
1191   p=pixels;
1192   remaining=count;
1193   while (remaining > 0)
1194   {
1195     length=image->columns;
1196     while (--length)
1197     {
1198       *(p+1)+=*p;
1199       p++;
1200     }
1201     p++;
1202     remaining-=row_size;
1203   }
1204 }
1205 
Unpredict16Bit(const Image * image,unsigned char * pixels,const size_t count,const size_t row_size)1206 static void Unpredict16Bit(const Image *image,unsigned char *pixels,
1207   const size_t count,const size_t row_size)
1208 {
1209   unsigned char
1210     *p;
1211 
1212   size_t
1213     length,
1214     remaining;
1215 
1216   p=pixels;
1217   remaining=count;
1218   while (remaining > 0)
1219   {
1220     length=image->columns;
1221     while (--length)
1222     {
1223       p[2]+=p[0]+((p[1]+p[3]) >> 8);
1224       p[3]+=p[1];
1225       p+=2;
1226     }
1227     p+=2;
1228     remaining-=row_size;
1229   }
1230 }
1231 
Unpredict32Bit(const Image * image,unsigned char * pixels,unsigned char * output_pixels,const size_t row_size)1232 static void Unpredict32Bit(const Image *image,unsigned char *pixels,
1233   unsigned char *output_pixels,const size_t row_size)
1234 {
1235   unsigned char
1236     *p,
1237     *q;
1238 
1239   ssize_t
1240     y;
1241 
1242   size_t
1243     offset1,
1244     offset2,
1245     offset3,
1246     remaining;
1247 
1248   unsigned char
1249     *start;
1250 
1251   offset1=image->columns;
1252   offset2=2*offset1;
1253   offset3=3*offset1;
1254   p=pixels;
1255   q=output_pixels;
1256   for (y=0; y < (ssize_t) image->rows; y++)
1257   {
1258     start=p;
1259     remaining=row_size;
1260     while (--remaining)
1261     {
1262       *(p+1)+=*p;
1263       p++;
1264     }
1265 
1266     p=start;
1267     remaining=image->columns;
1268     while (remaining--)
1269     {
1270       *(q++)=*p;
1271       *(q++)=*(p+offset1);
1272       *(q++)=*(p+offset2);
1273       *(q++)=*(p+offset3);
1274 
1275       p++;
1276     }
1277     p=start+row_size;
1278   }
1279 }
1280 
ReadPSDChannelZip(Image * image,const PixelChannel channel,const PSDCompressionType compression,const size_t compact_size,ExceptionInfo * exception)1281 static MagickBooleanType ReadPSDChannelZip(Image *image,
1282   const PixelChannel channel,const PSDCompressionType compression,
1283   const size_t compact_size,ExceptionInfo *exception)
1284 {
1285   MagickBooleanType
1286     status;
1287 
1288   unsigned char
1289     *p;
1290 
1291   size_t
1292     count,
1293     packet_size,
1294     row_size;
1295 
1296   ssize_t
1297     y;
1298 
1299   unsigned char
1300     *compact_pixels,
1301     *pixels;
1302 
1303   z_stream
1304     stream;
1305 
1306   if (image->debug != MagickFalse)
1307     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1308        "      layer data is ZIP compressed");
1309 
1310   if ((MagickSizeType) compact_size > GetBlobSize(image))
1311     ThrowBinaryException(CorruptImageError,"UnexpectedEndOfFile",
1312       image->filename);
1313   compact_pixels=(unsigned char *) AcquireQuantumMemory(compact_size,
1314     sizeof(*compact_pixels));
1315   if (compact_pixels == (unsigned char *) NULL)
1316     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1317       image->filename);
1318 
1319   packet_size=GetPSDPacketSize(image);
1320   row_size=image->columns*packet_size;
1321   count=image->rows*row_size;
1322 
1323   pixels=(unsigned char *) AcquireQuantumMemory(count,sizeof(*pixels));
1324   if (pixels == (unsigned char *) NULL)
1325     {
1326       compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
1327       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1328         image->filename);
1329     }
1330   if (ReadBlob(image,compact_size,compact_pixels) != (ssize_t) compact_size)
1331     {
1332       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1333       compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
1334       ThrowBinaryException(CorruptImageError,"UnexpectedEndOfFile",
1335         image->filename);
1336     }
1337 
1338   memset(&stream,0,sizeof(stream));
1339   stream.data_type=Z_BINARY;
1340   stream.next_in=(Bytef *)compact_pixels;
1341   stream.avail_in=(uInt) compact_size;
1342   stream.next_out=(Bytef *)pixels;
1343   stream.avail_out=(uInt) count;
1344 
1345   if (inflateInit(&stream) == Z_OK)
1346     {
1347       int
1348         ret;
1349 
1350       while (stream.avail_out > 0)
1351       {
1352         ret=inflate(&stream,Z_SYNC_FLUSH);
1353         if ((ret != Z_OK) && (ret != Z_STREAM_END))
1354           {
1355             (void) inflateEnd(&stream);
1356             compact_pixels=(unsigned char *) RelinquishMagickMemory(
1357               compact_pixels);
1358             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1359             return(MagickFalse);
1360           }
1361         if (ret == Z_STREAM_END)
1362           break;
1363       }
1364       (void) inflateEnd(&stream);
1365     }
1366 
1367   if (compression == ZipWithPrediction)
1368     {
1369       if (packet_size == 1)
1370         Unpredict8Bit(image,pixels,count,row_size);
1371       else if (packet_size == 2)
1372         Unpredict16Bit(image,pixels,count,row_size);
1373       else if (packet_size == 4)
1374       {
1375         unsigned char
1376           *output_pixels;
1377 
1378         output_pixels=(unsigned char *) AcquireQuantumMemory(count,
1379           sizeof(*output_pixels));
1380         if (pixels == (unsigned char *) NULL)
1381           {
1382             compact_pixels=(unsigned char *) RelinquishMagickMemory(
1383               compact_pixels);
1384             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1385             ThrowBinaryException(ResourceLimitError,
1386               "MemoryAllocationFailed",image->filename);
1387           }
1388         Unpredict32Bit(image,pixels,output_pixels,row_size);
1389         pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1390         pixels=output_pixels;
1391       }
1392     }
1393 
1394   status=MagickTrue;
1395   p=pixels;
1396   for (y=0; y < (ssize_t) image->rows; y++)
1397   {
1398     status=ReadPSDChannelPixels(image,y,channel,p,exception);
1399     if (status == MagickFalse)
1400       break;
1401 
1402     p+=row_size;
1403   }
1404 
1405   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
1406   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1407   return(status);
1408 }
1409 #endif
1410 
ReadPSDChannel(Image * image,const ImageInfo * image_info,const PSDInfo * psd_info,LayerInfo * layer_info,const size_t channel_index,const PSDCompressionType compression,ExceptionInfo * exception)1411 static MagickBooleanType ReadPSDChannel(Image *image,
1412   const ImageInfo *image_info,const PSDInfo *psd_info,LayerInfo* layer_info,
1413   const size_t channel_index,const PSDCompressionType compression,
1414   ExceptionInfo *exception)
1415 {
1416   Image
1417     *channel_image,
1418     *mask;
1419 
1420   MagickOffsetType
1421     end_offset,
1422     offset;
1423 
1424   MagickBooleanType
1425     status;
1426 
1427   PixelChannel
1428     channel;
1429 
1430   end_offset=(MagickOffsetType) layer_info->channel_info[channel_index].size-2;
1431   if (layer_info->channel_info[channel_index].supported == MagickFalse)
1432     {
1433       (void) SeekBlob(image,end_offset,SEEK_CUR);
1434       return(MagickTrue);
1435     }
1436   channel_image=image;
1437   channel=layer_info->channel_info[channel_index].channel;
1438   mask=(Image *) NULL;
1439   if (channel == ReadMaskPixelChannel)
1440     {
1441       const char
1442         *option;
1443 
1444       /*
1445         Ignore mask that is not a user supplied layer mask, if the mask is
1446         disabled or if the flags have unsupported values.
1447       */
1448       option=GetImageOption(image_info,"psd:preserve-opacity-mask");
1449       if ((layer_info->mask.flags > 2) || ((layer_info->mask.flags & 0x02) &&
1450            (IsStringTrue(option) == MagickFalse)) ||
1451            (layer_info->mask.page.width < 1) ||
1452            (layer_info->mask.page.height < 1))
1453         {
1454           (void) SeekBlob(image,end_offset,SEEK_CUR);
1455           return(MagickTrue);
1456         }
1457       mask=CloneImage(image,layer_info->mask.page.width,
1458         layer_info->mask.page.height,MagickFalse,exception);
1459       if (mask != (Image *) NULL)
1460         {
1461           (void) ResetImagePixels(mask,exception);
1462           (void) SetImageType(mask,GrayscaleType,exception);
1463           channel_image=mask;
1464           channel=GrayPixelChannel;
1465         }
1466     }
1467 
1468   offset=TellBlob(image);
1469   status=MagickFalse;
1470   switch(compression)
1471   {
1472     case Raw:
1473       status=ReadPSDChannelRaw(channel_image,channel,exception);
1474       break;
1475     case RLE:
1476       {
1477         MagickOffsetType
1478           *sizes;
1479 
1480         sizes=ReadPSDRLESizes(channel_image,psd_info,channel_image->rows);
1481         if (sizes == (MagickOffsetType *) NULL)
1482           ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1483             image->filename);
1484         status=ReadPSDChannelRLE(channel_image,channel,sizes,exception);
1485         sizes=(MagickOffsetType *) RelinquishMagickMemory(sizes);
1486       }
1487       break;
1488     case ZipWithPrediction:
1489     case ZipWithoutPrediction:
1490 #ifdef MAGICKCORE_ZLIB_DELEGATE
1491       status=ReadPSDChannelZip(channel_image,channel,compression,
1492         (const size_t) end_offset,exception);
1493 #else
1494       (void) ThrowMagickException(exception,GetMagickModule(),
1495           MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
1496             "'%s' (ZLIB)",image->filename);
1497 #endif
1498       break;
1499     default:
1500       (void) ThrowMagickException(exception,GetMagickModule(),TypeWarning,
1501         "CompressionNotSupported","'%.20g'",(double) compression);
1502       break;
1503   }
1504 
1505   (void) SeekBlob(image,offset+end_offset,SEEK_SET);
1506   if (status == MagickFalse)
1507     {
1508       if (mask != (Image *) NULL)
1509         (void) DestroyImage(mask);
1510       ThrowBinaryException(CoderError,"UnableToDecompressImage",
1511         image->filename);
1512     }
1513   if (mask != (Image *) NULL)
1514     {
1515       if (layer_info->mask.image != (Image *) NULL)
1516         layer_info->mask.image=DestroyImage(layer_info->mask.image);
1517       layer_info->mask.image=mask;
1518     }
1519   return(status);
1520 }
1521 
GetPixelChannelFromPsdIndex(const PSDInfo * psd_info,ssize_t index,PixelChannel * channel)1522 static MagickBooleanType GetPixelChannelFromPsdIndex(const PSDInfo *psd_info,
1523   ssize_t index,PixelChannel *channel)
1524 {
1525   *channel=RedPixelChannel;
1526   switch (psd_info->mode)
1527   {
1528     case BitmapMode:
1529     case IndexedMode:
1530     case GrayscaleMode:
1531     {
1532       if (index == 1)
1533         index=-1;
1534       else if (index > 1)
1535         index=StartMetaPixelChannel+index-2;
1536       break;
1537     }
1538     case LabMode:
1539     case MultichannelMode:
1540     case RGBMode:
1541     {
1542       if (index == 3)
1543         index=-1;
1544       else if (index > 3)
1545         index=StartMetaPixelChannel+index-4;
1546       break;
1547     }
1548     case CMYKMode:
1549     {
1550       if (index == 4)
1551         index=-1;
1552       else if (index > 4)
1553         index=StartMetaPixelChannel+index-5;
1554       break;
1555     }
1556   }
1557   if ((index < -2) || (index >= MaxPixelChannels))
1558     return(MagickFalse);
1559   if (index == -1)
1560     *channel=AlphaPixelChannel;
1561   else if (index == -2)
1562     *channel=ReadMaskPixelChannel;
1563   else
1564     *channel=(PixelChannel) index;
1565   return(MagickTrue);
1566 }
1567 
SetPsdMetaChannels(Image * image,const PSDInfo * psd_info,const unsigned short channels,ExceptionInfo * exception)1568 static void SetPsdMetaChannels(Image *image,const PSDInfo *psd_info,
1569   const unsigned short channels,ExceptionInfo *exception)
1570 {
1571   ssize_t
1572     number_meta_channels;
1573 
1574   number_meta_channels=(ssize_t) channels-psd_info->min_channels;
1575   if (image->alpha_trait == BlendPixelTrait)
1576     number_meta_channels--;
1577   if (number_meta_channels > 0)
1578     (void) SetPixelMetaChannels(image,(size_t) number_meta_channels,exception);
1579 }
1580 
ReadPSDLayer(Image * image,const ImageInfo * image_info,const PSDInfo * psd_info,LayerInfo * layer_info,ExceptionInfo * exception)1581 static MagickBooleanType ReadPSDLayer(Image *image,const ImageInfo *image_info,
1582   const PSDInfo *psd_info,LayerInfo* layer_info,ExceptionInfo *exception)
1583 {
1584   char
1585     message[MagickPathExtent];
1586 
1587   MagickBooleanType
1588     status;
1589 
1590   PSDCompressionType
1591     compression;
1592 
1593   ssize_t
1594     j;
1595 
1596   if (image->debug != MagickFalse)
1597     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1598       "    setting up new layer image");
1599   if (psd_info->mode != IndexedMode)
1600     (void) SetImageBackgroundColor(layer_info->image,exception);
1601   layer_info->image->compose=PSDBlendModeToCompositeOperator(
1602     layer_info->blendkey);
1603   if (layer_info->visible == MagickFalse)
1604     layer_info->image->compose=NoCompositeOp;
1605   /*
1606     Set up some hidden attributes for folks that need them.
1607   */
1608   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
1609     (double) layer_info->page.x);
1610   (void) SetImageArtifact(layer_info->image,"psd:layer.x",message);
1611   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
1612     (double) layer_info->page.y);
1613   (void) SetImageArtifact(layer_info->image,"psd:layer.y",message);
1614   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
1615     layer_info->opacity);
1616   (void) SetImageArtifact(layer_info->image,"psd:layer.opacity",message);
1617   (void) SetImageProperty(layer_info->image,"label",(char *) layer_info->name,
1618     exception);
1619 
1620   SetPsdMetaChannels(layer_info->image,psd_info,layer_info->channels,exception);
1621   status=MagickTrue;
1622   for (j=0; j < (ssize_t) layer_info->channels; j++)
1623   {
1624     if (image->debug != MagickFalse)
1625       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1626         "    reading data for channel %.20g",(double) j);
1627 
1628     compression=(PSDCompressionType) ReadBlobShort(layer_info->image);
1629     layer_info->image->compression=ConvertPSDCompression(compression);
1630 
1631     status=ReadPSDChannel(layer_info->image,image_info,psd_info,layer_info,
1632       (size_t) j,compression,exception);
1633 
1634     if (status == MagickFalse)
1635       break;
1636   }
1637 
1638   if (status != MagickFalse)
1639     status=ApplyPSDLayerOpacity(layer_info->image,layer_info->opacity,
1640       MagickFalse,exception);
1641 
1642   if ((status != MagickFalse) &&
1643       (layer_info->image->colorspace == CMYKColorspace))
1644     status=NegateCMYK(layer_info->image,exception);
1645 
1646   if ((status != MagickFalse) && (layer_info->mask.image != (Image *) NULL))
1647     {
1648       const char
1649         *option;
1650 
1651       layer_info->mask.image->page.x=layer_info->mask.page.x;
1652       layer_info->mask.image->page.y=layer_info->mask.page.y;
1653       /* Do not composite the mask when it is disabled */
1654       if ((layer_info->mask.flags & 0x02) == 0x02)
1655         layer_info->mask.image->compose=NoCompositeOp;
1656       else
1657         status=ApplyPSDOpacityMask(layer_info->image,layer_info->mask.image,
1658           layer_info->mask.background == 0 ? 0 : QuantumRange,MagickFalse,
1659           exception);
1660       option=GetImageOption(image_info,"psd:preserve-opacity-mask");
1661       if (IsStringTrue(option) != MagickFalse)
1662         PreservePSDOpacityMask(image,layer_info,exception);
1663       layer_info->mask.image=DestroyImage(layer_info->mask.image);
1664     }
1665 
1666   return(status);
1667 }
1668 
CheckPSDChannels(const PSDInfo * psd_info,LayerInfo * layer_info)1669 static MagickBooleanType CheckPSDChannels(const PSDInfo *psd_info,
1670   LayerInfo *layer_info)
1671 {
1672   int
1673     channel_type;
1674 
1675   ssize_t
1676     i;
1677 
1678   if (layer_info->channels < psd_info->min_channels)
1679     return(MagickFalse);
1680   channel_type=RedChannel;
1681   if (psd_info->min_channels >= 3)
1682     channel_type|=(GreenChannel | BlueChannel);
1683   if (psd_info->min_channels >= 4)
1684     channel_type|=BlackChannel;
1685   for (i=0; i < (ssize_t) layer_info->channels; i++)
1686   {
1687     PixelChannel
1688       channel;
1689 
1690     if (layer_info->channel_info[i].supported == MagickFalse)
1691       continue;
1692     channel=layer_info->channel_info[i].channel;
1693     if ((i == 0) && (psd_info->mode == IndexedMode) &&
1694         (channel != RedPixelChannel))
1695       return(MagickFalse);
1696     if (channel == AlphaPixelChannel)
1697       {
1698         channel_type|=AlphaChannel;
1699         continue;
1700       }
1701     if (channel == RedPixelChannel)
1702       channel_type&=~RedChannel;
1703     else if (channel == GreenPixelChannel)
1704       channel_type&=~GreenChannel;
1705     else if (channel == BluePixelChannel)
1706       channel_type&=~BlueChannel;
1707     else if (channel == BlackPixelChannel)
1708       channel_type&=~BlackChannel;
1709   }
1710   if (channel_type == 0)
1711     return(MagickTrue);
1712   if ((channel_type == AlphaChannel) &&
1713       (layer_info->channels >= psd_info->min_channels + 1))
1714     return(MagickTrue);
1715   return(MagickFalse);
1716 }
1717 
AttachPSDLayers(Image * image,LayerInfo * layer_info,ssize_t number_layers)1718 static void AttachPSDLayers(Image *image,LayerInfo *layer_info,
1719   ssize_t number_layers)
1720 {
1721   ssize_t
1722     i;
1723 
1724   ssize_t
1725     j;
1726 
1727   for (i=0; i < number_layers; i++)
1728   {
1729     if (layer_info[i].image == (Image *) NULL)
1730       {
1731         for (j=i; j < number_layers - 1; j++)
1732           layer_info[j] = layer_info[j+1];
1733         number_layers--;
1734         i--;
1735       }
1736   }
1737   if (number_layers == 0)
1738     {
1739       layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
1740       return;
1741     }
1742   for (i=0; i < number_layers; i++)
1743   {
1744     if (i > 0)
1745       layer_info[i].image->previous=layer_info[i-1].image;
1746     if (i < (number_layers-1))
1747       layer_info[i].image->next=layer_info[i+1].image;
1748     layer_info[i].image->page=layer_info[i].page;
1749   }
1750   image->next=layer_info[0].image;
1751   layer_info[0].image->previous=image;
1752   layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
1753 }
1754 
PSDSkipImage(const PSDInfo * psd_info,const ImageInfo * image_info,const size_t index)1755 static inline MagickBooleanType PSDSkipImage(const PSDInfo *psd_info,
1756   const ImageInfo *image_info,const size_t index)
1757 {
1758   if (psd_info->has_merged_image == MagickFalse)
1759     return(MagickFalse);
1760   if (image_info->number_scenes == 0)
1761     return(MagickFalse);
1762   if (index < image_info->scene)
1763     return(MagickTrue);
1764   if (index > image_info->scene+image_info->number_scenes-1)
1765     return(MagickTrue);
1766   return(MagickFalse);
1767 }
1768 
CheckMergedImageAlpha(const PSDInfo * psd_info,Image * image)1769 static void CheckMergedImageAlpha(const PSDInfo *psd_info,Image *image)
1770 {
1771   /*
1772     The number of layers cannot be used to determine if the merged image
1773     contains an alpha channel. So we enable it when we think we should.
1774   */
1775   if (((psd_info->mode == GrayscaleMode) && (psd_info->channels > 1)) ||
1776       ((psd_info->mode == RGBMode) && (psd_info->channels > 3)) ||
1777       ((psd_info->mode == CMYKMode) && (psd_info->channels > 4)))
1778     image->alpha_trait=BlendPixelTrait;
1779 }
1780 
ParseAdditionalInfo(LayerInfo * layer_info)1781 static void ParseAdditionalInfo(LayerInfo *layer_info)
1782 {
1783   char
1784     key[5];
1785 
1786   size_t
1787     remaining_length;
1788 
1789   unsigned char
1790     *p;
1791 
1792   unsigned int
1793     size;
1794 
1795   p=GetStringInfoDatum(layer_info->info);
1796   remaining_length=GetStringInfoLength(layer_info->info);
1797   while (remaining_length >= 12)
1798   {
1799     /* skip over signature */
1800     p+=4;
1801     key[0]=(char) (*p++);
1802     key[1]=(char) (*p++);
1803     key[2]=(char) (*p++);
1804     key[3]=(char) (*p++);
1805     key[4]='\0';
1806     size=(unsigned int) (*p++) << 24;
1807     size|=(unsigned int) (*p++) << 16;
1808     size|=(unsigned int) (*p++) << 8;
1809     size|=(unsigned int) (*p++);
1810     size=size & 0xffffffff;
1811     remaining_length-=12;
1812     if ((size_t) size > remaining_length)
1813       break;
1814     if (LocaleNCompare(key,"luni",sizeof(key)) == 0)
1815       {
1816         unsigned char
1817           *name;
1818 
1819         unsigned int
1820           length;
1821 
1822         length=(unsigned int) (*p++) << 24;
1823         length|=(unsigned int) (*p++) << 16;
1824         length|=(unsigned int) (*p++) << 8;
1825         length|=(unsigned int) (*p++);
1826         if (length * 2 > size - 4)
1827           break;
1828         if (sizeof(layer_info->name) <= length)
1829           break;
1830         name=layer_info->name;
1831         while (length > 0)
1832         {
1833           /* Only ASCII strings are supported */
1834           if (*p++ != '\0')
1835             break;
1836           *name++=*p++;
1837           length--;
1838         }
1839         if (length == 0)
1840           *name='\0';
1841         break;
1842       }
1843     else
1844       p+=size;
1845     remaining_length-=(size_t) size;
1846   }
1847 }
1848 
GetLayerInfoSize(const PSDInfo * psd_info,Image * image)1849 static MagickSizeType GetLayerInfoSize(const PSDInfo *psd_info,Image *image)
1850 {
1851   char
1852     type[4];
1853 
1854   MagickSizeType
1855     size;
1856 
1857   ssize_t
1858     count;
1859 
1860   size=GetPSDSize(psd_info,image);
1861   if (size != 0)
1862     return(size);
1863   (void) ReadBlobLong(image);
1864   count=ReadPSDString(image,type,4);
1865   if ((count != 4) || (LocaleNCompare(type,"8BIM",4) != 0))
1866     return(0);
1867   count=ReadPSDString(image,type,4);
1868   if ((count == 4) && ((LocaleNCompare(type,"Mt16",4) == 0) ||
1869       (LocaleNCompare(type,"Mt32",4) == 0) ||
1870       (LocaleNCompare(type,"Mtrn",4) == 0)))
1871     {
1872       size=GetPSDSize(psd_info,image);
1873       if (size != 0)
1874         return(0);
1875       image->alpha_trait=BlendPixelTrait;
1876       count=ReadPSDString(image,type,4);
1877       if ((count != 4) || (LocaleNCompare(type,"8BIM",4) != 0))
1878         return(0);
1879       count=ReadPSDString(image,type,4);
1880     }
1881   if ((count == 4) && ((LocaleNCompare(type,"Lr16",4) == 0) ||
1882       (LocaleNCompare(type,"Lr32",4) == 0)))
1883     size=GetPSDSize(psd_info,image);
1884   return(size);
1885 }
1886 
ReadPSDLayersInternal(Image * image,const ImageInfo * image_info,const PSDInfo * psd_info,const MagickBooleanType skip_layers,ExceptionInfo * exception)1887 static MagickBooleanType ReadPSDLayersInternal(Image *image,
1888   const ImageInfo *image_info,const PSDInfo *psd_info,
1889   const MagickBooleanType skip_layers,ExceptionInfo *exception)
1890 {
1891   char
1892     type[4];
1893 
1894   LayerInfo
1895     *layer_info;
1896 
1897   MagickSizeType
1898     size;
1899 
1900   MagickBooleanType
1901     status;
1902 
1903   ssize_t
1904     count,
1905     index,
1906     i,
1907     j,
1908     number_layers;
1909 
1910   size=GetLayerInfoSize(psd_info,image);
1911   if (size == 0)
1912     {
1913       CheckMergedImageAlpha(psd_info,image);
1914       return(MagickTrue);
1915     }
1916 
1917   layer_info=(LayerInfo *) NULL;
1918   number_layers=(ssize_t) ReadBlobSignedShort(image);
1919 
1920   if (number_layers < 0)
1921     {
1922       /*
1923         The first alpha channel in the merged result contains the
1924         transparency data for the merged result.
1925       */
1926       number_layers=MagickAbsoluteValue(number_layers);
1927       if (image->debug != MagickFalse)
1928         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1929           "  negative layer count corrected for");
1930       image->alpha_trait=BlendPixelTrait;
1931     }
1932 
1933   /*
1934     We only need to know if the image has an alpha channel
1935   */
1936   if (skip_layers != MagickFalse)
1937     return(MagickTrue);
1938 
1939   if (image->debug != MagickFalse)
1940     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1941       "  image contains %.20g layers",(double) number_layers);
1942 
1943   if (number_layers == 0)
1944     ThrowBinaryException(CorruptImageError,"InvalidNumberOfLayers",
1945       image->filename);
1946 
1947   layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
1948     sizeof(*layer_info));
1949   if (layer_info == (LayerInfo *) NULL)
1950     {
1951       if (image->debug != MagickFalse)
1952         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1953           "  allocation of LayerInfo failed");
1954       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1955         image->filename);
1956     }
1957   (void) memset(layer_info,0,(size_t) number_layers*sizeof(*layer_info));
1958 
1959   for (i=0; i < number_layers; i++)
1960   {
1961     ssize_t
1962       top,
1963       left,
1964       bottom,
1965       right;
1966 
1967     if (image->debug != MagickFalse)
1968       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1969         "  reading layer #%.20g",(double) i+1);
1970     top=(ssize_t) ReadBlobSignedLong(image);
1971     left=(ssize_t) ReadBlobSignedLong(image);
1972     bottom=(ssize_t) ReadBlobSignedLong(image);
1973     right=(ssize_t) ReadBlobSignedLong(image);
1974     if ((right < left) || (bottom < top))
1975       {
1976         layer_info=DestroyLayerInfo(layer_info,number_layers);
1977         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
1978           image->filename);
1979       }
1980     layer_info[i].page.y=top;
1981     layer_info[i].page.x=left;
1982     layer_info[i].page.width=(size_t) (right-left);
1983     layer_info[i].page.height=(size_t) (bottom-top);
1984     layer_info[i].channels=ReadBlobShort(image);
1985     if (layer_info[i].channels > MaxPSDChannels)
1986       {
1987         layer_info=DestroyLayerInfo(layer_info,number_layers);
1988         ThrowBinaryException(CorruptImageError,"MaximumChannelsExceeded",
1989           image->filename);
1990       }
1991     if (image->debug != MagickFalse)
1992       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1993         "    offset(%.20g,%.20g), size(%.20g,%.20g), channels=%.20g",
1994         (double) layer_info[i].page.x,(double) layer_info[i].page.y,
1995         (double) layer_info[i].page.height,(double)
1996         layer_info[i].page.width,(double) layer_info[i].channels);
1997     for (j=0; j < (ssize_t) layer_info[i].channels; j++)
1998     {
1999       layer_info[i].channel_info[j].supported=GetPixelChannelFromPsdIndex(
2000         psd_info,(ssize_t) ReadBlobSignedShort(image),
2001         &layer_info[i].channel_info[j].channel);
2002       layer_info[i].channel_info[j].size=(size_t) GetPSDSize(psd_info,
2003         image);
2004       if (image->debug != MagickFalse)
2005         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2006           "    channel[%.20g]: type=%.20g, size=%.20g",(double) j,
2007           (double) layer_info[i].channel_info[j].channel,
2008           (double) layer_info[i].channel_info[j].size);
2009     }
2010     if (CheckPSDChannels(psd_info,&layer_info[i]) == MagickFalse)
2011       {
2012         layer_info=DestroyLayerInfo(layer_info,number_layers);
2013         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
2014           image->filename);
2015       }
2016     count=ReadPSDString(image,type,4);
2017     if ((count != 4) || (LocaleNCompare(type,"8BIM",4) != 0))
2018       {
2019         if (image->debug != MagickFalse)
2020           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2021             "  layer type was %.4s instead of 8BIM", type);
2022         layer_info=DestroyLayerInfo(layer_info,number_layers);
2023         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
2024           image->filename);
2025       }
2026     count=ReadPSDString(image,layer_info[i].blendkey,4);
2027     if (count != 4)
2028       {
2029         layer_info=DestroyLayerInfo(layer_info,number_layers);
2030         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
2031           image->filename);
2032       }
2033     layer_info[i].opacity=(Quantum) ScaleCharToQuantum((unsigned char)
2034       ReadBlobByte(image));
2035     layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
2036     layer_info[i].flags=(unsigned char) ReadBlobByte(image);
2037     layer_info[i].visible=!(layer_info[i].flags & 0x02);
2038     if (image->debug != MagickFalse)
2039       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2040         "   blend=%.4s, opacity=%.20g, clipping=%s, flags=%d, visible=%s",
2041         layer_info[i].blendkey,(double) layer_info[i].opacity,
2042         layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
2043         layer_info[i].visible ? "true" : "false");
2044     (void) ReadBlobByte(image);  /* filler */
2045 
2046     size=ReadBlobLong(image);
2047     if (size != 0)
2048       {
2049         MagickSizeType
2050           combined_length,
2051           length;
2052 
2053         if (image->debug != MagickFalse)
2054           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2055             "    layer contains additional info");
2056         length=ReadBlobLong(image);
2057         combined_length=length+4;
2058         if (length != 0)
2059           {
2060             /*
2061               Layer mask info.
2062             */
2063             layer_info[i].mask.page.y=(ssize_t) ReadBlobSignedLong(image);
2064             layer_info[i].mask.page.x=(ssize_t) ReadBlobSignedLong(image);
2065             layer_info[i].mask.page.height=(size_t)
2066               (ReadBlobSignedLong(image)-layer_info[i].mask.page.y);
2067             layer_info[i].mask.page.width=(size_t) (
2068               ReadBlobSignedLong(image)-layer_info[i].mask.page.x);
2069             layer_info[i].mask.background=(unsigned char) ReadBlobByte(
2070               image);
2071             layer_info[i].mask.flags=(unsigned char) ReadBlobByte(image);
2072             if (!(layer_info[i].mask.flags & 0x01))
2073               {
2074                 layer_info[i].mask.page.y=layer_info[i].mask.page.y-
2075                   layer_info[i].page.y;
2076                 layer_info[i].mask.page.x=layer_info[i].mask.page.x-
2077                   layer_info[i].page.x;
2078               }
2079             if (image->debug != MagickFalse)
2080               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2081                 "      layer mask: offset(%.20g,%.20g), size(%.20g,%.20g), length=%.20g",
2082                 (double) layer_info[i].mask.page.x,(double)
2083                 layer_info[i].mask.page.y,(double)
2084                 layer_info[i].mask.page.width,(double)
2085                 layer_info[i].mask.page.height,(double) ((MagickOffsetType)
2086                 length)-18);
2087             /*
2088               Skip over the rest of the layer mask information.
2089             */
2090             if (DiscardBlobBytes(image,(MagickSizeType) (length-18)) == MagickFalse)
2091               {
2092                 layer_info=DestroyLayerInfo(layer_info,number_layers);
2093                 ThrowBinaryException(CorruptImageError,
2094                   "UnexpectedEndOfFile",image->filename);
2095               }
2096           }
2097         length=ReadBlobLong(image);
2098         combined_length+=length+4;
2099         if (length != 0)
2100           {
2101             /*
2102               Layer blending ranges info.
2103             */
2104             if (image->debug != MagickFalse)
2105               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2106                 "      layer blending ranges: length=%.20g",(double)
2107                 ((MagickOffsetType) length));
2108             if (DiscardBlobBytes(image,length) == MagickFalse)
2109               {
2110                 layer_info=DestroyLayerInfo(layer_info,number_layers);
2111                 ThrowBinaryException(CorruptImageError,
2112                   "UnexpectedEndOfFile",image->filename);
2113               }
2114           }
2115         /*
2116           Layer name.
2117         */
2118         length=(MagickSizeType) (unsigned char) ReadBlobByte(image);
2119         combined_length+=length+1;
2120         if (length > 0)
2121           (void) ReadBlob(image,(size_t) length++,layer_info[i].name);
2122         layer_info[i].name[length]='\0';
2123         if (image->debug != MagickFalse)
2124           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2125             "      layer name: %s",layer_info[i].name);
2126         if ((length % 4) != 0)
2127           {
2128             length=4-(length % 4);
2129             combined_length+=length;
2130             /* Skip over the padding of the layer name */
2131             if (DiscardBlobBytes(image,length) == MagickFalse)
2132               {
2133                 layer_info=DestroyLayerInfo(layer_info,number_layers);
2134                 ThrowBinaryException(CorruptImageError,
2135                   "UnexpectedEndOfFile",image->filename);
2136               }
2137           }
2138         length=(MagickSizeType) size-combined_length;
2139         if (length > 0)
2140           {
2141             unsigned char
2142               *info;
2143 
2144             if (length > GetBlobSize(image))
2145               {
2146                 layer_info=DestroyLayerInfo(layer_info,number_layers);
2147                 ThrowBinaryException(CorruptImageError,
2148                   "InsufficientImageDataInFile",image->filename);
2149               }
2150             layer_info[i].info=AcquireStringInfo((const size_t) length);
2151             info=GetStringInfoDatum(layer_info[i].info);
2152             (void) ReadBlob(image,(const size_t) length,info);
2153             ParseAdditionalInfo(&layer_info[i]);
2154           }
2155       }
2156   }
2157 
2158   for (i=0; i < number_layers; i++)
2159   {
2160     if ((layer_info[i].page.width == 0) || (layer_info[i].page.height == 0))
2161       {
2162         if (image->debug != MagickFalse)
2163           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2164             "      layer data is empty");
2165         if (layer_info[i].info != (StringInfo *) NULL)
2166           layer_info[i].info=DestroyStringInfo(layer_info[i].info);
2167         continue;
2168       }
2169 
2170     /*
2171       Allocate layered image.
2172     */
2173     layer_info[i].image=CloneImage(image,layer_info[i].page.width,
2174       layer_info[i].page.height,MagickFalse,exception);
2175     if (layer_info[i].image == (Image *) NULL)
2176       {
2177         layer_info=DestroyLayerInfo(layer_info,number_layers);
2178         if (image->debug != MagickFalse)
2179           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2180             "  allocation of image for layer %.20g failed",(double) i);
2181         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2182           image->filename);
2183       }
2184     for (j=0; j < (ssize_t) layer_info[i].channels; j++)
2185     {
2186       if (layer_info[i].channel_info[j].channel == AlphaPixelChannel)
2187         {
2188           layer_info[i].image->alpha_trait=BlendPixelTrait;
2189           break;
2190         }
2191     }
2192     if (layer_info[i].info != (StringInfo *) NULL)
2193       {
2194         (void) SetImageProfile(layer_info[i].image,"psd:additional-info",
2195           layer_info[i].info,exception);
2196         layer_info[i].info=DestroyStringInfo(layer_info[i].info);
2197       }
2198   }
2199   if (image_info->ping != MagickFalse)
2200     {
2201       AttachPSDLayers(image,layer_info,number_layers);
2202       return(MagickTrue);
2203     }
2204   status=MagickTrue;
2205   index=0;
2206   for (i=0; i < number_layers; i++)
2207   {
2208     if ((layer_info[i].image == (Image *) NULL) ||
2209         (PSDSkipImage(psd_info, image_info,++index) != MagickFalse))
2210       {
2211         for (j=0; j < (ssize_t) layer_info[i].channels; j++)
2212         {
2213           if (DiscardBlobBytes(image,(MagickSizeType)
2214               layer_info[i].channel_info[j].size) == MagickFalse)
2215             {
2216               layer_info=DestroyLayerInfo(layer_info,number_layers);
2217               ThrowBinaryException(CorruptImageError,
2218                 "UnexpectedEndOfFile",image->filename);
2219             }
2220         }
2221         continue;
2222       }
2223 
2224     if (image->debug != MagickFalse)
2225       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2226         "  reading data for layer %.20g",(double) i);
2227 
2228     status=ReadPSDLayer(image,image_info,psd_info,&layer_info[i],
2229       exception);
2230     if (status == MagickFalse)
2231       break;
2232 
2233     status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType) i,
2234       (MagickSizeType) number_layers);
2235     if (status == MagickFalse)
2236       break;
2237   }
2238 
2239   if (status != MagickFalse)
2240     AttachPSDLayers(image,layer_info,number_layers);
2241   else
2242     layer_info=DestroyLayerInfo(layer_info,number_layers);
2243 
2244   return(status);
2245 }
2246 
ReadPSDLayers(Image * image,const ImageInfo * image_info,const PSDInfo * psd_info,ExceptionInfo * exception)2247 ModuleExport MagickBooleanType ReadPSDLayers(Image *image,
2248   const ImageInfo *image_info,const PSDInfo *psd_info,ExceptionInfo *exception)
2249 {
2250   MagickBooleanType
2251     status;
2252 
2253   status=IsRightsAuthorized(CoderPolicyDomain,ReadPolicyRights,"PSD");
2254   if (status == MagickFalse)
2255     return(MagickTrue);
2256   return(ReadPSDLayersInternal(image,image_info,psd_info,MagickFalse,
2257     exception));
2258 }
2259 
ReadPSDMergedImage(const ImageInfo * image_info,Image * image,const PSDInfo * psd_info,ExceptionInfo * exception)2260 static MagickBooleanType ReadPSDMergedImage(const ImageInfo *image_info,
2261   Image *image,const PSDInfo *psd_info,ExceptionInfo *exception)
2262 {
2263   MagickOffsetType
2264     *sizes;
2265 
2266   MagickBooleanType
2267     status;
2268 
2269   PSDCompressionType
2270     compression;
2271 
2272   ssize_t
2273     i;
2274 
2275   if ((image_info->number_scenes != 0) && (image_info->scene != 0))
2276     return(MagickTrue);
2277   compression=(PSDCompressionType) ReadBlobMSBShort(image);
2278   image->compression=ConvertPSDCompression(compression);
2279 
2280   if (compression != Raw && compression != RLE)
2281     {
2282       (void) ThrowMagickException(exception,GetMagickModule(),
2283         TypeWarning,"CompressionNotSupported","'%.20g'",(double) compression);
2284       return(MagickFalse);
2285     }
2286 
2287   sizes=(MagickOffsetType *) NULL;
2288   if (compression == RLE)
2289     {
2290       sizes=ReadPSDRLESizes(image,psd_info,image->rows*psd_info->channels);
2291       if (sizes == (MagickOffsetType *) NULL)
2292         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2293           image->filename);
2294     }
2295 
2296   SetPsdMetaChannels(image,psd_info,psd_info->channels,exception);
2297   status=MagickTrue;
2298   for (i=0; i < (ssize_t) psd_info->channels; i++)
2299   {
2300     PixelChannel
2301       channel;
2302 
2303     status=GetPixelChannelFromPsdIndex(psd_info,i,&channel);
2304     if (status == MagickFalse)
2305       {
2306         (void) ThrowMagickException(exception,GetMagickModule(),
2307           CorruptImageError,"MaximumChannelsExceeded","'%.20g'",(double) i);
2308         break;
2309       }
2310 
2311     if (compression == RLE)
2312       status=ReadPSDChannelRLE(image,channel,sizes+(i*image->rows),exception);
2313     else
2314       status=ReadPSDChannelRaw(image,channel,exception);
2315 
2316     if (status != MagickFalse)
2317       status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType) i,
2318         psd_info->channels);
2319 
2320     if (status == MagickFalse)
2321       break;
2322   }
2323 
2324   if ((status != MagickFalse) && (image->colorspace == CMYKColorspace))
2325     status=NegateCMYK(image,exception);
2326 
2327   if (status != MagickFalse)
2328     status=CorrectPSDAlphaBlend(image_info,image,exception);
2329 
2330   sizes=(MagickOffsetType *) RelinquishMagickMemory(sizes);
2331 
2332   return(status);
2333 }
2334 
ReadPSDImage(const ImageInfo * image_info,ExceptionInfo * exception)2335 static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
2336 {
2337   Image
2338     *image;
2339 
2340   MagickBooleanType
2341     skip_layers;
2342 
2343   MagickOffsetType
2344     offset;
2345 
2346   MagickSizeType
2347     length;
2348 
2349   MagickBooleanType
2350     status;
2351 
2352   PSDInfo
2353     psd_info;
2354 
2355   ssize_t
2356     i;
2357 
2358   size_t
2359     image_list_length;
2360 
2361   ssize_t
2362     count;
2363 
2364   StringInfo
2365     *profile;
2366 
2367   /*
2368     Open image file.
2369   */
2370   assert(image_info != (const ImageInfo *) NULL);
2371   assert(image_info->signature == MagickCoreSignature);
2372   if (image_info->debug != MagickFalse)
2373     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2374       image_info->filename);
2375   assert(exception != (ExceptionInfo *) NULL);
2376   assert(exception->signature == MagickCoreSignature);
2377 
2378   image=AcquireImage(image_info,exception);
2379   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
2380   if (status == MagickFalse)
2381     {
2382       image=DestroyImageList(image);
2383       return((Image *) NULL);
2384     }
2385   /*
2386     Read image header.
2387   */
2388   image->endian=MSBEndian;
2389   count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
2390   psd_info.version=ReadBlobMSBShort(image);
2391   if ((count != 4) || (LocaleNCompare(psd_info.signature,"8BPS",4) != 0) ||
2392       ((psd_info.version != 1) && (psd_info.version != 2)))
2393     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2394   (void) ReadBlob(image,6,psd_info.reserved);
2395   psd_info.channels=ReadBlobMSBShort(image);
2396   if (psd_info.channels < 1)
2397     ThrowReaderException(CorruptImageError,"MissingImageChannel");
2398   if (psd_info.channels > MaxPSDChannels)
2399     ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
2400   psd_info.rows=ReadBlobMSBLong(image);
2401   psd_info.columns=ReadBlobMSBLong(image);
2402   if ((psd_info.version == 1) && ((psd_info.rows > 30000) ||
2403       (psd_info.columns > 30000)))
2404     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2405   psd_info.depth=ReadBlobMSBShort(image);
2406   if ((psd_info.depth != 1) && (psd_info.depth != 8) &&
2407       (psd_info.depth != 16) && (psd_info.depth != 32))
2408     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2409   psd_info.mode=ReadBlobMSBShort(image);
2410   if ((psd_info.mode == IndexedMode) && (psd_info.channels > 3))
2411     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2412   if (image->debug != MagickFalse)
2413     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2414       "  Image is %.20g x %.20g with channels=%.20g, depth=%.20g, mode=%s",
2415       (double) psd_info.columns,(double) psd_info.rows,(double)
2416       psd_info.channels,(double) psd_info.depth,ModeToString((PSDImageType)
2417       psd_info.mode));
2418   if (EOFBlob(image) != MagickFalse)
2419     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2420   /*
2421     Initialize image.
2422   */
2423   image->depth=psd_info.depth;
2424   image->columns=psd_info.columns;
2425   image->rows=psd_info.rows;
2426   status=SetImageExtent(image,image->columns,image->rows,exception);
2427   if (status == MagickFalse)
2428     return(DestroyImageList(image));
2429   status=ResetImagePixels(image,exception);
2430   if (status == MagickFalse)
2431     return(DestroyImageList(image));
2432   psd_info.min_channels=3;
2433   switch (psd_info.mode)
2434   {
2435     case LabMode:
2436     {
2437       (void) SetImageColorspace(image,LabColorspace,exception);
2438       break;
2439     }
2440     case CMYKMode:
2441     {
2442       psd_info.min_channels=4;
2443       (void) SetImageColorspace(image,CMYKColorspace,exception);
2444       break;
2445     }
2446     case BitmapMode:
2447     case GrayscaleMode:
2448     case DuotoneMode:
2449     {
2450       if (psd_info.depth != 32)
2451         {
2452           status=AcquireImageColormap(image,MagickMin((size_t)
2453             (psd_info.depth < 16 ? 256 : 65536), MaxColormapSize),exception);
2454           if (status == MagickFalse)
2455             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
2456           if (image->debug != MagickFalse)
2457             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2458               "  Image colormap allocated");
2459         }
2460       psd_info.min_channels=1;
2461       (void) SetImageColorspace(image,GRAYColorspace,exception);
2462       break;
2463     }
2464     case IndexedMode:
2465     {
2466       psd_info.min_channels=1;
2467       break;
2468     }
2469     case MultichannelMode:
2470     {
2471       if ((psd_info.channels > 0) && (psd_info.channels < 3))
2472         {
2473           psd_info.min_channels=psd_info.channels;
2474           (void) SetImageColorspace(image,GRAYColorspace,exception);
2475         }
2476       break;
2477     }
2478   }
2479   if (psd_info.channels < psd_info.min_channels)
2480     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2481   /*
2482     Read PSD raster colormap only present for indexed and duotone images.
2483   */
2484   length=ReadBlobMSBLong(image);
2485   if ((psd_info.mode == IndexedMode) && (length < 3))
2486     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2487   if (length != 0)
2488     {
2489       if (image->debug != MagickFalse)
2490         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2491           "  reading colormap");
2492       if ((psd_info.mode == DuotoneMode) || (psd_info.depth == 32))
2493         {
2494           /*
2495             Duotone image data;  the format of this data is undocumented.
2496             32 bits per pixel;  the colormap is ignored.
2497           */
2498           (void) SeekBlob(image,(const MagickOffsetType) length,SEEK_CUR);
2499         }
2500       else
2501         {
2502           size_t
2503             number_colors;
2504 
2505           /*
2506             Read PSD raster colormap.
2507           */
2508           number_colors=(size_t) length/3;
2509           if (number_colors > 65536)
2510             ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2511           if (AcquireImageColormap(image,number_colors,exception) == MagickFalse)
2512             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
2513           for (i=0; i < (ssize_t) image->colors; i++)
2514             image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(
2515               (unsigned char) ReadBlobByte(image));
2516           for (i=0; i < (ssize_t) image->colors; i++)
2517             image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(
2518               (unsigned char) ReadBlobByte(image));
2519           for (i=0; i < (ssize_t) image->colors; i++)
2520             image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(
2521               (unsigned char) ReadBlobByte(image));
2522           image->alpha_trait=UndefinedPixelTrait;
2523         }
2524     }
2525   if ((image->depth == 1) && (image->storage_class != PseudoClass))
2526     ThrowReaderException(CorruptImageError, "ImproperImageHeader");
2527   psd_info.has_merged_image=MagickTrue;
2528   profile=(StringInfo *) NULL;
2529   length=ReadBlobMSBLong(image);
2530   if (length != 0)
2531     {
2532       unsigned char
2533         *blocks;
2534 
2535       /*
2536         Image resources block.
2537       */
2538       if (image->debug != MagickFalse)
2539         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2540           "  reading image resource blocks - %.20g bytes",(double)
2541           ((MagickOffsetType) length));
2542       if (length > GetBlobSize(image))
2543         ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
2544       blocks=(unsigned char *) AcquireQuantumMemory((size_t) length,
2545         sizeof(*blocks));
2546       if (blocks == (unsigned char *) NULL)
2547         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
2548       count=ReadBlob(image,(size_t) length,blocks);
2549       if ((count != (ssize_t) length) || (length < 4) ||
2550           (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
2551         {
2552           blocks=(unsigned char *) RelinquishMagickMemory(blocks);
2553           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2554         }
2555       profile=ParseImageResourceBlocks(&psd_info,image,blocks,(size_t) length);
2556       blocks=(unsigned char *) RelinquishMagickMemory(blocks);
2557     }
2558   /*
2559     Layer and mask block.
2560   */
2561   length=GetPSDSize(&psd_info,image);
2562   if (length == 8)
2563     {
2564       length=ReadBlobMSBLong(image);
2565       length=ReadBlobMSBLong(image);
2566     }
2567   offset=TellBlob(image);
2568   skip_layers=MagickFalse;
2569   if ((image_info->number_scenes == 1) && (image_info->scene == 0) &&
2570       (psd_info.has_merged_image != MagickFalse))
2571     {
2572       if (image->debug != MagickFalse)
2573         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2574           "  read composite only");
2575       skip_layers=MagickTrue;
2576     }
2577   if (length == 0)
2578     {
2579       if (image->debug != MagickFalse)
2580         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2581           "  image has no layers");
2582     }
2583   else
2584     {
2585       if (ReadPSDLayersInternal(image,image_info,&psd_info,skip_layers,
2586             exception) != MagickTrue)
2587         {
2588           if (profile != (StringInfo *) NULL)
2589             profile=DestroyStringInfo(profile);
2590           (void) CloseBlob(image);
2591           image=DestroyImageList(image);
2592           return((Image *) NULL);
2593         }
2594 
2595       /*
2596          Skip the rest of the layer and mask information.
2597       */
2598       (void) SeekBlob(image,offset+length,SEEK_SET);
2599     }
2600   /*
2601     If we are only "pinging" the image, then we're done - so return.
2602   */
2603   if (EOFBlob(image) != MagickFalse)
2604     {
2605       if (profile != (StringInfo *) NULL)
2606         profile=DestroyStringInfo(profile);
2607       ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
2608     }
2609   if (image_info->ping != MagickFalse)
2610     {
2611       if (profile != (StringInfo *) NULL)
2612         profile=DestroyStringInfo(profile);
2613       (void) CloseBlob(image);
2614       return(GetFirstImageInList(image));
2615     }
2616   /*
2617     Read the precombined layer, present for PSD < 4 compatibility.
2618   */
2619   if (image->debug != MagickFalse)
2620     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2621       "  reading the precombined layer");
2622   image_list_length=GetImageListLength(image);
2623   if ((psd_info.has_merged_image != MagickFalse) || (image_list_length == 1))
2624     psd_info.has_merged_image=(MagickBooleanType) ReadPSDMergedImage(
2625       image_info,image,&psd_info,exception);
2626   if ((psd_info.has_merged_image == MagickFalse) && (image_list_length == 1) &&
2627       (length != 0))
2628     {
2629       (void) SeekBlob(image,offset,SEEK_SET);
2630       status=ReadPSDLayersInternal(image,image_info,&psd_info,MagickFalse,
2631         exception);
2632       if (status != MagickTrue)
2633         {
2634           if (profile != (StringInfo *) NULL)
2635             profile=DestroyStringInfo(profile);
2636           (void) CloseBlob(image);
2637           image=DestroyImageList(image);
2638           return((Image *) NULL);
2639         }
2640       image_list_length=GetImageListLength(image);
2641     }
2642   if (psd_info.has_merged_image == MagickFalse)
2643     {
2644       Image
2645         *merged;
2646 
2647       if (image_list_length == 1)
2648         {
2649           if (profile != (StringInfo *) NULL)
2650             profile=DestroyStringInfo(profile);
2651           ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
2652         }
2653       image->background_color.alpha=(MagickRealType) TransparentAlpha;
2654       image->background_color.alpha_trait=BlendPixelTrait;
2655       (void) SetImageBackgroundColor(image,exception);
2656       merged=MergeImageLayers(image,FlattenLayer,exception);
2657       if (merged == (Image *) NULL)
2658         {
2659           (void) CloseBlob(image);
2660           image=DestroyImageList(image);
2661           return((Image *) NULL);
2662         }
2663       ReplaceImageInList(&image,merged);
2664     }
2665   if (profile != (StringInfo *) NULL)
2666     {
2667       const char
2668         *option;
2669 
2670       Image
2671         *next;
2672 
2673       MagickBooleanType
2674         replicate_profile;
2675 
2676       option=GetImageOption(image_info,"psd:replicate-profile");
2677       replicate_profile=IsStringTrue(option);
2678       i=0;
2679       next=image;
2680       while (next != (Image *) NULL)
2681       {
2682         if (PSDSkipImage(&psd_info,image_info,i++) == MagickFalse)
2683           {
2684             (void) SetImageProfile(next,GetStringInfoName(profile),profile,
2685               exception);
2686             if (replicate_profile == MagickFalse)
2687               break;
2688           }
2689         next=next->next;
2690       }
2691       profile=DestroyStringInfo(profile);
2692     }
2693   (void) CloseBlob(image);
2694   return(GetFirstImageInList(image));
2695 }
2696 
2697 /*
2698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2699 %                                                                             %
2700 %                                                                             %
2701 %                                                                             %
2702 %   R e g i s t e r P S D I m a g e                                           %
2703 %                                                                             %
2704 %                                                                             %
2705 %                                                                             %
2706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2707 %
2708 %  RegisterPSDImage() adds properties for the PSD image format to
2709 %  the list of supported formats.  The properties include the image format
2710 %  tag, a method to read and/or write the format, whether the format
2711 %  supports the saving of more than one frame to the same file or blob,
2712 %  whether the format supports native in-memory I/O, and a brief
2713 %  description of the format.
2714 %
2715 %  The format of the RegisterPSDImage method is:
2716 %
2717 %      size_t RegisterPSDImage(void)
2718 %
2719 */
RegisterPSDImage(void)2720 ModuleExport size_t RegisterPSDImage(void)
2721 {
2722   MagickInfo
2723     *entry;
2724 
2725   entry=AcquireMagickInfo("PSD","PSB","Adobe Large Document Format");
2726   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
2727   entry->encoder=(EncodeImageHandler *) WritePSDImage;
2728   entry->magick=(IsImageFormatHandler *) IsPSD;
2729   entry->flags|=CoderDecoderSeekableStreamFlag;
2730   entry->flags|=CoderEncoderSeekableStreamFlag;
2731   (void) RegisterMagickInfo(entry);
2732   entry=AcquireMagickInfo("PSD","PSD","Adobe Photoshop bitmap");
2733   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
2734   entry->encoder=(EncodeImageHandler *) WritePSDImage;
2735   entry->magick=(IsImageFormatHandler *) IsPSD;
2736   entry->flags|=CoderDecoderSeekableStreamFlag;
2737   entry->flags|=CoderEncoderSeekableStreamFlag;
2738   (void) RegisterMagickInfo(entry);
2739   return(MagickImageCoderSignature);
2740 }
2741 
2742 /*
2743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2744 %                                                                             %
2745 %                                                                             %
2746 %                                                                             %
2747 %   U n r e g i s t e r P S D I m a g e                                       %
2748 %                                                                             %
2749 %                                                                             %
2750 %                                                                             %
2751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2752 %
2753 %  UnregisterPSDImage() removes format registrations made by the
2754 %  PSD module from the list of supported formats.
2755 %
2756 %  The format of the UnregisterPSDImage method is:
2757 %
2758 %      UnregisterPSDImage(void)
2759 %
2760 */
UnregisterPSDImage(void)2761 ModuleExport void UnregisterPSDImage(void)
2762 {
2763   (void) UnregisterMagickInfo("PSB");
2764   (void) UnregisterMagickInfo("PSD");
2765 }
2766 
2767 /*
2768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2769 %                                                                             %
2770 %                                                                             %
2771 %                                                                             %
2772 %   W r i t e P S D I m a g e                                                 %
2773 %                                                                             %
2774 %                                                                             %
2775 %                                                                             %
2776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2777 %
2778 %  WritePSDImage() writes an image in the Adobe Photoshop encoded image format.
2779 %
2780 %  The format of the WritePSDImage method is:
2781 %
2782 %      MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image,
2783 %        ExceptionInfo *exception)
2784 %
2785 %  A description of each parameter follows.
2786 %
2787 %    o image_info: the image info.
2788 %
2789 %    o image:  The image.
2790 %
2791 %    o exception: return any errors or warnings in this structure.
2792 %
2793 */
2794 
SetPSDOffset(const PSDInfo * psd_info,Image * image,const size_t offset)2795 static inline ssize_t SetPSDOffset(const PSDInfo *psd_info,Image *image,
2796   const size_t offset)
2797 {
2798   if (psd_info->version == 1)
2799     return(WriteBlobMSBShort(image,(unsigned short) offset));
2800   return(WriteBlobMSBLong(image,(unsigned int) offset));
2801 }
2802 
WritePSDOffset(const PSDInfo * psd_info,Image * image,const MagickSizeType size,const MagickOffsetType offset)2803 static inline ssize_t WritePSDOffset(const PSDInfo *psd_info,Image *image,
2804   const MagickSizeType size,const MagickOffsetType offset)
2805 {
2806   MagickOffsetType
2807     current_offset;
2808 
2809   ssize_t
2810     result;
2811 
2812   current_offset=TellBlob(image);
2813   (void) SeekBlob(image,offset,SEEK_SET);
2814   if (psd_info->version == 1)
2815     result=WriteBlobMSBShort(image,(unsigned short) size);
2816   else
2817     result=WriteBlobMSBLong(image,(unsigned int) size);
2818   (void) SeekBlob(image,current_offset,SEEK_SET);
2819   return(result);
2820 }
2821 
SetPSDSize(const PSDInfo * psd_info,Image * image,const MagickSizeType size)2822 static inline ssize_t SetPSDSize(const PSDInfo *psd_info,Image *image,
2823   const MagickSizeType size)
2824 {
2825   if (psd_info->version == 1)
2826     return(WriteBlobLong(image,(unsigned int) size));
2827   return(WriteBlobLongLong(image,size));
2828 }
2829 
WritePSDSize(const PSDInfo * psd_info,Image * image,const MagickSizeType size,const MagickOffsetType offset)2830 static inline ssize_t WritePSDSize(const PSDInfo *psd_info,Image *image,
2831   const MagickSizeType size,const MagickOffsetType offset)
2832 {
2833   MagickOffsetType
2834     current_offset;
2835 
2836   ssize_t
2837     result;
2838 
2839   current_offset=TellBlob(image);
2840   (void) SeekBlob(image,offset,SEEK_SET);
2841   result=SetPSDSize(psd_info,image,size);
2842   (void) SeekBlob(image,current_offset,SEEK_SET);
2843   return(result);
2844 }
2845 
PSDPackbitsEncodeImage(Image * image,const size_t length,const unsigned char * pixels,unsigned char * compact_pixels,ExceptionInfo * exception)2846 static size_t PSDPackbitsEncodeImage(Image *image,const size_t length,
2847   const unsigned char *pixels,unsigned char *compact_pixels,
2848   ExceptionInfo *exception)
2849 {
2850   int
2851     count;
2852 
2853   ssize_t
2854     i,
2855     j;
2856 
2857   unsigned char
2858     *q;
2859 
2860   unsigned char
2861     *packbits;
2862 
2863   /*
2864     Compress pixels with Packbits encoding.
2865   */
2866   assert(image != (Image *) NULL);
2867   assert(image->signature == MagickCoreSignature);
2868   if (image->debug != MagickFalse)
2869     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2870   assert(pixels != (unsigned char *) NULL);
2871   assert(compact_pixels != (unsigned char *) NULL);
2872   packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
2873   if (packbits == (unsigned char *) NULL)
2874     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2875       image->filename);
2876   q=compact_pixels;
2877   for (i=(ssize_t) length; i != 0; )
2878   {
2879     switch (i)
2880     {
2881       case 1:
2882       {
2883         i--;
2884         *q++=(unsigned char) 0;
2885         *q++=(*pixels);
2886         break;
2887       }
2888       case 2:
2889       {
2890         i-=2;
2891         *q++=(unsigned char) 1;
2892         *q++=(*pixels);
2893         *q++=pixels[1];
2894         break;
2895       }
2896       case 3:
2897       {
2898         i-=3;
2899         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
2900           {
2901             *q++=(unsigned char) ((256-3)+1);
2902             *q++=(*pixels);
2903             break;
2904           }
2905         *q++=(unsigned char) 2;
2906         *q++=(*pixels);
2907         *q++=pixels[1];
2908         *q++=pixels[2];
2909         break;
2910       }
2911       default:
2912       {
2913         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
2914           {
2915             /*
2916               Packed run.
2917             */
2918             count=3;
2919             while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
2920             {
2921               count++;
2922               if (count >= 127)
2923                 break;
2924             }
2925             i-=count;
2926             *q++=(unsigned char) ((256-count)+1);
2927             *q++=(*pixels);
2928             pixels+=count;
2929             break;
2930           }
2931         /*
2932           Literal run.
2933         */
2934         count=0;
2935         while ((*(pixels+count) != *(pixels+count+1)) ||
2936                (*(pixels+count+1) != *(pixels+count+2)))
2937         {
2938           packbits[count+1]=pixels[count];
2939           count++;
2940           if (((ssize_t) count >= (i-3)) || (count >= 127))
2941             break;
2942         }
2943         i-=count;
2944         *packbits=(unsigned char) (count-1);
2945         for (j=0; j <= (ssize_t) count; j++)
2946           *q++=packbits[j];
2947         pixels+=count;
2948         break;
2949       }
2950     }
2951   }
2952   *q++=(unsigned char) 128;  /* EOD marker */
2953   packbits=(unsigned char *) RelinquishMagickMemory(packbits);
2954   return((size_t) (q-compact_pixels));
2955 }
2956 
WriteCompressionStart(const PSDInfo * psd_info,Image * image,const Image * next_image,const CompressionType compression,const ssize_t channels)2957 static size_t WriteCompressionStart(const PSDInfo *psd_info,Image *image,
2958   const Image *next_image,const CompressionType compression,
2959   const ssize_t channels)
2960 {
2961   size_t
2962     length;
2963 
2964   ssize_t
2965     i,
2966     y;
2967 
2968   if (compression == RLECompression)
2969     {
2970       length=(size_t) WriteBlobShort(image,RLE);
2971       for (i=0; i < channels; i++)
2972         for (y=0; y < (ssize_t) next_image->rows; y++)
2973           length+=SetPSDOffset(psd_info,image,0);
2974     }
2975 #ifdef MAGICKCORE_ZLIB_DELEGATE
2976   else if (compression == ZipCompression)
2977     length=(size_t) WriteBlobShort(image,ZipWithoutPrediction);
2978 #endif
2979   else
2980     length=(size_t) WriteBlobShort(image,Raw);
2981   return(length);
2982 }
2983 
WritePSDChannel(const PSDInfo * psd_info,const ImageInfo * image_info,Image * image,Image * next_image,const QuantumType quantum_type,unsigned char * compact_pixels,MagickOffsetType size_offset,const MagickBooleanType separate,const CompressionType compression,ExceptionInfo * exception)2984 static size_t WritePSDChannel(const PSDInfo *psd_info,
2985   const ImageInfo *image_info,Image *image,Image *next_image,
2986   const QuantumType quantum_type, unsigned char *compact_pixels,
2987   MagickOffsetType size_offset,const MagickBooleanType separate,
2988   const CompressionType compression,ExceptionInfo *exception)
2989 {
2990   MagickBooleanType
2991     monochrome;
2992 
2993   QuantumInfo
2994     *quantum_info;
2995 
2996   const Quantum
2997     *p;
2998 
2999   ssize_t
3000     i;
3001 
3002   size_t
3003     count,
3004     length;
3005 
3006   ssize_t
3007     y;
3008 
3009   unsigned char
3010     *pixels;
3011 
3012 #ifdef MAGICKCORE_ZLIB_DELEGATE
3013 
3014   int
3015     flush,
3016     level;
3017 
3018   unsigned char
3019     *compressed_pixels;
3020 
3021   z_stream
3022     stream;
3023 
3024   compressed_pixels=(unsigned char *) NULL;
3025   flush=Z_NO_FLUSH;
3026 #endif
3027   count=0;
3028   if (separate != MagickFalse)
3029     {
3030       size_offset=TellBlob(image)+2;
3031       count+=WriteCompressionStart(psd_info,image,next_image,compression,1);
3032     }
3033   if (next_image->depth > 8)
3034     next_image->depth=16;
3035   monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
3036     MagickTrue : MagickFalse;
3037   quantum_info=AcquireQuantumInfo(image_info,next_image);
3038   if (quantum_info == (QuantumInfo *) NULL)
3039     return(0);
3040   pixels=(unsigned char *) GetQuantumPixels(quantum_info);
3041 #ifdef MAGICKCORE_ZLIB_DELEGATE
3042   if (compression == ZipCompression)
3043     {
3044       compressed_pixels=(unsigned char *) AcquireQuantumMemory(
3045         MagickMinBufferExtent,sizeof(*compressed_pixels));
3046       if (compressed_pixels == (unsigned char *) NULL)
3047         {
3048           quantum_info=DestroyQuantumInfo(quantum_info);
3049           return(0);
3050         }
3051       memset(&stream,0,sizeof(stream));
3052       stream.data_type=Z_BINARY;
3053       level=Z_DEFAULT_COMPRESSION;
3054       if ((image_info->quality > 0 && image_info->quality < 10))
3055         level=(int) image_info->quality;
3056       if (deflateInit(&stream,level) != Z_OK)
3057         {
3058           quantum_info=DestroyQuantumInfo(quantum_info);
3059           compressed_pixels=(unsigned char *) RelinquishMagickMemory(
3060             compressed_pixels);
3061           return(0);
3062         }
3063     }
3064 #endif
3065   for (y=0; y < (ssize_t) next_image->rows; y++)
3066   {
3067     p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception);
3068     if (p == (const Quantum *) NULL)
3069       break;
3070     length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info,
3071       quantum_type,pixels,exception);
3072     if (monochrome != MagickFalse)
3073       for (i=0; i < (ssize_t) length; i++)
3074         pixels[i]=(~pixels[i]);
3075     if (compression == RLECompression)
3076       {
3077         length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels,
3078           exception);
3079         count+=WriteBlob(image,length,compact_pixels);
3080         size_offset+=WritePSDOffset(psd_info,image,length,size_offset);
3081       }
3082 #ifdef MAGICKCORE_ZLIB_DELEGATE
3083     else if (compression == ZipCompression)
3084       {
3085         stream.avail_in=(uInt) length;
3086         stream.next_in=(Bytef *) pixels;
3087         if (y == (ssize_t) next_image->rows-1)
3088           flush=Z_FINISH;
3089         do {
3090             stream.avail_out=(uInt) MagickMinBufferExtent;
3091             stream.next_out=(Bytef *) compressed_pixels;
3092             if (deflate(&stream,flush) == Z_STREAM_ERROR)
3093               break;
3094             length=(size_t) MagickMinBufferExtent-stream.avail_out;
3095             if (length > 0)
3096               count+=WriteBlob(image,length,compressed_pixels);
3097         } while (stream.avail_out == 0);
3098       }
3099 #endif
3100     else
3101       count+=WriteBlob(image,length,pixels);
3102   }
3103 #ifdef MAGICKCORE_ZLIB_DELEGATE
3104   if (compression == ZipCompression)
3105     {
3106       (void) deflateEnd(&stream);
3107       compressed_pixels=(unsigned char *) RelinquishMagickMemory(
3108         compressed_pixels);
3109     }
3110 #endif
3111   quantum_info=DestroyQuantumInfo(quantum_info);
3112   return(count);
3113 }
3114 
AcquireCompactPixels(const Image * image,ExceptionInfo * exception)3115 static unsigned char *AcquireCompactPixels(const Image *image,
3116   ExceptionInfo *exception)
3117 {
3118   size_t
3119     packet_size;
3120 
3121   unsigned char
3122     *compact_pixels;
3123 
3124   packet_size=image->depth > 8UL ? 2UL : 1UL;
3125   compact_pixels=(unsigned char *) AcquireQuantumMemory((9*
3126     image->columns)+1,packet_size*sizeof(*compact_pixels));
3127   if (compact_pixels == (unsigned char *) NULL)
3128     {
3129       (void) ThrowMagickException(exception,GetMagickModule(),
3130         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
3131     }
3132   return(compact_pixels);
3133 }
3134 
WritePSDChannels(const PSDInfo * psd_info,const ImageInfo * image_info,Image * image,Image * next_image,MagickOffsetType size_offset,const MagickBooleanType separate,ExceptionInfo * exception)3135 static size_t WritePSDChannels(const PSDInfo *psd_info,
3136   const ImageInfo *image_info,Image *image,Image *next_image,
3137   MagickOffsetType size_offset,const MagickBooleanType separate,
3138   ExceptionInfo *exception)
3139 {
3140   CompressionType
3141     compression;
3142 
3143   Image
3144     *mask;
3145 
3146   MagickOffsetType
3147     rows_offset;
3148 
3149   size_t
3150     channels,
3151     count,
3152     length,
3153     offset_length;
3154 
3155   unsigned char
3156     *compact_pixels;
3157 
3158   count=0;
3159   offset_length=0;
3160   rows_offset=0;
3161   compact_pixels=(unsigned char *) NULL;
3162   compression=next_image->compression;
3163   if (image_info->compression != UndefinedCompression)
3164     compression=image_info->compression;
3165   if (compression == RLECompression)
3166     {
3167       compact_pixels=AcquireCompactPixels(next_image,exception);
3168       if (compact_pixels == (unsigned char *) NULL)
3169         return(0);
3170     }
3171   channels=1;
3172   if (separate == MagickFalse)
3173     {
3174       if ((next_image->storage_class != PseudoClass) ||
3175           (IsImageGray(next_image) != MagickFalse))
3176         {
3177           if (IsImageGray(next_image) == MagickFalse)
3178             channels=(size_t) (next_image->colorspace == CMYKColorspace ? 4 :
3179               3);
3180           if (next_image->alpha_trait != UndefinedPixelTrait)
3181             channels++;
3182         }
3183       rows_offset=TellBlob(image)+2;
3184       count+=WriteCompressionStart(psd_info,image,next_image,compression,
3185         (ssize_t) channels);
3186       offset_length=(next_image->rows*(psd_info->version == 1 ? 2 : 4));
3187     }
3188   size_offset+=2;
3189   if ((next_image->storage_class == PseudoClass) &&
3190       (IsImageGray(next_image) == MagickFalse))
3191     {
3192       length=WritePSDChannel(psd_info,image_info,image,next_image,
3193         IndexQuantum,compact_pixels,rows_offset,separate,compression,
3194         exception);
3195       if (separate != MagickFalse)
3196         size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
3197       else
3198         rows_offset+=offset_length;
3199       count+=length;
3200     }
3201   else
3202     {
3203       if (IsImageGray(next_image) != MagickFalse)
3204         {
3205           length=WritePSDChannel(psd_info,image_info,image,next_image,
3206             GrayQuantum,compact_pixels,rows_offset,separate,compression,
3207             exception);
3208           if (separate != MagickFalse)
3209             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
3210           else
3211             rows_offset+=offset_length;
3212           count+=length;
3213         }
3214       else
3215         {
3216           if (next_image->colorspace == CMYKColorspace)
3217             (void) NegateCMYK(next_image,exception);
3218 
3219           length=WritePSDChannel(psd_info,image_info,image,next_image,
3220             RedQuantum,compact_pixels,rows_offset,separate,compression,
3221             exception);
3222           if (separate != MagickFalse)
3223             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
3224           else
3225             rows_offset+=offset_length;
3226           count+=length;
3227 
3228           length=WritePSDChannel(psd_info,image_info,image,next_image,
3229             GreenQuantum,compact_pixels,rows_offset,separate,compression,
3230             exception);
3231           if (separate != MagickFalse)
3232             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
3233           else
3234             rows_offset+=offset_length;
3235           count+=length;
3236 
3237           length=WritePSDChannel(psd_info,image_info,image,next_image,
3238             BlueQuantum,compact_pixels,rows_offset,separate,compression,
3239             exception);
3240           if (separate != MagickFalse)
3241             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
3242           else
3243             rows_offset+=offset_length;
3244           count+=length;
3245 
3246           if (next_image->colorspace == CMYKColorspace)
3247             {
3248               length=WritePSDChannel(psd_info,image_info,image,next_image,
3249                 BlackQuantum,compact_pixels,rows_offset,separate,compression,
3250                 exception);
3251               if (separate != MagickFalse)
3252                 size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
3253               else
3254                 rows_offset+=offset_length;
3255               count+=length;
3256             }
3257         }
3258       if (next_image->alpha_trait != UndefinedPixelTrait)
3259         {
3260           length=WritePSDChannel(psd_info,image_info,image,next_image,
3261             AlphaQuantum,compact_pixels,rows_offset,separate,compression,
3262             exception);
3263           if (separate != MagickFalse)
3264             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
3265           else
3266             rows_offset+=offset_length;
3267           count+=length;
3268         }
3269     }
3270   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
3271   if (next_image->colorspace == CMYKColorspace)
3272     (void) NegateCMYK(next_image,exception);
3273   if (separate != MagickFalse)
3274     {
3275       const char
3276         *property;
3277 
3278       property=GetImageArtifact(next_image,"psd:opacity-mask");
3279       if (property != (const char *) NULL)
3280         {
3281           mask=(Image *) GetImageRegistry(ImageRegistryType,property,
3282             exception);
3283           if (mask != (Image *) NULL)
3284             {
3285               if (compression == RLECompression)
3286                 {
3287                   compact_pixels=AcquireCompactPixels(mask,exception);
3288                   if (compact_pixels == (unsigned char *) NULL)
3289                     return(0);
3290                 }
3291               length=WritePSDChannel(psd_info,image_info,image,mask,
3292                 RedQuantum,compact_pixels,rows_offset,MagickTrue,compression,
3293                 exception);
3294               (void) WritePSDSize(psd_info,image,length,size_offset);
3295               count+=length;
3296               compact_pixels=(unsigned char *) RelinquishMagickMemory(
3297                 compact_pixels);
3298             }
3299         }
3300     }
3301   return(count);
3302 }
3303 
WritePascalString(Image * image,const char * value,size_t padding)3304 static size_t WritePascalString(Image *image,const char *value,size_t padding)
3305 {
3306   size_t
3307     count,
3308     length;
3309 
3310   ssize_t
3311     i;
3312 
3313   /*
3314     Max length is 255.
3315   */
3316   count=0;
3317   length=(strlen(value) > 255UL ) ? 255UL : strlen(value);
3318   if (length ==  0)
3319     count+=WriteBlobByte(image,0);
3320   else
3321     {
3322       count+=WriteBlobByte(image,(unsigned char) length);
3323       count+=WriteBlob(image,length,(const unsigned char *) value);
3324     }
3325   length++;
3326   if ((length % padding) == 0)
3327     return(count);
3328   for (i=0; i < (ssize_t) (padding-(length % padding)); i++)
3329     count+=WriteBlobByte(image,0);
3330   return(count);
3331 }
3332 
WriteResolutionResourceBlock(Image * image)3333 static void WriteResolutionResourceBlock(Image *image)
3334 {
3335   double
3336     x_resolution,
3337     y_resolution;
3338 
3339   unsigned short
3340     units;
3341 
3342   if (image->units == PixelsPerCentimeterResolution)
3343     {
3344       x_resolution=2.54*65536.0*image->resolution.x+0.5;
3345       y_resolution=2.54*65536.0*image->resolution.y+0.5;
3346       units=2;
3347     }
3348   else
3349     {
3350       x_resolution=65536.0*image->resolution.x+0.5;
3351       y_resolution=65536.0*image->resolution.y+0.5;
3352       units=1;
3353     }
3354   (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
3355   (void) WriteBlobMSBShort(image,0x03ED);
3356   (void) WriteBlobMSBShort(image,0);
3357   (void) WriteBlobMSBLong(image,16); /* resource size */
3358   (void) WriteBlobMSBLong(image,(unsigned int) (x_resolution+0.5));
3359   (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
3360   (void) WriteBlobMSBShort(image,units); /* width unit */
3361   (void) WriteBlobMSBLong(image,(unsigned int) (y_resolution+0.5));
3362   (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
3363   (void) WriteBlobMSBShort(image,units); /* height unit */
3364 }
3365 
WriteChannelSize(const PSDInfo * psd_info,Image * image,const signed short channel)3366 static inline size_t WriteChannelSize(const PSDInfo *psd_info,Image *image,
3367   const signed short channel)
3368 {
3369   size_t
3370     count;
3371 
3372   count=(size_t) WriteBlobShort(image,(const unsigned short) channel);
3373   count+=SetPSDSize(psd_info,image,0);
3374   return(count);
3375 }
3376 
RemoveICCProfileFromResourceBlock(StringInfo * bim_profile)3377 static void RemoveICCProfileFromResourceBlock(StringInfo *bim_profile)
3378 {
3379   const unsigned char
3380     *p;
3381 
3382   size_t
3383     length;
3384 
3385   unsigned char
3386     *datum;
3387 
3388   unsigned int
3389     count,
3390     long_sans;
3391 
3392   unsigned short
3393     id,
3394     short_sans;
3395 
3396   length=GetStringInfoLength(bim_profile);
3397   if (length < 16)
3398     return;
3399   datum=GetStringInfoDatum(bim_profile);
3400   for (p=datum; (p >= datum) && (p < (datum+length-16)); )
3401   {
3402     unsigned char
3403       *q;
3404 
3405     q=(unsigned char *) p;
3406     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
3407       break;
3408     p=PushLongPixel(MSBEndian,p,&long_sans);
3409     p=PushShortPixel(MSBEndian,p,&id);
3410     p=PushShortPixel(MSBEndian,p,&short_sans);
3411     p=PushLongPixel(MSBEndian,p,&count);
3412     if (id == 0x0000040f)
3413       {
3414         ssize_t
3415           quantum;
3416 
3417         quantum=PSDQuantum(count)+12;
3418         if ((quantum >= 12) && (quantum < (ssize_t) length))
3419           {
3420             if ((q+quantum < (datum+length-16)))
3421               (void) memmove(q,q+quantum,length-quantum-(q-datum));
3422             SetStringInfoLength(bim_profile,length-quantum);
3423           }
3424         break;
3425       }
3426     p+=count;
3427     if ((count & 0x01) != 0)
3428       p++;
3429   }
3430 }
3431 
RemoveResolutionFromResourceBlock(StringInfo * bim_profile)3432 static void RemoveResolutionFromResourceBlock(StringInfo *bim_profile)
3433 {
3434   const unsigned char
3435     *p;
3436 
3437   size_t
3438     length;
3439 
3440   unsigned char
3441     *datum;
3442 
3443   unsigned int
3444     count,
3445     long_sans;
3446 
3447   unsigned short
3448     id,
3449     short_sans;
3450 
3451   length=GetStringInfoLength(bim_profile);
3452   if (length < 16)
3453     return;
3454   datum=GetStringInfoDatum(bim_profile);
3455   for (p=datum; (p >= datum) && (p < (datum+length-16)); )
3456   {
3457     unsigned char
3458       *q;
3459 
3460     ssize_t
3461       cnt;
3462 
3463     q=(unsigned char *) p;
3464     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
3465       return;
3466     p=PushLongPixel(MSBEndian,p,&long_sans);
3467     p=PushShortPixel(MSBEndian,p,&id);
3468     p=PushShortPixel(MSBEndian,p,&short_sans);
3469     p=PushLongPixel(MSBEndian,p,&count);
3470     cnt=PSDQuantum(count);
3471     if (cnt < 0)
3472       return;
3473     if ((id == 0x000003ed) && (cnt < (ssize_t) (length-12)) &&
3474         ((ssize_t) length-(cnt+12)-(q-datum)) > 0)
3475       {
3476         (void) memmove(q,q+cnt+12,length-(cnt+12)-(q-datum));
3477         SetStringInfoLength(bim_profile,length-(cnt+12));
3478         break;
3479       }
3480     p+=count;
3481     if ((count & 0x01) != 0)
3482       p++;
3483   }
3484 }
3485 
GetAdditionalInformation(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)3486 static const StringInfo *GetAdditionalInformation(const ImageInfo *image_info,
3487   Image *image,ExceptionInfo *exception)
3488 {
3489 #define PSDKeySize 5
3490 #define PSDAllowedLength 36
3491 
3492   char
3493     key[PSDKeySize];
3494 
3495   /* Whitelist of keys from: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ */
3496   const char
3497     allowed[PSDAllowedLength][PSDKeySize] = {
3498       "blnc", "blwh", "brit", "brst", "clbl", "clrL", "curv", "expA", "FMsk",
3499       "GdFl", "grdm", "hue ", "hue2", "infx", "knko", "lclr", "levl", "lnsr",
3500       "lfx2", "luni", "lrFX", "lspf", "lyid", "lyvr", "mixr", "nvrt", "phfl",
3501       "post", "PtFl", "selc", "shpa", "sn2P", "SoCo", "thrs", "tsly", "vibA"
3502     },
3503     *option;
3504 
3505   const StringInfo
3506     *info;
3507 
3508   MagickBooleanType
3509     found;
3510 
3511   size_t
3512     i;
3513 
3514   size_t
3515     remaining_length,
3516     length;
3517 
3518   StringInfo
3519     *profile;
3520 
3521   unsigned char
3522     *p;
3523 
3524   unsigned int
3525     size;
3526 
3527   info=GetImageProfile(image,"psd:additional-info");
3528   if (info == (const StringInfo *) NULL)
3529     return((const StringInfo *) NULL);
3530   option=GetImageOption(image_info,"psd:additional-info");
3531   if (LocaleCompare(option,"all") == 0)
3532     return(info);
3533   if (LocaleCompare(option,"selective") != 0)
3534     {
3535       profile=RemoveImageProfile(image,"psd:additional-info");
3536       return(DestroyStringInfo(profile));
3537     }
3538   length=GetStringInfoLength(info);
3539   p=GetStringInfoDatum(info);
3540   remaining_length=length;
3541   length=0;
3542   while (remaining_length >= 12)
3543   {
3544     /* skip over signature */
3545     p+=4;
3546     key[0]=(char) (*p++);
3547     key[1]=(char) (*p++);
3548     key[2]=(char) (*p++);
3549     key[3]=(char) (*p++);
3550     key[4]='\0';
3551     size=(unsigned int) (*p++) << 24;
3552     size|=(unsigned int) (*p++) << 16;
3553     size|=(unsigned int) (*p++) << 8;
3554     size|=(unsigned int) (*p++);
3555     size=size & 0xffffffff;
3556     remaining_length-=12;
3557     if ((size_t) size > remaining_length)
3558       return((const StringInfo *) NULL);
3559     found=MagickFalse;
3560     for (i=0; i < PSDAllowedLength; i++)
3561     {
3562       if (LocaleNCompare(key,allowed[i],PSDKeySize) != 0)
3563         continue;
3564 
3565       found=MagickTrue;
3566       break;
3567     }
3568     remaining_length-=(size_t) size;
3569     if (found == MagickFalse)
3570       {
3571         if (remaining_length > 0)
3572           p=(unsigned char *) memmove(p-12,p+size,remaining_length);
3573         continue;
3574       }
3575     length+=(size_t) size+12;
3576     p+=size;
3577   }
3578   profile=RemoveImageProfile(image,"psd:additional-info");
3579   if (length == 0)
3580     return(DestroyStringInfo(profile));
3581   SetStringInfoLength(profile,(const size_t) length);
3582   (void) SetImageProfile(image,"psd:additional-info",info,exception);
3583   return(profile);
3584 }
3585 
WritePSDLayersInternal(Image * image,const ImageInfo * image_info,const PSDInfo * psd_info,size_t * layers_size,ExceptionInfo * exception)3586 static MagickBooleanType WritePSDLayersInternal(Image *image,
3587   const ImageInfo *image_info,const PSDInfo *psd_info,size_t *layers_size,
3588   ExceptionInfo *exception)
3589 {
3590   char
3591     layer_name[MagickPathExtent];
3592 
3593   const char
3594     *property;
3595 
3596   const StringInfo
3597     *info;
3598 
3599   Image
3600     *base_image,
3601     *next_image;
3602 
3603   MagickBooleanType
3604     status;
3605 
3606   MagickOffsetType
3607     *layer_size_offsets,
3608     size_offset;
3609 
3610   ssize_t
3611     i;
3612 
3613   size_t
3614     layer_count,
3615     layer_index,
3616     length,
3617     name_length,
3618     rounded_size,
3619     size;
3620 
3621   status=MagickTrue;
3622   base_image=GetNextImageInList(image);
3623   if (base_image == (Image *) NULL)
3624     base_image=image;
3625   size=0;
3626   size_offset=TellBlob(image);
3627   (void) SetPSDSize(psd_info,image,0);
3628   layer_count=0;
3629   for (next_image=base_image; next_image != NULL; )
3630   {
3631     layer_count++;
3632     next_image=GetNextImageInList(next_image);
3633   }
3634   if (image->alpha_trait != UndefinedPixelTrait)
3635     size+=WriteBlobShort(image,-(unsigned short) layer_count);
3636   else
3637     size+=WriteBlobShort(image,(unsigned short) layer_count);
3638   layer_size_offsets=(MagickOffsetType *) AcquireQuantumMemory(
3639     (size_t) layer_count,sizeof(MagickOffsetType));
3640   if (layer_size_offsets == (MagickOffsetType *) NULL)
3641     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3642   layer_index=0;
3643   for (next_image=base_image; next_image != NULL; )
3644   {
3645     Image
3646       *mask;
3647 
3648     unsigned char
3649       default_color;
3650 
3651     unsigned short
3652       channels,
3653       total_channels;
3654 
3655     mask=(Image *) NULL;
3656     property=GetImageArtifact(next_image,"psd:opacity-mask");
3657     default_color=0;
3658     if (property != (const char *) NULL)
3659       {
3660         mask=(Image *) GetImageRegistry(ImageRegistryType,property,exception);
3661         default_color=(unsigned char) (strlen(property) == 9 ? 255 : 0);
3662       }
3663     size+=WriteBlobSignedLong(image,(signed int) next_image->page.y);
3664     size+=WriteBlobSignedLong(image,(signed int) next_image->page.x);
3665     size+=WriteBlobSignedLong(image,(signed int) (next_image->page.y+
3666       next_image->rows));
3667     size+=WriteBlobSignedLong(image,(signed int) (next_image->page.x+
3668       next_image->columns));
3669     channels=1;
3670     if ((next_image->storage_class != PseudoClass) &&
3671         (IsImageGray(next_image) == MagickFalse))
3672       channels=(unsigned short) (next_image->colorspace == CMYKColorspace ? 4 :
3673         3);
3674     total_channels=channels;
3675     if (next_image->alpha_trait != UndefinedPixelTrait)
3676       total_channels++;
3677     if (mask != (Image *) NULL)
3678       total_channels++;
3679     size+=WriteBlobShort(image,total_channels);
3680     layer_size_offsets[layer_index++]=TellBlob(image);
3681     for (i=0; i < (ssize_t) channels; i++)
3682       size+=WriteChannelSize(psd_info,image,(signed short) i);
3683     if (next_image->alpha_trait != UndefinedPixelTrait)
3684       size+=WriteChannelSize(psd_info,image,-1);
3685     if (mask != (Image *) NULL)
3686       size+=WriteChannelSize(psd_info,image,-2);
3687     size+=WriteBlobString(image,image->endian == LSBEndian ? "MIB8" :"8BIM");
3688     size+=WriteBlobString(image,CompositeOperatorToPSDBlendMode(next_image));
3689     property=GetImageArtifact(next_image,"psd:layer.opacity");
3690     if (property != (const char *) NULL)
3691       {
3692         Quantum
3693           opacity;
3694 
3695         opacity=(Quantum) StringToInteger(property);
3696         size+=WriteBlobByte(image,ScaleQuantumToChar(opacity));
3697         (void) ApplyPSDLayerOpacity(next_image,opacity,MagickTrue,exception);
3698       }
3699     else
3700       size+=WriteBlobByte(image,255);
3701     size+=WriteBlobByte(image,0);
3702     size+=WriteBlobByte(image,(const unsigned char)
3703       (next_image->compose == NoCompositeOp ? 1 << 0x02 : 1)); /* layer properties - visible, etc. */
3704     size+=WriteBlobByte(image,0);
3705     info=GetAdditionalInformation(image_info,next_image,exception);
3706     property=(const char *) GetImageProperty(next_image,"label",exception);
3707     if (property == (const char *) NULL)
3708       {
3709         (void) FormatLocaleString(layer_name,MagickPathExtent,"L%.20g",
3710           (double) layer_index);
3711         property=layer_name;
3712       }
3713     name_length=strlen(property)+1;
3714     if ((name_length % 4) != 0)
3715       name_length+=(4-(name_length % 4));
3716     if (info != (const StringInfo *) NULL)
3717       name_length+=GetStringInfoLength(info);
3718     name_length+=8;
3719     if (mask != (Image *) NULL)
3720       name_length+=20;
3721     size+=WriteBlobLong(image,(unsigned int) name_length);
3722     if (mask == (Image *) NULL)
3723       size+=WriteBlobLong(image,0);
3724     else
3725       {
3726         if (mask->compose != NoCompositeOp)
3727           (void) ApplyPSDOpacityMask(next_image,mask,ScaleCharToQuantum(
3728             default_color),MagickTrue,exception);
3729         mask->page.y+=image->page.y;
3730         mask->page.x+=image->page.x;
3731         size+=WriteBlobLong(image,20);
3732         size+=WriteBlobSignedLong(image,(const signed int) mask->page.y);
3733         size+=WriteBlobSignedLong(image,(const signed int) mask->page.x);
3734         size+=WriteBlobSignedLong(image,(const signed int) (mask->rows+
3735           mask->page.y));
3736         size+=WriteBlobSignedLong(image,(const signed int) (mask->columns+
3737           mask->page.x));
3738         size+=WriteBlobByte(image,default_color);
3739         size+=WriteBlobByte(image,(const unsigned char)
3740           (mask->compose == NoCompositeOp ? 2 : 0));
3741         size+=WriteBlobMSBShort(image,0);
3742       }
3743     size+=WriteBlobLong(image,0);
3744     size+=WritePascalString(image,property,4);
3745     if (info != (const StringInfo *) NULL)
3746       size+=WriteBlob(image,GetStringInfoLength(info),
3747         GetStringInfoDatum(info));
3748     next_image=GetNextImageInList(next_image);
3749   }
3750   /*
3751     Now the image data!
3752   */
3753   next_image=base_image;
3754   layer_index=0;
3755   while (next_image != NULL)
3756   {
3757     length=WritePSDChannels(psd_info,image_info,image,next_image,
3758       layer_size_offsets[layer_index++],MagickTrue,exception);
3759     if (length == 0)
3760       {
3761         status=MagickFalse;
3762         break;
3763       }
3764     size+=length;
3765     next_image=GetNextImageInList(next_image);
3766   }
3767   /*
3768     Write the total size
3769   */
3770   if (layers_size != (size_t*) NULL)
3771     *layers_size=size;
3772   if ((size/2) != ((size+1)/2))
3773     rounded_size=size+1;
3774   else
3775     rounded_size=size;
3776   (void) WritePSDSize(psd_info,image,rounded_size,size_offset);
3777   layer_size_offsets=(MagickOffsetType *) RelinquishMagickMemory(
3778     layer_size_offsets);
3779   /*
3780     Remove the opacity mask from the registry
3781   */
3782   next_image=base_image;
3783   while (next_image != (Image *) NULL)
3784   {
3785     property=GetImageArtifact(next_image,"psd:opacity-mask");
3786     if (property != (const char *) NULL)
3787       (void) DeleteImageRegistry(property);
3788     next_image=GetNextImageInList(next_image);
3789   }
3790   return(status);
3791 }
3792 
WritePSDLayers(Image * image,const ImageInfo * image_info,const PSDInfo * psd_info,ExceptionInfo * exception)3793 ModuleExport MagickBooleanType WritePSDLayers(Image * image,
3794   const ImageInfo *image_info,const PSDInfo *psd_info,ExceptionInfo *exception)
3795 {
3796   MagickBooleanType
3797     status;
3798 
3799   status=IsRightsAuthorized(CoderPolicyDomain,WritePolicyRights,"PSD");
3800   if (status == MagickFalse)
3801     return(MagickTrue);
3802   return WritePSDLayersInternal(image,image_info,psd_info,(size_t*) NULL,
3803     exception);
3804 }
3805 
WritePSDImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)3806 static MagickBooleanType WritePSDImage(const ImageInfo *image_info,
3807   Image *image,ExceptionInfo *exception)
3808 {
3809   const StringInfo
3810     *icc_profile;
3811 
3812   MagickBooleanType
3813     status;
3814 
3815   PSDInfo
3816     psd_info;
3817 
3818   ssize_t
3819     i;
3820 
3821   size_t
3822     length,
3823     num_channels;
3824 
3825   StringInfo
3826     *bim_profile;
3827 
3828   /*
3829     Open image file.
3830   */
3831   assert(image_info != (const ImageInfo *) NULL);
3832   assert(image_info->signature == MagickCoreSignature);
3833   assert(image != (Image *) NULL);
3834   assert(image->signature == MagickCoreSignature);
3835   if (image->debug != MagickFalse)
3836     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3837   assert(exception != (ExceptionInfo *) NULL);
3838   assert(exception->signature == MagickCoreSignature);
3839   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
3840   if (status == MagickFalse)
3841     return(status);
3842   psd_info.version=1;
3843   if ((LocaleCompare(image_info->magick,"PSB") == 0) ||
3844       (image->columns > 30000) || (image->rows > 30000))
3845     psd_info.version=2;
3846   (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
3847   (void) WriteBlobMSBShort(image,psd_info.version);  /* version */
3848   for (i=1; i <= 6; i++)
3849     (void) WriteBlobByte(image, 0);  /* 6 bytes of reserved */
3850   if ((GetImageProfile(image,"icc") == (StringInfo *) NULL) &&
3851       (SetImageGray(image,exception) != MagickFalse))
3852     num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
3853   else
3854     if ((image_info->type != TrueColorType) &&
3855         (image_info->type != TrueColorAlphaType) &&
3856         (image->storage_class == PseudoClass))
3857       num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
3858     else
3859       {
3860         if (image->storage_class == PseudoClass)
3861           (void) SetImageStorageClass(image,DirectClass,exception);
3862         if (image->colorspace != CMYKColorspace)
3863           num_channels=(image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL);
3864         else
3865           num_channels=(image->alpha_trait != UndefinedPixelTrait ? 5UL : 4UL);
3866       }
3867   (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
3868   (void) WriteBlobMSBLong(image,(unsigned int) image->rows);
3869   (void) WriteBlobMSBLong(image,(unsigned int) image->columns);
3870   if (IsImageGray(image) != MagickFalse)
3871     {
3872       MagickBooleanType
3873         monochrome;
3874 
3875       /*
3876         Write depth & mode.
3877       */
3878       monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
3879         MagickTrue : MagickFalse;
3880       (void) WriteBlobMSBShort(image,(unsigned short)
3881         (monochrome != MagickFalse ? 1 : image->depth > 8 ? 16 : 8));
3882       (void) WriteBlobMSBShort(image,(unsigned short)
3883         (monochrome != MagickFalse ? BitmapMode : GrayscaleMode));
3884     }
3885   else
3886     {
3887       (void) WriteBlobMSBShort(image,(unsigned short) (image->storage_class ==
3888         PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
3889 
3890       if (((image_info->colorspace != UndefinedColorspace) ||
3891            (image->colorspace != CMYKColorspace)) &&
3892           (image_info->colorspace != CMYKColorspace))
3893         {
3894           (void) TransformImageColorspace(image,sRGBColorspace,exception);
3895           (void) WriteBlobMSBShort(image,(unsigned short)
3896             (image->storage_class == PseudoClass ? IndexedMode : RGBMode));
3897         }
3898       else
3899         {
3900           if (image->colorspace != CMYKColorspace)
3901             (void) TransformImageColorspace(image,CMYKColorspace,exception);
3902           (void) WriteBlobMSBShort(image,CMYKMode);
3903         }
3904     }
3905   if ((IsImageGray(image) != MagickFalse) ||
3906       (image->storage_class == DirectClass) || (image->colors > 256))
3907     (void) WriteBlobMSBLong(image,0);
3908   else
3909     {
3910       /*
3911         Write PSD raster colormap.
3912       */
3913       (void) WriteBlobMSBLong(image,768);
3914       for (i=0; i < (ssize_t) image->colors; i++)
3915         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
3916           image->colormap[i].red)));
3917       for ( ; i < 256; i++)
3918         (void) WriteBlobByte(image,0);
3919       for (i=0; i < (ssize_t) image->colors; i++)
3920         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
3921           image->colormap[i].green)));
3922       for ( ; i < 256; i++)
3923         (void) WriteBlobByte(image,0);
3924       for (i=0; i < (ssize_t) image->colors; i++)
3925         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
3926           image->colormap[i].blue)));
3927       for ( ; i < 256; i++)
3928         (void) WriteBlobByte(image,0);
3929     }
3930   /*
3931     Image resource block.
3932   */
3933   length=28; /* 0x03EB */
3934   bim_profile=(StringInfo *) GetImageProfile(image,"8bim");
3935   icc_profile=GetImageProfile(image,"icc");
3936   if (bim_profile != (StringInfo *) NULL)
3937     {
3938       bim_profile=CloneStringInfo(bim_profile);
3939       if (icc_profile != (StringInfo *) NULL)
3940         RemoveICCProfileFromResourceBlock(bim_profile);
3941       RemoveResolutionFromResourceBlock(bim_profile);
3942       length+=PSDQuantum(GetStringInfoLength(bim_profile));
3943     }
3944   if (icc_profile != (const StringInfo *) NULL)
3945     length+=PSDQuantum(GetStringInfoLength(icc_profile))+12;
3946   (void) WriteBlobMSBLong(image,(unsigned int) length);
3947   WriteResolutionResourceBlock(image);
3948   if (bim_profile != (StringInfo *) NULL)
3949     {
3950       (void) WriteBlob(image,GetStringInfoLength(bim_profile),
3951         GetStringInfoDatum(bim_profile));
3952       bim_profile=DestroyStringInfo(bim_profile);
3953     }
3954   if (icc_profile != (StringInfo *) NULL)
3955     {
3956       (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
3957       (void) WriteBlobMSBShort(image,0x0000040F);
3958       (void) WriteBlobMSBShort(image,0);
3959       (void) WriteBlobMSBLong(image,(unsigned int) GetStringInfoLength(
3960         icc_profile));
3961       (void) WriteBlob(image,GetStringInfoLength(icc_profile),
3962         GetStringInfoDatum(icc_profile));
3963       if ((ssize_t) GetStringInfoLength(icc_profile) != PSDQuantum(GetStringInfoLength(icc_profile)))
3964         (void) WriteBlobByte(image,0);
3965     }
3966   if (status != MagickFalse)
3967     {
3968       const char
3969         *option;
3970 
3971       CompressionType
3972         compression;
3973 
3974       MagickOffsetType
3975         size_offset;
3976 
3977       size_t
3978         size;
3979 
3980       size_offset=TellBlob(image);
3981       (void) SetPSDSize(&psd_info,image,0);
3982       option=GetImageOption(image_info,"psd:write-layers");
3983       if (IsStringFalse(option) != MagickTrue)
3984         {
3985           status=WritePSDLayersInternal(image,image_info,&psd_info,&size,
3986             exception);
3987           (void) WritePSDSize(&psd_info,image,size+
3988             (psd_info.version == 1 ? 8 : 12),size_offset);
3989           (void) WriteBlobMSBLong(image,0);  /* user mask data */
3990         }
3991       /*
3992         Write composite image.
3993       */
3994       compression=image->compression;
3995       if (image_info->compression != UndefinedCompression)
3996         image->compression=image_info->compression;
3997       if (image->compression == ZipCompression)
3998         image->compression=RLECompression;
3999       if (WritePSDChannels(&psd_info,image_info,image,image,0,MagickFalse,
4000           exception) == 0)
4001         status=MagickFalse;
4002       image->compression=compression;
4003     }
4004   (void) CloseBlob(image);
4005   return(status);
4006 }
4007