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