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