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