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