]> granicus.if.org Git - imagemagick/blob - coders/psd.c
(no commit message)
[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 %                                John Cristy                                  %
17 %                              Leonard Rosenthol                              %
18 %                                 July 1992                                   %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    http://www.imagemagick.org/script/license.php                            %
28 %                                                                             %
29 %  Unless required by applicable law or agreed to in writing, software        %
30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32 %  See the License for the specific language governing permissions and        %
33 %  limitations under the License.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 */
39 \f
40 /*
41   Include declarations.
42 */
43 #include "magick/studio.h"
44 #include "magick/artifact.h"
45 #include "magick/blob.h"
46 #include "magick/blob-private.h"
47 #include "magick/cache.h"
48 #include "magick/colorspace.h"
49 #include "magick/constitute.h"
50 #include "magick/enhance.h"
51 #include "magick/exception.h"
52 #include "magick/exception-private.h"
53 #include "magick/image.h"
54 #include "magick/image-private.h"
55 #include "magick/list.h"
56 #include "magick/log.h"
57 #include "magick/magick.h"
58 #include "magick/memory_.h"
59 #include "magick/module.h"
60 #include "magick/monitor-private.h"
61 #include "magick/profile.h"
62 #include "magick/property.h"
63 #include "magick/quantum-private.h"
64 #include "magick/static.h"
65 #include "magick/string_.h"
66 \f
67 /*
68   Define declaractions.
69 */
70 #define MaxPSDChannels  56
71 \f
72 /*
73   Enumerated declaractions.
74 */
75 typedef enum
76 {
77   BitmapMode = 0,
78   GrayscaleMode = 1,
79   IndexedMode = 2,
80   RGBMode = 3,
81   CMYKMode = 4,
82   MultichannelMode = 7,
83   DuotoneMode = 8,
84   LabMode = 9
85 } PSDImageType;
86 \f
87 /*
88   Typedef declaractions.
89 */
90 typedef struct _ChannelInfo
91 {
92   short int
93     type;
94
95   unsigned long
96     size;
97 } ChannelInfo;
98
99 typedef struct _LayerInfo
100 {
101   RectangleInfo
102     page,
103     mask;
104
105   unsigned short
106     channels;
107
108   ChannelInfo
109     channel_info[MaxPSDChannels];
110
111   char
112     blendkey[4];
113
114   Quantum
115     opacity;
116
117   unsigned char
118     clipping,
119     visible,
120     flags;
121
122   unsigned long
123     offset_x,
124     offset_y;
125
126   unsigned char
127     name[256];
128
129   Image
130     *image;
131 } LayerInfo;
132
133 typedef struct _PSDInfo
134 {
135   char
136     signature[4];
137
138   unsigned short
139     channels,
140     version;
141
142   unsigned char
143     reserved[6];
144
145   unsigned long
146     rows,
147     columns;
148
149   unsigned short
150     depth,
151     mode;
152 } PSDInfo;
153 \f
154 /*
155   Forward declarations.
156 */
157 static MagickBooleanType
158   WritePSDImage(const ImageInfo *,Image *);
159 \f
160 /*
161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162 %                                                                             %
163 %                                                                             %
164 %                                                                             %
165 %   D e c o d e I m a g e                                                     %
166 %                                                                             %
167 %                                                                             %
168 %                                                                             %
169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 %
171 %  DecodeImage uncompresses an image via Macintosh encoding specific to
172 %  the Adobe Photoshop image format.
173 %
174 %  The format of the DecodeImage method is:
175 %
176 %      MagickBooleanType DecodeImage(Image *image,const long channel)
177 %
178 %  A description of each parameter follows:
179 %
180 %    o image,image: the address of a structure of type Image.
181 %
182 %    o channel:  Specifies which channel: red, green, blue, or index to
183 %      decode the pixel values into.
184 %
185 */
186 static MagickBooleanType DecodeImage(Image *image,const long channel)
187 {
188   ExceptionInfo
189     *exception;
190
191   MagickOffsetType
192     number_pixels;
193
194   Quantum
195     pixel;
196
197   register IndexPacket
198     *indexes;
199
200   register long
201     i,
202     x;
203
204   register PixelPacket
205     *q;
206
207   ssize_t
208     count;
209
210   exception=(&image->exception);
211   number_pixels=(MagickOffsetType) image->columns*image->rows;
212   for (x=0; number_pixels > 0; )
213   {
214     count=(ssize_t) ReadBlobByte(image);
215     if (count >= 128)
216       count-=256;
217     if (count < 0)
218       {
219         if (count == -128)
220           continue;
221         pixel=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
222         q=GetAuthenticPixels(image,(long) (x % image->columns),
223           (long) (x/image->columns),-count+1,1,exception);
224         if (q == (PixelPacket *) NULL)
225           break;
226         indexes=GetAuthenticIndexQueue(image);
227         for (count=(-count+1); count > 0; count--)
228         {
229           switch (channel)
230           {
231             case -1:
232             {
233               q->opacity=(Quantum) (QuantumRange-pixel);
234               break;
235             }
236             case 0:
237             {
238               q->red=pixel;
239               if (image->storage_class == PseudoClass)
240                 {
241                   *indexes=(IndexPacket) ScaleQuantumToChar(pixel);
242                   q->red=image->colormap[(long) *indexes].red;
243                   q->green=image->colormap[(long) *indexes].green;
244                   q->blue=image->colormap[(long) *indexes].blue;
245                 }
246               break;
247             }
248             case 1:
249             {
250               if (image->storage_class == PseudoClass)
251                 q->opacity=(Quantum) (QuantumRange-pixel);
252               else
253                 q->green=pixel;
254               break;
255             }
256             case 2:
257             {
258               q->blue=pixel;
259               break;
260             }
261             case 3:
262             {
263               if (image->colorspace == CMYKColorspace)
264                 *indexes=(IndexPacket) pixel;
265               else
266                 q->opacity=(Quantum) (QuantumRange-pixel);
267               break;
268             }
269             case 4:
270             {
271               q->opacity=(Quantum) (QuantumRange-pixel);
272               break;
273             }
274             default:
275               break;
276           }
277           if (SyncAuthenticPixels(image,exception) == MagickFalse)
278             break;
279           q++;
280           indexes++;
281           x++;
282           number_pixels--;
283         }
284         continue;
285       }
286     count++;
287     q=GetAuthenticPixels(image,(long) (x % image->columns),
288       (long) (x/image->columns),count,1,exception);
289     if (q == (PixelPacket *) NULL)
290       break;
291     indexes=GetAuthenticIndexQueue(image);
292     for (i=(long) count; i > 0; i--)
293     {
294       pixel=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
295       switch (channel)
296       {
297         case -1:
298         {
299           q->opacity=(Quantum) (QuantumRange-pixel);
300           break;
301         }
302         case 0:
303         {
304           q->red=pixel;
305           if (image->storage_class == PseudoClass)
306             {
307               *indexes=(IndexPacket) ScaleQuantumToChar(pixel);
308               q->red=image->colormap[(long) *indexes].red;
309               q->green=image->colormap[(long) *indexes].green;
310               q->blue=image->colormap[(long) *indexes].blue;
311             }
312           break;
313         }
314         case 1:
315         {
316           if (image->storage_class == PseudoClass)
317             q->opacity=(Quantum) (QuantumRange-pixel);
318           else
319             q->green=pixel;
320           break;
321         }
322         case 2:
323         {
324           q->blue=pixel;
325           break;
326         }
327         case 3:
328         {
329           if (image->colorspace == CMYKColorspace)
330             *indexes=(IndexPacket) pixel;
331           else
332             q->opacity=(Quantum) (QuantumRange-pixel);
333           break;
334         }
335         case 4:
336         {
337           q->opacity=(Quantum) pixel;
338           break;
339         }
340         default:
341           break;
342       }
343       if (SyncAuthenticPixels(image,exception) == MagickFalse)
344         break;
345       q++;
346       indexes++;
347       x++;
348       number_pixels--;
349     }
350   }
351   /*
352     Guarentee the correct number of pixel packets.
353   */
354   if (number_pixels > 0)
355     ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
356       image->filename)
357   else
358     if (number_pixels < 0)
359       ThrowBinaryException(CorruptImageError,"TooMuchImageDataInFile",
360         image->filename);
361   return(MagickTrue);
362 }
363 \f
364 /*
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 %                                                                             %
367 %                                                                             %
368 %                                                                             %
369 %   I s P S D                                                                 %
370 %                                                                             %
371 %                                                                             %
372 %                                                                             %
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374 %
375 %  IsPSD()() returns MagickTrue if the image format type, identified by the
376 %  magick string, is PSD.
377 %
378 %  The format of the IsPSD method is:
379 %
380 %      MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
381 %
382 %  A description of each parameter follows:
383 %
384 %    o magick: compare image format pattern against these bytes.
385 %
386 %    o length: Specifies the length of the magick string.
387 %
388 */
389 static MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
390 {
391   if (length < 4)
392     return(MagickFalse);
393   if (LocaleNCompare((const char *) magick,"8BPS",4) == 0)
394     return(MagickTrue);
395   if (LocaleNCompare((const char *) magick,"8BPB",4) == 0)
396     return(MagickTrue);
397   return(MagickFalse);
398 }
399 \f
400 /*
401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402 %                                                                             %
403 %                                                                             %
404 %                                                                             %
405 %   R e a d P S D I m a g e                                                   %
406 %                                                                             %
407 %                                                                             %
408 %                                                                             %
409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
410 %
411 %  ReadPSDImage() reads an Adobe Photoshop image file and returns it.  It
412 %  allocates the memory necessary for the new Image structure and returns a
413 %  pointer to the new image.
414 %
415 %  The format of the ReadPSDImage method is:
416 %
417 %      image=ReadPSDImage(image_info)
418 %
419 %  A description of each parameter follows:
420 %
421 %    o image_info: the image info.
422 %
423 %    o exception: return any errors or warnings in this structure.
424 %
425 */
426
427 static inline MagickOffsetType GetPSDOffset(PSDInfo *psd_info,Image *image)
428 {
429   if (psd_info->version == 1)
430     return((MagickOffsetType) ReadBlobMSBShort(image));
431   return((MagickOffsetType) ReadBlobMSBLong(image));
432 }
433
434 static inline MagickSizeType GetPSDSize(PSDInfo *psd_info,Image *image)
435 {
436   if (psd_info->version == 1)
437     return((MagickSizeType) ReadBlobMSBLong(image));
438   return((MagickSizeType) ReadBlobMSBLongLong(image));
439 }
440
441 static inline long MagickAbsoluteValue(const long x)
442 {
443   if (x < 0)
444     return(-x);
445   return(x);
446 }
447
448 static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
449 {
450   if (mode == (const char *) NULL)
451     return(OverCompositeOp);
452   if (LocaleNCompare(mode,"norm",4) == 0)
453     return(OverCompositeOp);
454   if (LocaleNCompare(mode,"mul ",4) == 0)
455     return(MultiplyCompositeOp);
456   if (LocaleNCompare(mode,"diss",4) == 0)
457     return(DissolveCompositeOp);
458   if (LocaleNCompare(mode,"diff",4) == 0)
459     return(DifferenceCompositeOp);
460   if (LocaleNCompare(mode,"dark",4) == 0)
461     return(DarkenCompositeOp);
462   if (LocaleNCompare(mode,"lite",4) == 0)
463     return(LightenCompositeOp);
464   if (LocaleNCompare(mode,"hue ",4) == 0)
465     return(HueCompositeOp);
466   if (LocaleNCompare(mode,"sat ",4) == 0)
467     return(SaturateCompositeOp);
468   if (LocaleNCompare(mode,"colr",4) == 0)
469     return(ColorizeCompositeOp);
470   if (LocaleNCompare(mode,"lum ",4) == 0)
471     return(LuminizeCompositeOp);
472   if (LocaleNCompare(mode,"scrn",4) == 0)
473     return(ScreenCompositeOp);
474   if (LocaleNCompare(mode,"over",4) == 0)
475     return(OverlayCompositeOp);
476   if (LocaleNCompare(mode,"hLit",4) == 0)
477     return(OverCompositeOp);
478   if (LocaleNCompare(mode,"sLit",4) == 0)
479     return(OverCompositeOp);
480   if (LocaleNCompare(mode,"smud",4) == 0)
481     return(OverCompositeOp);
482   if (LocaleNCompare(mode,"div ",4) == 0)
483     return(OverCompositeOp);
484   if (LocaleNCompare(mode,"idiv",4) == 0)
485     return(OverCompositeOp);
486   return(OverCompositeOp);
487 }
488
489 static const char *CompositeOperatorToPSDBlendMode(CompositeOperator inOp)
490 {
491   const char
492     *outMode = "norm";
493
494   switch (inOp)
495   {
496     case OverCompositeOp:    outMode = "norm";  break;
497     case MultiplyCompositeOp:  outMode = "mul ";  break;
498     case DissolveCompositeOp:  outMode = "diss";  break;
499     case DifferenceCompositeOp:  outMode = "diff";  break;
500     case DarkenCompositeOp:    outMode = "dark";  break;
501     case LightenCompositeOp:  outMode = "lite";  break;
502     case HueCompositeOp:    outMode = "hue ";  break;
503     case SaturateCompositeOp:  outMode = "sat ";  break;
504     case ColorizeCompositeOp:  outMode = "colr";  break;
505     case LuminizeCompositeOp:  outMode = "lum ";  break;
506     case ScreenCompositeOp:    outMode = "scrn";  break;
507     case OverlayCompositeOp:  outMode = "over";  break;
508     default:
509       outMode = "norm";
510   }
511   return(outMode);
512 }
513
514 static const char *ModeToString( PSDImageType inType )
515 {
516   switch ( inType )
517   {
518     case BitmapMode: return "Bitmap";
519     case GrayscaleMode: return "Grayscale";
520     case IndexedMode: return "Indexed";
521     case RGBMode: return "RGB";
522     case CMYKMode:  return "CMYK";
523     case MultichannelMode: return "Multichannel";
524     case DuotoneMode: return "Duotone";
525     case LabMode: return "L*A*B";
526     default: return "unknown";
527   }
528 }
529
530 static MagickBooleanType ParseImageResourceBlocks(Image *image,
531   const unsigned char *blocks,size_t length)
532 {
533   const unsigned char
534     *p;
535
536   StringInfo
537     *profile;
538
539   unsigned long
540     count,
541     long_sans;
542
543   unsigned short
544     id,
545     short_sans;
546
547   if (length < 16)
548     return(MagickFalse);
549   profile=AcquireStringInfo(length);
550   SetStringInfoDatum(profile,blocks);
551   (void) SetImageProfile(image,"8bim",profile);
552   profile=DestroyStringInfo(profile);
553   for (p=blocks; (p >= blocks) && (p < (blocks+length-16)); )
554   {
555     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
556       break;
557     p=PushLongPixel(LSBEndian,p,&long_sans);
558     p=PushShortPixel(LSBEndian,p,&id);
559     p=PushShortPixel(LSBEndian,p,&short_sans);
560     p=PushLongPixel(LSBEndian,p,&count);
561     switch (id)
562     {
563       case 0x03ed:
564       {
565         unsigned short
566           resolution;
567
568         /*
569           Resolution info.
570         */
571         p=PushShortPixel(LSBEndian,p,&resolution);
572         image->x_resolution=(double) resolution;
573         p=PushShortPixel(LSBEndian,p,&short_sans);
574         p=PushShortPixel(LSBEndian,p,&short_sans);
575         p=PushShortPixel(LSBEndian,p,&short_sans);
576         p=PushShortPixel(LSBEndian,p,&resolution);
577         image->y_resolution=(double) resolution;
578         p=PushShortPixel(LSBEndian,p,&short_sans);
579         p=PushShortPixel(LSBEndian,p,&short_sans);
580         p=PushShortPixel(LSBEndian,p,&short_sans);
581         break;
582       }
583       default:
584       {
585         p+=count;
586         break;
587       }
588     }
589     if ((count & 0x01) != 0)
590       p++;
591   }
592   return(MagickTrue);
593 }
594
595 static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
596 {
597   char
598     s[MaxTextExtent],
599     type[4];
600
601   Image
602     *image;
603
604   IndexPacket
605     *indexes;
606
607   LayerInfo
608     *layer_info;
609
610   long
611     j,
612     number_layers,
613     y;
614
615   PSDInfo
616     psd_info;
617
618   register long
619     x;
620
621   register PixelPacket
622     *q;
623
624   register long
625     i;
626
627   MagickSizeType
628     length,
629     combinedlength,
630     size;
631
632   ssize_t
633     count;
634
635   MagickBooleanType
636     status;
637
638   MagickOffsetType
639     offset;
640
641   size_t
642     packet_size;
643
644   unsigned char
645     *data;
646
647   unsigned short
648     compression;
649
650   unsigned long
651     mask_size,
652     pixel,
653     skip_first_alpha = 0;
654
655   /*
656     Open image file.
657   */
658   assert(image_info != (const ImageInfo *) NULL);
659   assert(image_info->signature == MagickSignature);
660   if (image_info->debug != MagickFalse)
661     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
662       image_info->filename);
663   assert(exception != (ExceptionInfo *) NULL);
664   assert(exception->signature == MagickSignature);
665   image=AcquireImage(image_info);
666   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
667   if (status == MagickFalse)
668     {
669       image=DestroyImageList(image);
670       return((Image *) NULL);
671     }
672   /*
673     Read image header.
674   */
675   count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
676   psd_info.version=ReadBlobMSBShort(image);
677   if ((count == 0) || ((LocaleNCompare(psd_info.signature,"8BPS",4) != 0) &&
678       (LocaleNCompare(psd_info.signature,"8BPB",4) != 0)) ||
679       ((psd_info.version != 1) && (psd_info.version != 2)))
680     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
681   count=ReadBlob(image,6,psd_info.reserved);
682   psd_info.channels=ReadBlobMSBShort(image);
683   if (psd_info.channels > MaxPSDChannels)
684     ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
685   psd_info.rows=ReadBlobMSBLong(image);
686   psd_info.columns=ReadBlobMSBLong(image);
687   if ((psd_info.version == 1) && ((psd_info.rows > 30000) ||
688       (psd_info.columns > 30000)))
689     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
690   if ((psd_info.version == 1) && ((psd_info.rows > 300000) ||
691       (psd_info.columns > 300000)))
692     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
693   psd_info.depth=ReadBlobMSBShort(image);
694   if ((psd_info.depth != 1) && (psd_info.depth != 8) && (psd_info.depth != 16))
695     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
696   psd_info.mode=ReadBlobMSBShort(image);
697   if (image->debug != MagickFalse)
698     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
699       "  Image is %ld x %ld with channels=%d, depth=%d, mode=%s",
700       psd_info.columns,psd_info.rows,psd_info.channels,psd_info.depth,
701       ModeToString((PSDImageType) psd_info.mode));
702   /*
703     Initialize image.
704   */
705   image->depth=psd_info.depth;
706   image->columns=psd_info.columns;
707   image->rows=psd_info.rows;
708   if (SetImageBackgroundColor(image) == MagickFalse)
709     {
710       InheritException(exception,&image->exception);
711       image=DestroyImageList(image);
712       return((Image *) NULL);
713     }
714   image->matte=psd_info.channels >= 4 ? MagickTrue : MagickFalse;
715   if (psd_info.mode == LabMode)
716     image->colorspace=LabColorspace;
717   if (psd_info.mode == CMYKMode)
718     {
719       image->colorspace=CMYKColorspace;
720       image->matte=psd_info.channels >= 5 ? MagickTrue : MagickFalse;
721     }
722   if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
723       (psd_info.mode == DuotoneMode))
724     {
725       if (AcquireImageColormap(image,256) == MagickFalse)
726         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
727       image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
728       if (image->debug != MagickFalse)
729         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
730           "  ImageColorMap allocated");
731     }
732   if (image->debug != MagickFalse)
733     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
734       image->matte ? "  image has matte" : "  image has no matte");
735   /*
736     Read PSD raster colormap only present for indexed and duotone images.
737   */
738   length=ReadBlobMSBLong(image);
739   if (length != 0)
740     {
741       if (image->debug != MagickFalse)
742         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
743           "  reading colormap");
744       if (psd_info.mode == DuotoneMode)
745         {
746           /*
747             Duotone image data;  the format of this data is undocumented.
748           */
749           data=(unsigned char *) AcquireQuantumMemory(length,sizeof(*data));
750           if (data == (unsigned char *) NULL)
751             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
752           count=ReadBlob(image,length,data);
753           data=(unsigned char *) RelinquishMagickMemory(data);
754         }
755       else
756         {
757           /*
758             Read PSD raster colormap.
759           */
760           if (AcquireImageColormap(image,(unsigned long) (length/3)) == MagickFalse)
761             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
762           for (i=0; i < (long) image->colors; i++)
763             image->colormap[i].red=ScaleCharToQuantum((unsigned char)
764               ReadBlobByte(image));
765           for (i=0; i < (long) image->colors; i++)
766             image->colormap[i].green=ScaleCharToQuantum((unsigned char)
767               ReadBlobByte(image));
768           for (i=0; i < (long) image->colors; i++)
769             image->colormap[i].blue=ScaleCharToQuantum((unsigned char)
770               ReadBlobByte(image));
771           image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
772         }
773     }
774   length=ReadBlobMSBLong(image);
775   if (length != 0)
776     {
777       unsigned char
778         *blocks;
779
780       /*
781         Image resources block.
782       */
783       if (image->debug != MagickFalse)
784         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
785           "  reading image resource blocks - %ld bytes",(long) length);
786       blocks=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blocks));
787       if (blocks == (unsigned char *) NULL)
788         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
789       count=ReadBlob(image,length,blocks);
790       if (((size_t) count != length) ||
791           (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
792         {
793           blocks=(unsigned char *) RelinquishMagickMemory(blocks);
794           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
795         }
796       (void) ParseImageResourceBlocks(image,blocks,length);
797       blocks=(unsigned char *) RelinquishMagickMemory(blocks);
798     }
799   /*
800     If we are only "pinging" the image, then we're done - so return.
801   */
802   if (image_info->ping != MagickFalse)
803     {
804       (void) CloseBlob(image);
805       return(GetFirstImageInList(image));
806     }
807   /*
808     Layer and mask block.
809   */
810   layer_info=(LayerInfo *) NULL;
811   number_layers=1;
812   length=GetPSDSize(&psd_info,image);
813   if (length == 8)
814     {
815       length=ReadBlobMSBLong(image);
816       length=ReadBlobMSBLong(image);
817     }
818   if ((image_info->number_scenes == 1) && (image_info->scene == 0))
819     for ( ; length != 0; length--)
820       if (ReadBlobByte(image) == EOF)
821         {
822           ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
823             image->filename);
824           break;
825         }
826   if (length == 0)
827     {
828       if (image->debug != MagickFalse)
829         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
830           "  image has no layers");
831     }
832   else
833     {
834       offset=TellBlob(image);
835       size=GetPSDSize(&psd_info,image);
836       if (size == 0)
837         {
838           unsigned long
839             quantum;
840
841           /*
842             Skip layers & masks.
843           */
844           quantum=psd_info.version == 1 ? 4 : 8;
845           for (j=0; j < (long) (length-quantum); j++)
846             (void) ReadBlobByte(image);
847         }
848       else
849         {
850           MagickOffsetType
851             layer_offset;
852
853           layer_offset=offset+length;
854           number_layers=(short) ReadBlobMSBShort(image);
855           if (image->debug != MagickFalse)
856             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
857               "  image contains %ld layers", number_layers);
858           if (number_layers < 0)
859             {
860               /*
861                 Weird hack in PSD format to ignore first alpha channel.
862               */
863               skip_first_alpha=1;
864               number_layers=MagickAbsoluteValue(number_layers);
865               if (image->debug != MagickFalse)
866                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
867                   "  negative layer count corrected for");
868             }
869           layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
870             sizeof(*layer_info));
871           if (layer_info == (LayerInfo *) NULL)
872             {
873               if (image->debug != MagickFalse)
874                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
875                   "  allocation of LayerInfo failed");
876               ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
877             }
878           (void) ResetMagickMemory(layer_info,0,(size_t) number_layers*
879             sizeof(*layer_info));
880           for (i=0; i < number_layers; i++)
881           {
882             if (image->debug != MagickFalse)
883               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
884                 "  reading layer #%ld",i+1);
885             layer_info[i].page.y=(long) ReadBlobMSBLong(image);
886             layer_info[i].page.x=(long) ReadBlobMSBLong(image);
887             layer_info[i].page.height=ReadBlobMSBLong(image)-layer_info[i].page.y;
888             layer_info[i].page.width=ReadBlobMSBLong(image)-layer_info[i].page.x;
889             layer_info[i].channels=ReadBlobMSBShort(image);
890             if (layer_info[i].channels > MaxPSDChannels)
891               ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
892             if (image->debug != MagickFalse)
893               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
894                 "    offset(%ld,%ld), size(%ld,%ld), channels=%d",
895                 layer_info[i].page.x, layer_info[i].page.y,
896                 layer_info[i].page.height,layer_info[i].page.width,
897                 layer_info[i].channels);
898             for (j=0; j < (long) layer_info[i].channels; j++)
899             {
900               layer_info[i].channel_info[j].type=(short) ReadBlobMSBShort(image);
901               layer_info[i].channel_info[j].size=ReadBlobMSBLong(image);
902               if (image->debug != MagickFalse)
903                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
904                   "    channel[%ld]: type=%d, size=%ld",j,
905                   layer_info[i].channel_info[j].type,
906               (long) layer_info[i].channel_info[j].size);
907             }
908             count=ReadBlob(image,4,(unsigned char *) type);
909             if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
910               {
911                 if (image->debug != MagickFalse)
912                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
913                     "  layer type was %.4s instead of 8BIM", type);
914                  ThrowReaderException(CorruptImageError,"ImproperImageHeader");
915               }
916             count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
917             layer_info[i].opacity=(Quantum) (QuantumRange-ScaleCharToQuantum(
918               (unsigned char) ReadBlobByte(image)));
919             layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
920             layer_info[i].flags=(unsigned char) ReadBlobByte(image);
921             layer_info[i].visible=!(layer_info[i].flags & 0x02);
922             if (image->debug != MagickFalse)
923               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
924                 "   blend=%.4s, opacity=%lu, clipping=%s, flags=%d, visible=%s",
925                 layer_info[i].blendkey,(unsigned long) layer_info[i].opacity,
926                 layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
927                 layer_info[i].visible ? "true" : "false");
928             (void) ReadBlobByte(image);  /* filler */
929             combinedlength=0;
930             size=ReadBlobMSBLong(image);
931             if (size != 0)
932               {
933                 if (image->debug != MagickFalse)
934                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
935                     "    layer contains additional info");
936                 length=ReadBlobMSBLong(image);
937                 if (length != 0)
938                   {
939                     /*
940                       Layer mask info.
941                     */
942                     layer_info[i].mask.y=(long) ReadBlobMSBLong(image);
943                     layer_info[i].mask.x=(long) ReadBlobMSBLong(image);
944                     layer_info[i].mask.height=
945                       (ReadBlobMSBLong(image)-layer_info[i].mask.y);
946                     layer_info[i].mask.width=
947                       (ReadBlobMSBLong(image)-layer_info[i].mask.x);
948                     if (image->debug != MagickFalse)
949                       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
950                         "      layer mask: offset(%ld,%ld), size(%ld,%ld), length=%ld",
951                         layer_info[i].mask.x,layer_info[i].mask.y,
952                         layer_info[i].mask.width, layer_info[i].mask.height,
953                         (long) length-16);
954                     /*
955                       Skip over the rest of the layer mask information.
956                     */
957                     for (j=0; j < (long) (length-16); j++)
958                       (void) ReadBlobByte(image);
959                   }
960                 combinedlength+=length+4;  /* +4 for length */
961                 length=ReadBlobMSBLong(image);
962                 if (length != 0)
963                   {
964                     /*
965                       Layer blending ranges info.
966                     */
967                     if (image->debug != MagickFalse)
968                       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
969                         "      layer blending ranges: length=%ld",(long) length);
970                     /*
971                       We read it, but don't use it...
972                     */
973                     for (j=0; j < (long) (length); j+=8)
974                     {
975                       size_t blend_source=ReadBlobMSBLong(image);
976                       size_t blend_dest=ReadBlobMSBLong(image);
977                       if (image->debug != MagickFalse)
978                         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
979                           "        source(%x), dest(%x)",(unsigned int)
980                           blend_source,(unsigned int) blend_dest);
981                     }
982                   }
983                 combinedlength+=length+4;
984                 /*
985                   Layer name.
986                 */
987                 length=(size_t) ReadBlobByte(image);
988                 for (j=0; j < (long) length; j++)
989                   layer_info[i].name[j]=(unsigned char) ReadBlobByte(image);
990                 layer_info[i].name[j]='\0';
991                 if (image->debug != MagickFalse)
992                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
993                     "      layer name: %s",layer_info[i].name);
994                 combinedlength+=length+1;
995
996 #if     0  /* still in development */
997           /*
998             Adjustment layers and other stuff...
999           */
1000           {
1001             char  alsig[4],
1002                 alkey[4];
1003
1004             count=ReadBlob(image,4,alsig);
1005             if ((count == 0) || (LocaleNCompare(alsig,"8BIM",4) != 0)) {
1006               if (debug != MagickFalse)
1007               {
1008       if (image->debug != MagickFalse)
1009                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  adjustment layer type was %.4s instead of 8BIM", alsig);
1010               }
1011               ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1012             }
1013             count=ReadBlob(image,4,alkey);
1014             length=ReadBlobMSBLong(image);
1015               if (debug != MagickFalse)
1016               {
1017       if (image->debug != MagickFalse)
1018                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1019                             "      adjustment layer key: %.4s, data length=%ld",
1020                             alkey, length);
1021               }
1022
1023               if ( length ) {
1024               for (j=0; j < (long) (length); j++)
1025                 (void) ReadBlobByte(image);
1026               }
1027
1028           }
1029           combinedlength += 12 + length;  /* sig, key, length + the actual length*/
1030 #endif
1031
1032                /*
1033                   Skip the rest of the variable data until we support it.
1034                 */
1035                 if (image->debug != MagickFalse)
1036                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1037                     "      unsupported data: length=%ld",(long)
1038                     (size-combinedlength));
1039                 for (j=0; j < (long) (size-combinedlength); j++)
1040                   (void) ReadBlobByte(image);
1041               }
1042             /*
1043               Allocate layered image.
1044             */
1045             layer_info[i].image=CloneImage(image,layer_info[i].page.width,
1046               layer_info[i].page.height,MagickFalse,&image->exception);
1047             if (layer_info[i].image == (Image *) NULL)
1048               {
1049                 for (j=0; j < i; j++)
1050                   layer_info[j].image=DestroyImage(layer_info[j].image);
1051                 if (image->debug != MagickFalse)
1052                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1053                     "  allocation of image for layer %ld failed", i);
1054                 ThrowReaderException(ResourceLimitError,
1055                   "MemoryAllocationFailed");
1056               }
1057             if (image->debug != MagickFalse)
1058               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1059                 "    setting up new layer image");
1060             (void) SetImageBackgroundColor(layer_info[i].image);
1061             layer_info[i].image->compose=
1062               PSDBlendModeToCompositeOperator(layer_info[i].blendkey);
1063             if (layer_info[i].visible == MagickFalse)
1064               layer_info[i].image->compose=NoCompositeOp;
1065             if (psd_info.mode == CMYKMode)
1066               image->colorspace=CMYKColorspace;
1067             for (j=0; j < (long) layer_info[i].channels; j++)
1068               if (layer_info[i].channel_info[j].type == -1)
1069                 layer_info[i].image->matte=MagickTrue;
1070             /*
1071               Set up some hidden attributes for folks that need them.
1072             */
1073             (void) FormatMagickString(s,MaxTextExtent,"%ld",
1074               layer_info[i].page.x );
1075             (void) SetImageArtifact(layer_info[i].image,"psd:layer.x",s);
1076             (void) FormatMagickString(s,MaxTextExtent,"%ld",
1077               layer_info[i].page.y);
1078             (void) SetImageArtifact(layer_info[i].image,"psd:layer.y",s);
1079             (void) FormatMagickString(s,MaxTextExtent,"%lu",(unsigned long)
1080               layer_info[i].opacity );
1081             (void) SetImageArtifact(layer_info[i].image,"psd:layer.opacity",s);
1082             (void) SetImageProperty(layer_info[i].image,"label",(char *)
1083               layer_info[i].name);
1084           }
1085         if (image->debug != MagickFalse)
1086           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1087             "  reading image data for layers");
1088         /*
1089           Read pixel data for each layer.
1090         */
1091         for (i=0; i < number_layers; i++)
1092         {
1093           if (image->debug != MagickFalse)
1094             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1095               "  reading data for layer %ld",i);
1096             for (j=0; j < (long) layer_info[i].channels; j++)
1097             {
1098               if (image->debug != MagickFalse)
1099                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1100                   "    reading data for channel %ld", j);
1101 #if     1
1102               if (layer_info[i].channel_info[j].size <= (2*layer_info[i].image->rows))
1103                 {
1104                   long
1105                     k;
1106
1107                   if (image->debug != MagickFalse)
1108                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1109                       "      layer data is empty");
1110                   /*
1111                     A layer without data.
1112                   */
1113                   for (k=0; k < (long) layer_info[i].channel_info[j].size; k++)
1114                     (void) ReadBlobByte(layer_info[i].image);
1115                   continue;
1116                 }
1117 #endif
1118               compression=ReadBlobMSBShort(layer_info[i].image);
1119               if ((layer_info[i].page.height != 0) &&
1120                   (layer_info[i].page.width != 0))
1121                 {
1122                   if (compression == 1)
1123                     {
1124                       /*
1125                         Read RLE compressed data.
1126                       */
1127                       if (image->debug != MagickFalse)
1128                         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1129                           "      layer data is RLE compressed");
1130                       for (y=0; y < (long) layer_info[i].image->rows; y++)
1131                         (void) GetPSDOffset(&psd_info,layer_info[i].image);
1132                       (void) DecodeImage(layer_info[i].image,
1133                          layer_info[i].channel_info[j].type);
1134                       continue;
1135                     }
1136                   /*
1137                     Read uncompressed pixel datas separate planes.
1138                   */
1139                   if (image->debug != MagickFalse)
1140                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1141                       "      layer data is uncompressed");
1142                   packet_size=1;
1143                   if (layer_info[i].image->storage_class == PseudoClass)
1144                     {
1145                       if (layer_info[i].image->colors > 256)
1146                         packet_size++;
1147                       else
1148                         if (layer_info[i].image->depth > 8)
1149                           packet_size++;
1150                     }
1151                   else
1152                     if (layer_info[i].image->depth > 8)
1153                       packet_size++;
1154                   for (y=0; y < (long) layer_info[i].image->rows; y++)
1155                   {
1156                     q=GetAuthenticPixels(layer_info[i].image,0,y,
1157                       layer_info[i].image->columns,1,exception);
1158                     if (q == (PixelPacket *) NULL)
1159                       break;
1160                     indexes=GetAuthenticIndexQueue(layer_info[i].image);
1161                     for (x=0; x < (long) layer_info[i].image->columns; x++)
1162                     {
1163                       if (packet_size == 1)
1164                         pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1165                           ReadBlobByte(layer_info[i].image));
1166                       else
1167                         pixel=(unsigned long) ScaleShortToQuantum(
1168                           ReadBlobMSBShort(layer_info[i].image));
1169                       switch (layer_info[i].channel_info[j].type)
1170                       {
1171                         case -1:  /* transparency mask */
1172                         {
1173                           q->opacity=(Quantum) (QuantumRange-pixel);
1174                           break;
1175                         }
1176                         case 0:  /* first component (Red, Cyan, Gray or Index) */
1177                         {
1178                           q->red=(Quantum) pixel;
1179                           if (layer_info[i].image->storage_class == PseudoClass)
1180                             {
1181                               if (packet_size == 1)
1182                                 indexes[x]=(IndexPacket) ScaleQuantumToChar(
1183                                   (Quantum) pixel);
1184                               else
1185                                 indexes[x]=(IndexPacket) ScaleQuantumToShort(
1186                                   (Quantum) pixel);
1187                               q->red=layer_info[i].image->colormap[(long) *indexes].red;
1188                               q->green=layer_info[i].image->colormap[(long) *indexes].green;
1189                               q->blue=layer_info[i].image->colormap[(long) *indexes].blue;
1190                             }
1191                           break;
1192                         }
1193                         case 1:  /* second component (Green, Magenta, or opacity) */
1194                         {
1195                           if (layer_info[i].image->storage_class == PseudoClass)
1196                             q->opacity=(Quantum) (QuantumRange-pixel);
1197                           else
1198                             q->green=(Quantum) pixel;
1199                           break;
1200                         }
1201                         case 2:  /* third component (Blue or Yellow) */
1202                         {
1203                           q->blue=(Quantum) pixel;
1204                           break;
1205                         }
1206                         case 3:  /* fourth component (Opacity or Black) */
1207                         {
1208                           if (image->colorspace == CMYKColorspace)
1209                             indexes[x]=(Quantum) pixel;
1210                           else
1211                             q->opacity=(Quantum) (QuantumRange-pixel);
1212                           break;
1213                         }
1214                         case 4:  /* fifth component (opacity) */
1215                         {
1216                           q->opacity=(Quantum) (QuantumRange-pixel);
1217                           break;
1218                         }
1219                         default:
1220                           break;
1221                       }
1222                       q++;
1223                     }
1224                     if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
1225                       break;
1226                   }
1227                   }
1228                 }
1229             if (layer_info[i].opacity != OpaqueOpacity)
1230               {
1231                 /*
1232                   Correct for opacity level.
1233                 */
1234                 for (y=0; y < (long) layer_info[i].image->rows; y++)
1235                 {
1236                   q=GetAuthenticPixels(layer_info[i].image,0,y,
1237                     layer_info[i].image->columns,1,exception);
1238                   if (q == (PixelPacket *) NULL)
1239                     break;
1240                   indexes=GetAuthenticIndexQueue(layer_info[i].image);
1241                   for (x=0; x < (long) layer_info[i].image->columns; x++)
1242                   {
1243                     q->opacity=(Quantum) (QuantumRange-(Quantum) (QuantumScale*
1244                       ((QuantumRange-q->opacity)*(QuantumRange-
1245                       layer_info[i].opacity))));
1246                     q++;
1247                   }
1248                   if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
1249                     break;
1250                 }
1251               }
1252             if (layer_info[i].image->colorspace == CMYKColorspace)
1253               (void) NegateImage(layer_info[i].image,MagickFalse);
1254             status=SetImageProgress(image,LoadImagesTag,i,number_layers);
1255             if (status == MagickFalse)
1256               break;
1257           }
1258         /* added by palf -> invisible group layer make layer of this group
1259            invisible I consider that all layer with width and height null are
1260            layer for group layer */
1261        {
1262          short inside_layer = 0;
1263          short layer_visible = 0;
1264          for (i=number_layers-1; i >=0; i--)
1265          {
1266            if ((layer_info[i].page.width == 0) ||
1267                (layer_info[i].page.height == 0))
1268              {
1269                if (inside_layer == 0)
1270                  {
1271                    inside_layer=1;
1272                    layer_visible=(short int) layer_info[i].visible;
1273                  }
1274                else
1275                  {
1276                    inside_layer = 0;
1277                  }
1278              }
1279            else
1280              if ((inside_layer == 1) && (layer_visible == 0))
1281                {
1282                  layer_info[i].visible=(unsigned char) layer_visible;
1283                  layer_info[i].image->compose=NoCompositeOp;
1284                }
1285          }
1286        }
1287        /* added by palf -> suppression of empty layer */
1288        /* I consider that all layer with width and height null are layer for group layer */
1289        for (i=0; i < number_layers; i++)
1290        {
1291          if ((layer_info[i].page.width == 0) ||
1292              (layer_info[i].page.height == 0))
1293            {
1294              if (layer_info[i].image != (Image *) NULL)
1295                layer_info[i].image=DestroyImage(layer_info[i].image);
1296              for (j=i; j < number_layers - 1; j++)
1297                layer_info[j] = layer_info[j+1];
1298              number_layers--;
1299              i--;
1300            }
1301          }
1302         mask_size = ReadBlobMSBLong(image);  /* global mask size: currently ignored */
1303           if (number_layers > 0)
1304             {
1305
1306           if (image->debug != MagickFalse)
1307             (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  putting layers into image list");
1308               for (i=0; i < number_layers; i++)
1309               {
1310                 if (i > 0)
1311                   layer_info[i].image->previous=layer_info[i-1].image;
1312                 if (i < (number_layers-1))
1313                   layer_info[i].image->next=layer_info[i+1].image;
1314                 layer_info[i].image->page=layer_info[i].page;
1315               }
1316             image->next=layer_info[0].image;
1317             layer_info[0].image->previous=image;
1318             layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
1319
1320             }
1321           layer_offset-=TellBlob(image);
1322           offset=SeekBlob(image,layer_offset,SEEK_CUR);
1323         }
1324     }
1325   /*
1326     Read the precombined layer, present for PSD < 4 compatibility
1327   */
1328   if (image->debug != MagickFalse)
1329     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1330       "  reading the precombined layer");
1331   compression=ReadBlobMSBShort(image);
1332   if (compression == 1)
1333     {
1334       /*
1335         Read Packbit encoded pixel datas separate planes.
1336       */
1337       for (i=0; i < (long) (image->rows*psd_info.channels); i++)
1338         (void) GetPSDOffset(&psd_info,image);
1339       for (i=0; i < (long) psd_info.channels; i++)
1340       {
1341         (void) DecodeImage(image,(int) i);
1342         status=SetImageProgress(image,LoadImagesTag,i,psd_info.channels);
1343         if (status == MagickFalse)
1344           break;
1345       }
1346     }
1347   else
1348     {
1349       /*
1350         Read uncompressed pixel data separate planes.
1351       */
1352       packet_size=1;
1353       if (image->storage_class == PseudoClass)
1354         {
1355           if (image->colors > 256)
1356             packet_size++;
1357           else
1358             if (image->depth > 8)
1359               packet_size++;
1360         }
1361       else
1362         if (image->depth > 8)
1363           packet_size++;
1364       for (i=0; i < (long) psd_info.channels; i++)
1365       {
1366         for (y=0; y < (long) image->rows; y++)
1367         {
1368           q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
1369           if (q == (PixelPacket *) NULL)
1370             break;
1371           indexes=GetAuthenticIndexQueue(image);
1372           for (x=0; x < (long) image->columns; x++)
1373           {
1374             if (packet_size == 1)
1375               pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1376                 ReadBlobByte(image));
1377             else
1378               pixel=(unsigned long) ScaleShortToQuantum(
1379                 ReadBlobMSBShort(image));
1380             switch (i)
1381             {
1382               case -1:
1383               {
1384                 q->opacity=(Quantum) (QuantumRange-pixel);
1385                 break;
1386               }
1387               case 0:
1388               {
1389                 q->red=(Quantum) pixel;
1390                 if (psd_info.channels == 1)
1391                   {
1392                     q->green=q->red;
1393                     q->blue=q->red;
1394                   }
1395                 if (image->storage_class == PseudoClass)
1396                   {
1397                     if (packet_size == 1)
1398                       indexes[x]=(IndexPacket) ScaleQuantumToChar((Quantum)
1399                         pixel);
1400                     else
1401                       indexes[x]=(IndexPacket) ScaleQuantumToShort((Quantum)
1402                         pixel);
1403                     *q=image->colormap[(long) indexes[x]];
1404                     q->red=image->colormap[(long) indexes[x]].red;
1405                     q->green=image->colormap[(long) indexes[x]].green;
1406                     q->blue=image->colormap[(long) indexes[x]].blue;
1407                   }
1408                 break;
1409               }
1410               case 1:
1411               {
1412                 if (image->storage_class == PseudoClass)
1413                   q->opacity=(Quantum) (QuantumRange-pixel);
1414                 else
1415                   q->green=(Quantum) pixel;
1416                 break;
1417               }
1418               case 2:
1419               {
1420                 q->blue=(Quantum) pixel;
1421                 break;
1422               }
1423               case 3:
1424               {
1425                 if (image->colorspace == CMYKColorspace)
1426                   indexes[x]=(IndexPacket) pixel;
1427                 else
1428                   q->opacity=(Quantum) (QuantumRange-pixel);
1429                 break;
1430               }
1431               case 4:
1432               {
1433                 q->opacity=(Quantum) (QuantumRange-pixel);
1434                 break;
1435               }
1436               default:
1437                 break;
1438             }
1439             q++;
1440           }
1441           if (SyncAuthenticPixels(image,exception) == MagickFalse)
1442             break;
1443         }
1444         status=SetImageProgress(image,LoadImagesTag,i,psd_info.channels);
1445         if (status == MagickFalse)
1446           break;
1447       }
1448     }
1449   if (image->colorspace == CMYKColorspace)
1450     (void) NegateImage(image,MagickFalse);
1451   (void) CloseBlob(image);
1452   return(GetFirstImageInList(image));
1453 }
1454 \f
1455 /*
1456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1457 %                                                                             %
1458 %                                                                             %
1459 %                                                                             %
1460 %   R e g i s t e r P S D I m a g e                                           %
1461 %                                                                             %
1462 %                                                                             %
1463 %                                                                             %
1464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465 %
1466 %  RegisterPSDImage() adds properties for the PSD image format to
1467 %  the list of supported formats.  The properties include the image format
1468 %  tag, a method to read and/or write the format, whether the format
1469 %  supports the saving of more than one frame to the same file or blob,
1470 %  whether the format supports native in-memory I/O, and a brief
1471 %  description of the format.
1472 %
1473 %  The format of the RegisterPSDImage method is:
1474 %
1475 %      unsigned long RegisterPSDImage(void)
1476 %
1477 */
1478 ModuleExport unsigned long RegisterPSDImage(void)
1479 {
1480   MagickInfo
1481     *entry;
1482
1483   entry=SetMagickInfo("PSB");
1484   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
1485   entry->encoder=(EncodeImageHandler *) WritePSDImage;
1486   entry->magick=(IsImageFormatHandler *) IsPSD;
1487   entry->description=ConstantString("Adobe Large Document Format");
1488   entry->module=ConstantString("PSD");
1489   (void) RegisterMagickInfo(entry);
1490   entry=SetMagickInfo("PSD");
1491   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
1492   entry->encoder=(EncodeImageHandler *) WritePSDImage;
1493   entry->magick=(IsImageFormatHandler *) IsPSD;
1494   entry->description=ConstantString("Adobe Photoshop bitmap");
1495   entry->module=ConstantString("PSD");
1496   (void) RegisterMagickInfo(entry);
1497   return(MagickImageCoderSignature);
1498 }
1499 \f
1500 /*
1501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502 %                                                                             %
1503 %                                                                             %
1504 %                                                                             %
1505 %   U n r e g i s t e r P S D I m a g e                                       %
1506 %                                                                             %
1507 %                                                                             %
1508 %                                                                             %
1509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1510 %
1511 %  UnregisterPSDImage() removes format registrations made by the
1512 %  PSD module from the list of supported formats.
1513 %
1514 %  The format of the UnregisterPSDImage method is:
1515 %
1516 %      UnregisterPSDImage(void)
1517 %
1518 */
1519 ModuleExport void UnregisterPSDImage(void)
1520 {
1521   (void) UnregisterMagickInfo("PSB");
1522   (void) UnregisterMagickInfo("PSD");
1523 }
1524 \f
1525 /*
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 %                                                                             %
1528 %                                                                             %
1529 %                                                                             %
1530 %   W r i t e P S D I m a g e                                                 %
1531 %                                                                             %
1532 %                                                                             %
1533 %                                                                             %
1534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1535 %
1536 %  WritePSDImage() writes an image in the Adobe Photoshop encoded image
1537 %  format.
1538 %
1539 %  The format of the WritePSDImage method is:
1540 %
1541 %      MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1542 %
1543 %  A description of each parameter follows.
1544 %
1545 %    o image_info: the image info.
1546 %
1547 %    o image:  The image.
1548 %
1549 %
1550 */
1551
1552 static inline ssize_t SetPSDOffset(PSDInfo *psd_info,Image *image,
1553   const size_t offset)
1554 {
1555   if (psd_info->version == 1)
1556     return(WriteBlobMSBShort(image,offset));
1557   return(WriteBlobMSBLong(image,offset));
1558 }
1559
1560 static inline ssize_t SetPSDSize(PSDInfo *psd_info,Image *image,
1561   const MagickSizeType size)
1562 {
1563   if (psd_info->version == 1)
1564     return(WriteBlobMSBLong(image,(unsigned long) size));
1565   return(WriteBlobMSBLongLong(image,size));
1566 }
1567
1568 static size_t PSDPackbitsEncodeImage(Image *image,const size_t length,
1569   const unsigned char *pixels,unsigned char *compressed_pixels)
1570 {
1571   int
1572     count;
1573
1574   register long
1575     i,
1576     j;
1577
1578   register unsigned char
1579     *q;
1580
1581   unsigned char
1582     *packbits;
1583
1584   /*
1585     Compress pixels with Packbits encoding.
1586   */
1587   assert(image != (Image *) NULL);
1588   assert(image->signature == MagickSignature);
1589   if (image->debug != MagickFalse)
1590     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1591   assert(pixels != (unsigned char *) NULL);
1592   packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
1593   if (packbits == (unsigned char *) NULL)
1594     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1595       image->filename);
1596   q=compressed_pixels;
1597   for (i=(long) length; i != 0; )
1598   {
1599     switch (i)
1600     {
1601       case 1:
1602       {
1603         i--;
1604         *q++=(unsigned char) 0;
1605         *q++=(*pixels);
1606         break;
1607       }
1608       case 2:
1609       {
1610         i-=2;
1611         *q++=(unsigned char) 1;
1612         *q++=(*pixels);
1613         *q++=pixels[1];
1614         break;
1615       }
1616       case 3:
1617       {
1618         i-=3;
1619         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1620           {
1621             *q++=(unsigned char) ((256-3)+1);
1622             *q++=(*pixels);
1623             break;
1624           }
1625         *q++=(unsigned char) 2;
1626         *q++=(*pixels);
1627         *q++=pixels[1];
1628         *q++=pixels[2];
1629         break;
1630       }
1631       default:
1632       {
1633         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1634           {
1635             /*
1636               Packed run.
1637             */
1638             count=3;
1639             while (((long) count < i) && (*pixels == *(pixels+count)))
1640             {
1641               count++;
1642               if (count >= 127)
1643                 break;
1644             }
1645             i-=count;
1646             *q++=(unsigned char) ((256-count)+1);
1647             *q++=(*pixels);
1648             pixels+=count;
1649             break;
1650           }
1651         /*
1652           Literal run.
1653         */
1654         count=0;
1655         while ((*(pixels+count) != *(pixels+count+1)) ||
1656                (*(pixels+count+1) != *(pixels+count+2)))
1657         {
1658           packbits[count+1]=pixels[count];
1659           count++;
1660           if (((long) count >= (i-3)) || (count >= 127))
1661             break;
1662         }
1663         i-=count;
1664         *packbits=(unsigned char) (count-1);
1665         for (j=0; j <= (long) count; j++)
1666           *q++=packbits[j];
1667         pixels+=count;
1668         break;
1669       }
1670     }
1671   }
1672   *q++=(unsigned char) 128;  /* EOD marker */
1673   packbits=(unsigned char *) RelinquishMagickMemory(packbits);
1674   return(q-compressed_pixels);
1675 }
1676
1677 static void WritePackbitsLength(const ImageInfo *image_info,Image *image,
1678   Image *tmp_image,unsigned char *pixels,unsigned char *compressed_pixels,
1679   const QuantumType quantum_type)
1680 {
1681   int
1682     y;
1683
1684   QuantumInfo
1685     *quantum_info;
1686
1687   register const PixelPacket
1688     *p;
1689
1690   size_t
1691     length,
1692     packet_size;
1693
1694   if (tmp_image->depth > 8)
1695     tmp_image->depth=16;
1696   packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1697   quantum_info=AcquireQuantumInfo(image_info,image);
1698   for (y=0; y < (long) tmp_image->rows; y++)
1699   {
1700     p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception);
1701     if (p == (const PixelPacket *) NULL)
1702       break;
1703     length=ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info,
1704       quantum_type,pixels,&image->exception);
1705     length=PSDPackbitsEncodeImage(image,length,pixels,compressed_pixels);
1706     (void) WriteBlobMSBShort(image,length);
1707   }
1708   quantum_info=DestroyQuantumInfo(quantum_info);
1709 }
1710
1711 static void WriteOneChannel(const ImageInfo *image_info,Image *image,
1712   Image *tmp_image,unsigned char *pixels,unsigned char *compressed_pixels,
1713   const QuantumType quantum_type,const MagickBooleanType compression_flag)
1714 {
1715   int
1716     y;
1717
1718   QuantumInfo
1719     *quantum_info;
1720
1721   register const PixelPacket
1722     *p;
1723
1724   size_t
1725     length,
1726     packet_size;
1727
1728   if ((compression_flag != MagickFalse) &&
1729       (image->compression == NoCompression))
1730     (void) WriteBlobMSBShort(image,0);
1731   if (tmp_image->depth > 8)
1732     tmp_image->depth=16;
1733   packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1734   quantum_info=AcquireQuantumInfo(image_info,image);
1735   for (y=0; y < (long) tmp_image->rows; y++)
1736   {
1737     p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception);
1738     if (p == (const PixelPacket *) NULL)
1739       break;
1740     length=ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info,
1741       quantum_type,pixels,&image->exception);
1742     if (image->compression == NoCompression)
1743       (void) WriteBlob(image,length,pixels);
1744     else
1745       {
1746         length=PSDPackbitsEncodeImage(image,length,pixels,compressed_pixels);
1747         (void) WriteBlob(image,length,compressed_pixels);
1748       }
1749   }
1750   quantum_info=DestroyQuantumInfo(quantum_info);
1751 }
1752
1753 static MagickBooleanType WriteImageChannels(const ImageInfo *image_info,
1754   Image *image,Image *tmp_image,const MagickBooleanType separate)
1755 {
1756   int
1757     i;
1758
1759   size_t
1760     channels,
1761     packet_size;
1762
1763   unsigned char
1764     *compressed_pixels,
1765     *pixels;
1766
1767   /*
1768     Write uncompressed pixel datas separate planes.
1769   */
1770   channels=1;
1771   if ((tmp_image->storage_class == PseudoClass) &&
1772       (tmp_image->matte == MagickFalse))
1773     channels++;
1774   packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1775   pixels=(unsigned char *) AcquireQuantumMemory(channels*tmp_image->columns,
1776     packet_size*sizeof(*pixels));
1777   compressed_pixels=(unsigned char *) AcquireQuantumMemory(2*channels*
1778     tmp_image->columns,packet_size*sizeof(*pixels));
1779   if ((pixels == (unsigned char *) NULL) ||
1780       (compressed_pixels == (unsigned char *) NULL))
1781     {
1782       if (pixels != (unsigned char *) NULL)
1783         pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1784       if (compressed_pixels != (unsigned char *) NULL)
1785         compressed_pixels=(unsigned char *)
1786           RelinquishMagickMemory(compressed_pixels);
1787       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1788     }
1789   i=0;
1790   if (tmp_image->storage_class == PseudoClass)
1791     {
1792       if (image->compression != NoCompression)
1793         {
1794           /*
1795             Packbits compression.
1796           */
1797           (void) WriteBlobMSBShort(image,1);
1798           if (tmp_image->matte == MagickFalse)
1799             WritePackbitsLength(image_info,image,tmp_image,pixels,
1800               compressed_pixels,IndexQuantum);
1801           else
1802             WritePackbitsLength(image_info,image,tmp_image,pixels,
1803               compressed_pixels,IndexAlphaQuantum);
1804         }
1805       if (tmp_image->matte == MagickFalse)
1806         WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1807           IndexQuantum,(i++ == 0) || (separate != MagickFalse) ?
1808           MagickTrue : MagickFalse);
1809       else
1810         WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1811           IndexAlphaQuantum,(i++ == 0) || (separate != MagickFalse) ?
1812           MagickTrue : MagickFalse);
1813       (void) SetImageProgress(image,SaveImagesTag,0,1);
1814     }
1815   else
1816     {
1817       if (tmp_image->colorspace == CMYKColorspace)
1818         (void) NegateImage(image,MagickFalse);
1819       if (image->compression != NoCompression)
1820         {
1821           /*
1822             Packbits compression.
1823           */
1824           (void) WriteBlobMSBShort(image,1);
1825           if (tmp_image->matte != MagickFalse)
1826             WritePackbitsLength(image_info,image,tmp_image,pixels,
1827               compressed_pixels,AlphaQuantum);
1828           WritePackbitsLength(image_info,image,tmp_image,pixels,
1829             compressed_pixels,RedQuantum);
1830           WritePackbitsLength(image_info,image,tmp_image,pixels,
1831             compressed_pixels,GreenQuantum);
1832           WritePackbitsLength(image_info,image,tmp_image,pixels,
1833             compressed_pixels,BlueQuantum);
1834           if (tmp_image->colorspace == CMYKColorspace)
1835             WritePackbitsLength(image_info,image,tmp_image,pixels,
1836               compressed_pixels,BlackQuantum);
1837         }
1838       (void) SetImageProgress(image,SaveImagesTag,0,6);
1839       if (tmp_image->matte != MagickFalse)
1840         WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1841           AlphaQuantum,(i++ == 0) || (separate != MagickFalse) ?
1842           MagickTrue : MagickFalse);
1843       (void) SetImageProgress(image,SaveImagesTag,1,6);
1844       WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1845         RedQuantum,(i++ == 0) || (separate != MagickFalse) ?
1846         MagickTrue : MagickFalse);
1847       (void) SetImageProgress(image,SaveImagesTag,2,6);
1848       WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1849         GreenQuantum,(i++ == 0) || (separate != MagickFalse) ?
1850         MagickTrue : MagickFalse);
1851       (void) SetImageProgress(image,SaveImagesTag,3,6);
1852       WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1853         BlueQuantum,(i++ == 0) || (separate != MagickFalse) ?
1854         MagickTrue : MagickFalse);
1855       (void) SetImageProgress(image,SaveImagesTag,4,6);
1856       if (tmp_image->colorspace == CMYKColorspace)
1857         {
1858           WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1859             BlackQuantum,(i++ == 0) || (separate != MagickFalse) ?
1860             MagickTrue : MagickFalse);
1861           (void) NegateImage(image,MagickFalse);
1862         }
1863       (void) SetImageProgress(image,SaveImagesTag,5,6);
1864     }
1865   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1866   return(MagickTrue);
1867 }
1868
1869 /* Write white background, RLE-compressed */
1870
1871 static void WriteWhiteBackground( Image* image )
1872 {
1873   long       w8, w;
1874   char       *d, scanline[256];
1875
1876   int numChannels = 3, dim = (int) (image->rows*numChannels);
1877
1878   register long
1879     i;
1880
1881   size_t
1882     length;
1883
1884   unsigned short
1885     bytecount;
1886
1887   (void) WriteBlobMSBShort(image,1); /* RLE compressed */
1888   w8 = (long) image->columns;
1889   d = scanline;
1890   /* Set up scanline */
1891   for (w=w8; w > 128; w-=128)
1892   {
1893     *d++=(-127);
1894     *d++=(char) 255;
1895   }
1896   switch (w)
1897   {
1898     case 0:
1899       break;
1900     case 1:
1901       *d++=0;
1902       *d++=(char) 255;
1903       break;
1904     default:
1905       *d++=(char) (1-w);
1906       *d++=(char) 255;
1907       break;
1908   }
1909   bytecount = d - scanline;
1910
1911   /* Scanline counts (rows*channels) */
1912   for (i=0; i < dim; i++)
1913   {
1914     (void) WriteBlobMSBShort(image,bytecount);
1915   }
1916
1917   /* RLE compressed data  */
1918   length = bytecount;
1919   for (i=0; i < dim; i++)
1920   {
1921     (void) WriteBlob( image, length, (unsigned char *) scanline );
1922   }
1923
1924 }
1925
1926 static void WritePascalString(Image* inImage,const char *inString,int inPad)
1927 {
1928   size_t
1929     strLength;
1930   int i;
1931
1932   /* max length is 255 */
1933
1934   strLength = (strlen(inString) > 255UL ) ? 255UL : strlen(inString);
1935
1936   if ( strLength !=  0 )
1937   {
1938   (void) WriteBlobByte(inImage,(unsigned char) strLength);
1939   (void) WriteBlob(inImage, strLength, (const unsigned char *) inString);
1940   }
1941   else
1942   (void) WriteBlobByte(inImage, 0);
1943
1944   strLength ++;
1945
1946   if ( (strLength % inPad) == 0 )
1947     return;
1948   for (i=0; i < (long) (inPad-(strLength % inPad)); i++)
1949     (void) WriteBlobByte(inImage,0);
1950 }
1951
1952 static void WriteResolutionResourceBlock(Image *image)
1953 {
1954   unsigned long
1955      x_resolution,
1956      y_resolution;
1957
1958   unsigned short
1959     units;
1960
1961   x_resolution=65536.0*image->x_resolution+0.5;
1962   y_resolution=65536.0*image->y_resolution+0.5;
1963   units=1;
1964   if (image->units == PixelsPerCentimeterResolution)
1965     {
1966       x_resolution=2.54*65536.0*image->x_resolution*0.5;
1967       y_resolution=2.54*65536.0*image->y_resolution+0.5;
1968       units=2;
1969     }
1970   (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
1971   (void) WriteBlobMSBShort(image,0x03ED);
1972   (void) WriteBlobMSBShort(image,0);
1973   (void) WriteBlobMSBLong(image,16); /* resource size */
1974   (void) WriteBlobMSBLong(image,x_resolution);
1975   (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
1976   (void) WriteBlobMSBShort(image,units); /* width unit */
1977   (void) WriteBlobMSBLong(image,y_resolution);
1978   (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
1979   (void) WriteBlobMSBShort(image,units); /* height unit */
1980 }
1981
1982 static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1983 {
1984   const char
1985     *theAttr;
1986
1987   const StringInfo
1988     *profile;
1989
1990   MagickBooleanType
1991     force_white_background = image->matte,
1992     invert_layer_count = MagickFalse,
1993     status;
1994
1995   register long
1996     i;
1997
1998   size_t
1999     num_channels,
2000     packet_size;
2001
2002   unsigned char
2003     layer_name[4];
2004
2005   unsigned long
2006     channel_size,
2007     channelLength,
2008     layer_count,
2009     layer_info_size,
2010     rounded_layer_info_size,
2011     res_extra;
2012
2013   Image
2014     * tmp_image = (Image *) NULL,
2015     * base_image = force_white_background ? image : GetNextImageInList(image);
2016
2017   /*
2018     Open output image file.
2019   */
2020   assert(image_info != (const ImageInfo *) NULL);
2021   assert(image_info->signature == MagickSignature);
2022   assert(image != (Image *) NULL);
2023   assert(image->signature == MagickSignature);
2024   if (image->debug != MagickFalse)
2025     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2026   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
2027   if (status == MagickFalse)
2028     return(status);
2029   packet_size=(size_t) (image->depth > 8 ? 6 : 3);
2030   if (image->matte != MagickFalse)
2031     packet_size+=image->depth > 8 ? 2 : 1;
2032   (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
2033   (void) WriteBlobMSBShort(image,1);  /* version */
2034   for ( i=1; i<=6; i++)
2035   (void) WriteBlobByte(image, 0);  /* 6 bytes of reserved */
2036   if ( force_white_background )
2037     num_channels = 3;
2038   else
2039   {
2040     if (image->storage_class == PseudoClass)
2041      num_channels=(image->matte ? 2UL : 1UL);
2042     else
2043     {
2044     if (image->colorspace != CMYKColorspace)
2045       num_channels=(image->matte ? 4UL : 3UL);
2046     else
2047       num_channels=(image->matte ? 5UL : 4UL);
2048     }
2049   }
2050   (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
2051   (void) WriteBlobMSBLong(image,image->rows);
2052   (void) WriteBlobMSBLong(image,image->columns);
2053   (void) WriteBlobMSBShort(image,(unsigned short)
2054     (image->storage_class == PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
2055   if (((image->colorspace != UndefinedColorspace) ||
2056        (image->colorspace != CMYKColorspace)) &&
2057        (image->colorspace != CMYKColorspace))
2058     {
2059       if (image->colorspace != RGBColorspace)
2060         (void) TransformImageColorspace(image,RGBColorspace);
2061       (void) WriteBlobMSBShort(image,(unsigned short)
2062         (image->storage_class == PseudoClass ? 2 : 3));
2063     }
2064   else
2065     {
2066       if (image->colorspace != RGBColorspace)
2067         (void) TransformImageColorspace(image,CMYKColorspace);
2068       (void) WriteBlobMSBShort(image,4);
2069     }
2070   if ((image->storage_class == DirectClass) || (image->colors > 256))
2071     (void) WriteBlobMSBLong(image,0);
2072   else
2073     {
2074       /*
2075         Write PSD raster colormap.
2076       */
2077       (void) WriteBlobMSBLong(image,768);
2078       for (i=0; i < (long) image->colors; i++)
2079         (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
2080       for ( ; i < 256; i++)
2081         (void) WriteBlobByte(image,0);
2082       for (i=0; i < (long) image->colors; i++)
2083         (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].green));
2084       for ( ; i < 256; i++)
2085         (void) WriteBlobByte(image,0);
2086       for (i=0; i < (long) image->colors; i++)
2087         (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
2088       for ( ; i < 256; i++)
2089         (void) WriteBlobByte(image,0);
2090     }
2091   /*
2092     Image resource block.
2093   */
2094   res_extra = 28; /* 0x03EB */
2095   profile=GetImageProfile(image,"8bim");
2096   if (profile == (StringInfo *) NULL)
2097     WriteBlobMSBLong(image, res_extra);
2098   else
2099     {
2100       (void) WriteBlobMSBLong(image,(unsigned long) res_extra +
2101         GetStringInfoLength(profile));
2102       (void) WriteBlob(image,GetStringInfoLength(profile),GetStringInfoDatum(
2103         profile));
2104     }
2105   WriteResolutionResourceBlock(image);
2106
2107 compute_layer_info:
2108   layer_count = 0;
2109   layer_info_size = 2;
2110   tmp_image = base_image;
2111   while ( tmp_image != NULL ) {
2112     packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
2113
2114     if (tmp_image->storage_class == PseudoClass)
2115      num_channels = (tmp_image->matte != MagickFalse ? 2UL : 1UL);
2116     else
2117     if (tmp_image->colorspace != CMYKColorspace)
2118       num_channels = (tmp_image->matte != MagickFalse ? 4UL : 3UL);
2119     else
2120       num_channels = (tmp_image->matte != MagickFalse ? 5UL : 4UL);
2121
2122     channelLength=(unsigned long) (tmp_image->columns * tmp_image->rows *
2123       packet_size + 2);
2124     layer_info_size += (unsigned long) (4*4 + 2 + num_channels * 6 + 4 + 4 +
2125       4 * 1 + 4 + 12 + num_channels * channelLength);
2126     layer_count++;
2127     tmp_image = GetNextImageInList(tmp_image);
2128   }
2129
2130   /* if the image has a matte, then we need to use layers */
2131   if ( layer_count == 0 && image->matte == MagickTrue )
2132   {
2133   invert_layer_count = MagickTrue;
2134   base_image = image;
2135   goto compute_layer_info;  /* yes, goto's suck, but it keeps the code cleaner! */
2136   }
2137
2138   if ( layer_count == 0 )
2139     (void) WriteBlobMSBLong(image, 0);
2140   else
2141   {
2142     (void) WriteBlobMSBLong(image,layer_info_size+4+4);
2143     if ( layer_info_size/2 != (layer_info_size+1)/2 ) /* odd */
2144       rounded_layer_info_size = layer_info_size + 1;
2145     else
2146       rounded_layer_info_size = layer_info_size;
2147     (void) WriteBlobMSBLong(image,rounded_layer_info_size);
2148
2149     if ( invert_layer_count )
2150       layer_count *= -1;  /* if we have a matte, then use negative count! */
2151     (void) WriteBlobMSBShort(image,(unsigned short) layer_count);
2152
2153     layer_count = 1;
2154     tmp_image = base_image;
2155     while ( tmp_image != NULL ) {
2156       (void) WriteBlobMSBLong(image,0);
2157       (void) WriteBlobMSBLong(image,0);
2158       (void) WriteBlobMSBLong(image,tmp_image->rows);
2159       (void) WriteBlobMSBLong(image,tmp_image->columns);
2160
2161       packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
2162       channel_size=(unsigned int) ((packet_size*tmp_image->rows*
2163         tmp_image->columns)+2);
2164       if (tmp_image->storage_class == PseudoClass) {
2165        (void) WriteBlobMSBShort(image,(unsigned short)
2166          (tmp_image->matte ? 2 : 1));
2167        if (tmp_image->matte) {
2168          (void) WriteBlobMSBShort(image,(unsigned short) -1);
2169          (void) WriteBlobMSBLong(image,channel_size);
2170        }
2171        (void) WriteBlobMSBShort(image, 0);
2172        (void) WriteBlobMSBLong(image, channel_size);
2173       } else
2174       if (tmp_image->colorspace != CMYKColorspace)
2175       {
2176         (void) WriteBlobMSBShort(image,(unsigned short)
2177           (tmp_image->matte ? 4 : 3));
2178        if (tmp_image->matte) {
2179          (void) WriteBlobMSBShort(image,(unsigned short) -1);
2180          (void) WriteBlobMSBLong(image,channel_size);
2181        }
2182        (void) WriteBlobMSBShort(image, 0);
2183        (void) WriteBlobMSBLong(image, channel_size);
2184        (void) WriteBlobMSBShort(image, 1);
2185        (void) WriteBlobMSBLong(image, channel_size);
2186        (void) WriteBlobMSBShort(image, 2);
2187        (void) WriteBlobMSBLong(image, channel_size);
2188       }
2189       else
2190       {
2191         (void) WriteBlobMSBShort(image,(unsigned short)
2192           (tmp_image->matte ? 5 : 4));
2193        if (tmp_image->matte) {
2194          (void) WriteBlobMSBShort(image,(unsigned short) -1);
2195          (void) WriteBlobMSBLong(image,channel_size);
2196        }
2197        (void) WriteBlobMSBShort(image, 0);
2198        (void) WriteBlobMSBLong(image, channel_size);
2199        (void) WriteBlobMSBShort(image, 1);
2200        (void) WriteBlobMSBLong(image, channel_size);
2201        (void) WriteBlobMSBShort(image, 2);
2202        (void) WriteBlobMSBLong(image, channel_size);
2203        (void) WriteBlobMSBShort(image, 3);
2204        (void) WriteBlobMSBLong(image, channel_size);
2205       }
2206
2207       (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
2208       (void) WriteBlob(image,4,(const unsigned char *)
2209         CompositeOperatorToPSDBlendMode(tmp_image->compose));
2210       (void) WriteBlobByte(image, 255); /* BOGUS: layer opacity */
2211       (void) WriteBlobByte(image, 0);
2212       (void) WriteBlobByte(image, 1); /* BOGUS: layer attributes - visible, etc. */
2213       (void) WriteBlobByte(image, 0);
2214
2215       (void) WriteBlobMSBLong(image, 12);
2216       (void) WriteBlobMSBLong(image, 0);
2217       (void) WriteBlobMSBLong(image, 0);
2218
2219       theAttr=(const char *) GetImageProperty(tmp_image,"label");
2220       if (theAttr) {
2221         WritePascalString( image, theAttr, 4 );
2222         /*
2223         sprintf((char *) &(layer_name[1]), "%4s", theAttr->value );
2224         (void) WriteBlobByte(image, 3);
2225         (void) WriteBlob(image, 3, &layer_name[1]);
2226         */
2227       } else {
2228         (void) FormatMagickString((char *) layer_name,MaxTextExtent,"L%02ld",
2229           layer_count++ );
2230         WritePascalString( image, (char*)layer_name, 4 );
2231       }
2232       tmp_image = GetNextImageInList(tmp_image);
2233     };
2234
2235      /* now the image data! */
2236     tmp_image = base_image;
2237     while ( tmp_image != NULL ) {
2238       status=WriteImageChannels(image_info,image,tmp_image,MagickTrue);
2239
2240       /* add in the pad! */
2241        if ( rounded_layer_info_size != layer_info_size )
2242          (void) WriteBlobByte(image,'\0');
2243
2244       tmp_image = GetNextImageInList(tmp_image);
2245     };
2246
2247     /* user mask data */
2248      (void) WriteBlobMSBLong(image, 0);
2249
2250   }
2251
2252    /* now the background image data! */
2253    if (force_white_background != MagickFalse)
2254      WriteWhiteBackground(image);
2255    else
2256      status=WriteImageChannels(image_info,image,image,MagickFalse);
2257
2258   (void) CloseBlob(image);
2259   return(status);
2260 }