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