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