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