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