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