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