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