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