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