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