Home | History | Annotate | Download | only in coders
      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 %                                   Cristy                                    %
     17 %                              Leonard Rosenthol                              %
     18 %                                 July 1992                                   %
     19 %                                Dirk Lemstra                                 %
     20 %                                December 2013                                %
     21 %                                                                             %
     22 %                                                                             %
     23 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     24 %  dedicated to making software imaging solutions freely available.           %
     25 %                                                                             %
     26 %  You may not use this file except in compliance with the License.  You may  %
     27 %  obtain a copy of the License at                                            %
     28 %                                                                             %
     29 %    http://www.imagemagick.org/script/license.php                            %
     30 %                                                                             %
     31 %  Unless required by applicable law or agreed to in writing, software        %
     32 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     33 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     34 %  See the License for the specific language governing permissions and        %
     35 %  limitations under the License.                                             %
     36 %                                                                             %
     37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     38 %
     39 %
     40 */
     41 
     42 /*
     44   Include declarations.
     45 */
     46 #include "MagickCore/studio.h"
     47 #include "MagickCore/artifact.h"
     48 #include "MagickCore/attribute.h"
     49 #include "MagickCore/blob.h"
     50 #include "MagickCore/blob-private.h"
     51 #include "MagickCore/cache.h"
     52 #include "MagickCore/channel.h"
     53 #include "MagickCore/colormap.h"
     54 #include "MagickCore/colormap-private.h"
     55 #include "MagickCore/colorspace.h"
     56 #include "MagickCore/colorspace-private.h"
     57 #include "MagickCore/constitute.h"
     58 #include "MagickCore/enhance.h"
     59 #include "MagickCore/exception.h"
     60 #include "MagickCore/exception-private.h"
     61 #include "MagickCore/image.h"
     62 #include "MagickCore/image-private.h"
     63 #include "MagickCore/list.h"
     64 #include "MagickCore/log.h"
     65 #include "MagickCore/magick.h"
     66 #include "MagickCore/memory_.h"
     67 #include "MagickCore/module.h"
     68 #include "MagickCore/monitor-private.h"
     69 #include "MagickCore/option.h"
     70 #include "MagickCore/pixel.h"
     71 #include "MagickCore/pixel-accessor.h"
     72 #include "MagickCore/profile.h"
     73 #include "MagickCore/property.h"
     74 #include "MagickCore/quantum-private.h"
     75 #include "MagickCore/static.h"
     76 #include "MagickCore/string_.h"
     77 #include "MagickCore/thread-private.h"
     78 #ifdef MAGICKCORE_ZLIB_DELEGATE
     79 #include <zlib.h>
     80 #endif
     81 #include "psd-private.h"
     82 
     83 /*
     84   Define declaractions.
     85 */
     86 #define MaxPSDChannels  56
     87 #define PSDQuantum(x) (((ssize_t) (x)+1) & -2)
     88 
     89 /*
     91   Enumerated declaractions.
     92 */
     93 typedef enum
     94 {
     95   Raw = 0,
     96   RLE = 1,
     97   ZipWithoutPrediction = 2,
     98   ZipWithPrediction = 3
     99 } PSDCompressionType;
    100 
    101 typedef enum
    102 {
    103   BitmapMode = 0,
    104   GrayscaleMode = 1,
    105   IndexedMode = 2,
    106   RGBMode = 3,
    107   CMYKMode = 4,
    108   MultichannelMode = 7,
    109   DuotoneMode = 8,
    110   LabMode = 9
    111 } PSDImageType;
    112 
    113 /*
    115   Typedef declaractions.
    116 */
    117 typedef struct _ChannelInfo
    118 {
    119   short int
    120     type;
    121 
    122   size_t
    123     size;
    124 } ChannelInfo;
    125 
    126 typedef struct _MaskInfo
    127 {
    128   Image
    129     *image;
    130 
    131   RectangleInfo
    132     page;
    133 
    134   unsigned char
    135     background,
    136     flags;
    137 } MaskInfo;
    138 
    139 typedef struct _LayerInfo
    140 {
    141   ChannelInfo
    142     channel_info[MaxPSDChannels];
    143 
    144   char
    145     blendkey[4];
    146 
    147   Image
    148     *image;
    149 
    150   MaskInfo
    151     mask;
    152 
    153   Quantum
    154     opacity;
    155 
    156   RectangleInfo
    157     page;
    158 
    159   size_t
    160     offset_x,
    161     offset_y;
    162 
    163   unsigned char
    164     clipping,
    165     flags,
    166     name[256],
    167     visible;
    168 
    169   unsigned short
    170     channels;
    171 } LayerInfo;
    172 
    173 /*
    174   Forward declarations.
    175 */
    176 static MagickBooleanType
    177   WritePSDImage(const ImageInfo *,Image *,ExceptionInfo *);
    178 
    179 /*
    181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    182 %                                                                             %
    183 %                                                                             %
    184 %                                                                             %
    185 %   I s P S D                                                                 %
    186 %                                                                             %
    187 %                                                                             %
    188 %                                                                             %
    189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    190 %
    191 %  IsPSD()() returns MagickTrue if the image format type, identified by the
    192 %  magick string, is PSD.
    193 %
    194 %  The format of the IsPSD method is:
    195 %
    196 %      MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
    197 %
    198 %  A description of each parameter follows:
    199 %
    200 %    o magick: compare image format pattern against these bytes.
    201 %
    202 %    o length: Specifies the length of the magick string.
    203 %
    204 */
    205 static MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
    206 {
    207   if (length < 4)
    208     return(MagickFalse);
    209   if (LocaleNCompare((const char *) magick,"8BPS",4) == 0)
    210     return(MagickTrue);
    211   return(MagickFalse);
    212 }
    213 
    214 /*
    216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    217 %                                                                             %
    218 %                                                                             %
    219 %                                                                             %
    220 %   R e a d P S D I m a g e                                                   %
    221 %                                                                             %
    222 %                                                                             %
    223 %                                                                             %
    224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    225 %
    226 %  ReadPSDImage() reads an Adobe Photoshop image file and returns it.  It
    227 %  allocates the memory necessary for the new Image structure and returns a
    228 %  pointer to the new image.
    229 %
    230 %  The format of the ReadPSDImage method is:
    231 %
    232 %      Image *ReadPSDImage(image_info,ExceptionInfo *exception)
    233 %
    234 %  A description of each parameter follows:
    235 %
    236 %    o image_info: the image info.
    237 %
    238 %    o exception: return any errors or warnings in this structure.
    239 %
    240 */
    241 
    242 static const char *CompositeOperatorToPSDBlendMode(CompositeOperator op)
    243 {
    244   const char
    245     *blend_mode;
    246 
    247   switch (op)
    248   {
    249     case ColorBurnCompositeOp:  blend_mode = "idiv";  break;
    250     case ColorDodgeCompositeOp: blend_mode = "div ";  break;
    251     case ColorizeCompositeOp:   blend_mode = "colr";  break;
    252     case DarkenCompositeOp:     blend_mode = "dark";  break;
    253     case DifferenceCompositeOp: blend_mode = "diff";  break;
    254     case DissolveCompositeOp:   blend_mode = "diss";  break;
    255     case ExclusionCompositeOp:  blend_mode = "smud";  break;
    256     case HardLightCompositeOp:  blend_mode = "hLit";  break;
    257     case HardMixCompositeOp:    blend_mode = "hMix";  break;
    258     case HueCompositeOp:        blend_mode = "hue ";  break;
    259     case LightenCompositeOp:    blend_mode = "lite";  break;
    260     case LinearBurnCompositeOp: blend_mode = "lbrn";  break;
    261     case LinearDodgeCompositeOp:blend_mode = "lddg";  break;
    262     case LinearLightCompositeOp:blend_mode = "lLit";  break;
    263     case LuminizeCompositeOp:   blend_mode = "lum ";  break;
    264     case MultiplyCompositeOp:   blend_mode = "mul ";  break;
    265     case OverCompositeOp:       blend_mode = "norm";  break;
    266     case OverlayCompositeOp:    blend_mode = "over";  break;
    267     case PinLightCompositeOp:   blend_mode = "pLit";  break;
    268     case SaturateCompositeOp:   blend_mode = "sat ";  break;
    269     case ScreenCompositeOp:     blend_mode = "scrn";  break;
    270     case SoftLightCompositeOp:  blend_mode = "sLit";  break;
    271     case VividLightCompositeOp: blend_mode = "vLit";  break;
    272     default:                    blend_mode = "norm";
    273   }
    274   return(blend_mode);
    275 }
    276 
    277 /*
    278   For some reason Photoshop seems to blend semi-transparent pixels with white.
    279   This method reverts the blending. This can be disabled by setting the
    280   option 'psd:alpha-unblend' to off.
    281 */
    282 static MagickBooleanType CorrectPSDAlphaBlend(const ImageInfo *image_info,
    283   Image *image,ExceptionInfo* exception)
    284 {
    285   const char
    286     *option;
    287 
    288   MagickBooleanType
    289     status;
    290 
    291   ssize_t
    292     y;
    293 
    294   if (image->alpha_trait != BlendPixelTrait || image->colorspace != sRGBColorspace)
    295     return(MagickTrue);
    296   option=GetImageOption(image_info,"psd:alpha-unblend");
    297   if (IsStringFalse(option) != MagickFalse)
    298     return(MagickTrue);
    299   status=MagickTrue;
    300 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    301 #pragma omp parallel for schedule(static,4) shared(status) \
    302   magick_threads(image,image,image->rows,1)
    303 #endif
    304   for (y=0; y < (ssize_t) image->rows; y++)
    305   {
    306     register Quantum
    307       *magick_restrict q;
    308 
    309     register ssize_t
    310       x;
    311 
    312     if (status == MagickFalse)
    313       continue;
    314     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    315     if (q == (Quantum *) NULL)
    316     {
    317       status=MagickFalse;
    318       continue;
    319     }
    320     for (x=0; x < (ssize_t) image->columns; x++)
    321     {
    322       double
    323         gamma;
    324 
    325       register ssize_t
    326         i;
    327 
    328       gamma=QuantumScale*GetPixelAlpha(image, q);
    329       if (gamma != 0.0 && gamma != 1.0)
    330         {
    331           for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
    332           {
    333             PixelChannel channel=GetPixelChannelChannel(image,i);
    334             if (channel != AlphaPixelChannel)
    335               q[i]=ClampToQuantum((q[i]-((1.0-gamma)*QuantumRange))/gamma);
    336           }
    337         }
    338       q+=GetPixelChannels(image);
    339     }
    340     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    341       status=MagickFalse;
    342   }
    343 
    344   return(status);
    345 }
    346 
    347 static inline CompressionType ConvertPSDCompression(
    348   PSDCompressionType compression)
    349 {
    350   switch (compression)
    351   {
    352     case RLE:
    353       return RLECompression;
    354     case ZipWithPrediction:
    355     case ZipWithoutPrediction:
    356       return ZipCompression;
    357     default:
    358       return NoCompression;
    359   }
    360 }
    361 
    362 static MagickBooleanType CorrectPSDOpacity(LayerInfo *layer_info,
    363   ExceptionInfo *exception)
    364 {
    365   MagickBooleanType
    366     status;
    367 
    368   ssize_t
    369     y;
    370 
    371   if (layer_info->opacity == OpaqueAlpha)
    372     return(MagickTrue);
    373 
    374   layer_info->image->alpha_trait=BlendPixelTrait;
    375   status=MagickTrue;
    376 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    377 #pragma omp parallel for schedule(static,4) shared(status) \
    378   magick_threads(layer_info->image,layer_info->image,layer_info->image->rows,1)
    379 #endif
    380   for (y=0; y < (ssize_t) layer_info->image->rows; y++)
    381   {
    382     register Quantum
    383       *magick_restrict q;
    384 
    385     register ssize_t
    386       x;
    387 
    388     if (status == MagickFalse)
    389       continue;
    390     q=GetAuthenticPixels(layer_info->image,0,y,layer_info->image->columns,1,
    391       exception);
    392     if (q == (Quantum *)NULL)
    393       {
    394         status=MagickFalse;
    395         continue;
    396       }
    397     for (x=0; x < (ssize_t) layer_info->image->columns; x++)
    398     {
    399       SetPixelAlpha(layer_info->image,(Quantum) (QuantumScale*(GetPixelAlpha(
    400         layer_info->image,q))*layer_info->opacity),q);
    401       q+=GetPixelChannels(layer_info->image);
    402     }
    403     if (SyncAuthenticPixels(layer_info->image,exception) == MagickFalse)
    404       status=MagickFalse;
    405   }
    406 
    407   return(status);
    408 }
    409 
    410 static ssize_t DecodePSDPixels(const size_t number_compact_pixels,
    411   const unsigned char *compact_pixels,const ssize_t depth,
    412   const size_t number_pixels,unsigned char *pixels)
    413 {
    414 #define CheckNumberCompactPixels \
    415   if (packets == 0) \
    416     return(i); \
    417   packets--
    418 
    419 #define CheckNumberPixels(count) \
    420   if (((ssize_t) i + count) > (ssize_t) number_pixels) \
    421     return(i); \
    422   i+=count
    423 
    424   int
    425     pixel;
    426 
    427   register ssize_t
    428     i,
    429     j;
    430 
    431   size_t
    432     length;
    433 
    434   ssize_t
    435     packets;
    436 
    437   packets=(ssize_t) number_compact_pixels;
    438   for (i=0; (packets > 1) && (i < (ssize_t) number_pixels); )
    439   {
    440     packets--;
    441     length=(size_t) (*compact_pixels++);
    442     if (length == 128)
    443       continue;
    444     if (length > 128)
    445       {
    446         length=256-length+1;
    447         CheckNumberCompactPixels;
    448         pixel=(*compact_pixels++);
    449         for (j=0; j < (ssize_t) length; j++)
    450         {
    451           switch (depth)
    452           {
    453             case 1:
    454             {
    455               CheckNumberPixels(8);
    456               *pixels++=(pixel >> 7) & 0x01 ? 0U : 255U;
    457               *pixels++=(pixel >> 6) & 0x01 ? 0U : 255U;
    458               *pixels++=(pixel >> 5) & 0x01 ? 0U : 255U;
    459               *pixels++=(pixel >> 4) & 0x01 ? 0U : 255U;
    460               *pixels++=(pixel >> 3) & 0x01 ? 0U : 255U;
    461               *pixels++=(pixel >> 2) & 0x01 ? 0U : 255U;
    462               *pixels++=(pixel >> 1) & 0x01 ? 0U : 255U;
    463               *pixels++=(pixel >> 0) & 0x01 ? 0U : 255U;
    464               break;
    465             }
    466             case 2:
    467             {
    468               CheckNumberPixels(4);
    469               *pixels++=(unsigned char) ((pixel >> 6) & 0x03);
    470               *pixels++=(unsigned char) ((pixel >> 4) & 0x03);
    471               *pixels++=(unsigned char) ((pixel >> 2) & 0x03);
    472               *pixels++=(unsigned char) ((pixel & 0x03) & 0x03);
    473               break;
    474             }
    475             case 4:
    476             {
    477               CheckNumberPixels(2);
    478               *pixels++=(unsigned char) ((pixel >> 4) & 0xff);
    479               *pixels++=(unsigned char) ((pixel & 0x0f) & 0xff);
    480               break;
    481             }
    482             default:
    483             {
    484               CheckNumberPixels(1);
    485               *pixels++=(unsigned char) pixel;
    486               break;
    487             }
    488           }
    489         }
    490         continue;
    491       }
    492     length++;
    493     for (j=0; j < (ssize_t) length; j++)
    494     {
    495       CheckNumberCompactPixels;
    496       switch (depth)
    497       {
    498         case 1:
    499         {
    500           CheckNumberPixels(8);
    501           *pixels++=(*compact_pixels >> 7) & 0x01 ? 0U : 255U;
    502           *pixels++=(*compact_pixels >> 6) & 0x01 ? 0U : 255U;
    503           *pixels++=(*compact_pixels >> 5) & 0x01 ? 0U : 255U;
    504           *pixels++=(*compact_pixels >> 4) & 0x01 ? 0U : 255U;
    505           *pixels++=(*compact_pixels >> 3) & 0x01 ? 0U : 255U;
    506           *pixels++=(*compact_pixels >> 2) & 0x01 ? 0U : 255U;
    507           *pixels++=(*compact_pixels >> 1) & 0x01 ? 0U : 255U;
    508           *pixels++=(*compact_pixels >> 0) & 0x01 ? 0U : 255U;
    509           break;
    510         }
    511         case 2:
    512         {
    513           CheckNumberPixels(4);
    514           *pixels++=(*compact_pixels >> 6) & 0x03;
    515           *pixels++=(*compact_pixels >> 4) & 0x03;
    516           *pixels++=(*compact_pixels >> 2) & 0x03;
    517           *pixels++=(*compact_pixels & 0x03) & 0x03;
    518           break;
    519         }
    520         case 4:
    521         {
    522           CheckNumberPixels(2);
    523           *pixels++=(*compact_pixels >> 4) & 0xff;
    524           *pixels++=(*compact_pixels & 0x0f) & 0xff;
    525           break;
    526         }
    527         default:
    528         {
    529           CheckNumberPixels(1);
    530           *pixels++=(*compact_pixels);
    531           break;
    532         }
    533       }
    534       compact_pixels++;
    535     }
    536   }
    537   return(i);
    538 }
    539 
    540 static inline LayerInfo *DestroyLayerInfo(LayerInfo *layer_info,
    541   const ssize_t number_layers)
    542 {
    543   ssize_t
    544     i;
    545 
    546   for (i=0; i<number_layers; i++)
    547   {
    548     if (layer_info[i].image != (Image *) NULL)
    549       layer_info[i].image=DestroyImage(layer_info[i].image);
    550     if (layer_info[i].mask.image != (Image *) NULL)
    551       layer_info[i].mask.image=DestroyImage(layer_info[i].mask.image);
    552   }
    553 
    554   return (LayerInfo *) RelinquishMagickMemory(layer_info);
    555 }
    556 
    557 static inline size_t GetPSDPacketSize(Image *image)
    558 {
    559   if (image->storage_class == PseudoClass)
    560     {
    561       if (image->colors > 256)
    562         return(2);
    563       else if (image->depth > 8)
    564         return(2);
    565     }
    566   else
    567     if (image->depth > 8)
    568       return(2);
    569 
    570   return(1);
    571 }
    572 
    573 static inline MagickSizeType GetPSDSize(const PSDInfo *psd_info,Image *image)
    574 {
    575   if (psd_info->version == 1)
    576     return((MagickSizeType) ReadBlobLong(image));
    577   return((MagickSizeType) ReadBlobLongLong(image));
    578 }
    579 
    580 static inline size_t GetPSDRowSize(Image *image)
    581 {
    582   if (image->depth == 1)
    583     return(((image->columns+7)/8)*GetPSDPacketSize(image));
    584   else
    585     return(image->columns*GetPSDPacketSize(image));
    586 }
    587 
    588 static const char *ModeToString(PSDImageType type)
    589 {
    590   switch (type)
    591   {
    592     case BitmapMode: return "Bitmap";
    593     case GrayscaleMode: return "Grayscale";
    594     case IndexedMode: return "Indexed";
    595     case RGBMode: return "RGB";
    596     case CMYKMode:  return "CMYK";
    597     case MultichannelMode: return "Multichannel";
    598     case DuotoneMode: return "Duotone";
    599     case LabMode: return "L*A*B";
    600     default: return "unknown";
    601   }
    602 }
    603 
    604 static MagickBooleanType NegateCMYK(Image *image,ExceptionInfo *exception)
    605 {
    606   ChannelType
    607     channel_mask;
    608 
    609   MagickBooleanType
    610     status;
    611 
    612   channel_mask=SetImageChannelMask(image,(ChannelType)(AllChannels &~
    613     AlphaChannel));
    614   status=NegateImage(image,MagickFalse,exception);
    615   (void) SetImageChannelMask(image,channel_mask);
    616   return(status);
    617 }
    618 
    619 static void ParseImageResourceBlocks(Image *image,
    620   const unsigned char *blocks,size_t length,
    621   MagickBooleanType *has_merged_image,ExceptionInfo *exception)
    622 {
    623   const unsigned char
    624     *p;
    625 
    626   StringInfo
    627     *profile;
    628 
    629   unsigned int
    630     count,
    631     long_sans;
    632 
    633   unsigned short
    634     id,
    635     short_sans;
    636 
    637   if (length < 16)
    638     return;
    639   profile=BlobToStringInfo((const unsigned char *) NULL,length);
    640   SetStringInfoDatum(profile,blocks);
    641   (void) SetImageProfile(image,"8bim",profile,exception);
    642   profile=DestroyStringInfo(profile);
    643   for (p=blocks; (p >= blocks) && (p < (blocks+length-16)); )
    644   {
    645     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
    646       break;
    647     p=PushLongPixel(MSBEndian,p,&long_sans);
    648     p=PushShortPixel(MSBEndian,p,&id);
    649     p=PushShortPixel(MSBEndian,p,&short_sans);
    650     p=PushLongPixel(MSBEndian,p,&count);
    651     if ((p+count) > (blocks+length-16))
    652       return;
    653     switch (id)
    654     {
    655       case 0x03ed:
    656       {
    657         char
    658           value[MagickPathExtent];
    659 
    660         unsigned short
    661           resolution;
    662 
    663         /*
    664           Resolution info.
    665         */
    666         p=PushShortPixel(MSBEndian,p,&resolution);
    667         image->resolution.x=(double) resolution;
    668         (void) FormatLocaleString(value,MagickPathExtent,"%g",image->resolution.x);
    669         (void) SetImageProperty(image,"tiff:XResolution",value,exception);
    670         p=PushShortPixel(MSBEndian,p,&short_sans);
    671         p=PushShortPixel(MSBEndian,p,&short_sans);
    672         p=PushShortPixel(MSBEndian,p,&short_sans);
    673         p=PushShortPixel(MSBEndian,p,&resolution);
    674         image->resolution.y=(double) resolution;
    675         (void) FormatLocaleString(value,MagickPathExtent,"%g",image->resolution.y);
    676         (void) SetImageProperty(image,"tiff:YResolution",value,exception);
    677         p=PushShortPixel(MSBEndian,p,&short_sans);
    678         p=PushShortPixel(MSBEndian,p,&short_sans);
    679         p=PushShortPixel(MSBEndian,p,&short_sans);
    680         image->units=PixelsPerInchResolution;
    681         break;
    682       }
    683       case 0x0421:
    684       {
    685         if (*(p+4) == 0)
    686           *has_merged_image=MagickFalse;
    687         p+=count;
    688         break;
    689       }
    690       default:
    691       {
    692         p+=count;
    693         break;
    694       }
    695     }
    696     if ((count & 0x01) != 0)
    697       p++;
    698   }
    699   return;
    700 }
    701 
    702 static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
    703 {
    704   if (mode == (const char *) NULL)
    705     return(OverCompositeOp);
    706   if (LocaleNCompare(mode,"norm",4) == 0)
    707     return(OverCompositeOp);
    708   if (LocaleNCompare(mode,"mul ",4) == 0)
    709     return(MultiplyCompositeOp);
    710   if (LocaleNCompare(mode,"diss",4) == 0)
    711     return(DissolveCompositeOp);
    712   if (LocaleNCompare(mode,"diff",4) == 0)
    713     return(DifferenceCompositeOp);
    714   if (LocaleNCompare(mode,"dark",4) == 0)
    715     return(DarkenCompositeOp);
    716   if (LocaleNCompare(mode,"lite",4) == 0)
    717     return(LightenCompositeOp);
    718   if (LocaleNCompare(mode,"hue ",4) == 0)
    719     return(HueCompositeOp);
    720   if (LocaleNCompare(mode,"sat ",4) == 0)
    721     return(SaturateCompositeOp);
    722   if (LocaleNCompare(mode,"colr",4) == 0)
    723     return(ColorizeCompositeOp);
    724   if (LocaleNCompare(mode,"lum ",4) == 0)
    725     return(LuminizeCompositeOp);
    726   if (LocaleNCompare(mode,"scrn",4) == 0)
    727     return(ScreenCompositeOp);
    728   if (LocaleNCompare(mode,"over",4) == 0)
    729     return(OverlayCompositeOp);
    730   if (LocaleNCompare(mode,"hLit",4) == 0)
    731     return(HardLightCompositeOp);
    732   if (LocaleNCompare(mode,"sLit",4) == 0)
    733     return(SoftLightCompositeOp);
    734   if (LocaleNCompare(mode,"smud",4) == 0)
    735     return(ExclusionCompositeOp);
    736   if (LocaleNCompare(mode,"div ",4) == 0)
    737     return(ColorDodgeCompositeOp);
    738   if (LocaleNCompare(mode,"idiv",4) == 0)
    739     return(ColorBurnCompositeOp);
    740   if (LocaleNCompare(mode,"lbrn",4) == 0)
    741     return(LinearBurnCompositeOp);
    742   if (LocaleNCompare(mode,"lddg",4) == 0)
    743     return(LinearDodgeCompositeOp);
    744   if (LocaleNCompare(mode,"lLit",4) == 0)
    745     return(LinearLightCompositeOp);
    746   if (LocaleNCompare(mode,"vLit",4) == 0)
    747     return(VividLightCompositeOp);
    748   if (LocaleNCompare(mode,"pLit",4) == 0)
    749     return(PinLightCompositeOp);
    750   if (LocaleNCompare(mode,"hMix",4) == 0)
    751     return(HardMixCompositeOp);
    752   return(OverCompositeOp);
    753 }
    754 
    755 static inline void ReversePSDString(Image *image,char *p,size_t length)
    756 {
    757   char
    758     *q;
    759 
    760   if (image->endian == MSBEndian)
    761     return;
    762 
    763   q=p+length;
    764   for(--q; p < q; ++p, --q)
    765   {
    766     *p = *p ^ *q,
    767     *q = *p ^ *q,
    768     *p = *p ^ *q;
    769   }
    770 }
    771 
    772 static inline void SetPSDPixel(Image *image,const size_t channels,
    773   const ssize_t type,const size_t packet_size,const Quantum pixel,Quantum *q,
    774   ExceptionInfo *exception)
    775 {
    776   if (image->storage_class == PseudoClass)
    777     {
    778       if (packet_size == 1)
    779         SetPixelIndex(image,ScaleQuantumToChar(pixel),q);
    780       else
    781         SetPixelIndex(image,ScaleQuantumToShort(pixel),q);
    782       SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
    783         ConstrainColormapIndex(image,GetPixelIndex(image,q),exception),q);
    784       return;
    785     }
    786   switch (type)
    787   {
    788     case -1:
    789     {
    790       SetPixelAlpha(image, pixel,q);
    791       break;
    792     }
    793     case -2:
    794     case 0:
    795     {
    796       SetPixelRed(image,pixel,q);
    797       if (channels == 1 || type == -2)
    798         SetPixelGray(image,pixel,q);
    799       break;
    800     }
    801     case 1:
    802     {
    803       if (image->storage_class == PseudoClass)
    804         SetPixelAlpha(image,pixel,q);
    805       else
    806         SetPixelGreen(image,pixel,q);
    807       break;
    808     }
    809     case 2:
    810     {
    811       if (image->storage_class == PseudoClass)
    812         SetPixelAlpha(image,pixel,q);
    813       else
    814         SetPixelBlue(image,pixel,q);
    815       break;
    816     }
    817     case 3:
    818     {
    819       if (image->colorspace == CMYKColorspace)
    820         SetPixelBlack(image,pixel,q);
    821       else
    822         if (image->alpha_trait != UndefinedPixelTrait)
    823           SetPixelAlpha(image,pixel,q);
    824       break;
    825     }
    826     case 4:
    827     {
    828       if ((IssRGBCompatibleColorspace(image->colorspace) != MagickFalse) &&
    829           (channels > 3))
    830         break;
    831       if (image->alpha_trait != UndefinedPixelTrait)
    832         SetPixelAlpha(image,pixel,q);
    833       break;
    834     }
    835   }
    836 }
    837 
    838 static MagickBooleanType ReadPSDChannelPixels(Image *image,
    839   const size_t channels,const size_t row,const ssize_t type,
    840   const unsigned char *pixels,ExceptionInfo *exception)
    841 {
    842   Quantum
    843     pixel;
    844 
    845   register const unsigned char
    846     *p;
    847 
    848   register Quantum
    849     *q;
    850 
    851   register ssize_t
    852     x;
    853 
    854   size_t
    855     packet_size;
    856 
    857   unsigned short
    858     nibble;
    859 
    860   p=pixels;
    861   q=GetAuthenticPixels(image,0,row,image->columns,1,exception);
    862   if (q == (Quantum *) NULL)
    863     return MagickFalse;
    864   packet_size=GetPSDPacketSize(image);
    865   for (x=0; x < (ssize_t) image->columns; x++)
    866   {
    867     if (packet_size == 1)
    868       pixel=ScaleCharToQuantum(*p++);
    869     else
    870       {
    871         p=PushShortPixel(MSBEndian,p,&nibble);
    872         pixel=ScaleShortToQuantum(nibble);
    873       }
    874     if (image->depth > 1)
    875       {
    876         SetPSDPixel(image,channels,type,packet_size,pixel,q,exception);
    877         q+=GetPixelChannels(image);
    878       }
    879     else
    880       {
    881         ssize_t
    882           bit,
    883           number_bits;
    884 
    885         number_bits=image->columns-x;
    886         if (number_bits > 8)
    887           number_bits=8;
    888         for (bit = 0; bit < number_bits; bit++)
    889         {
    890           SetPSDPixel(image,channels,type,packet_size,(((unsigned char) pixel)
    891             & (0x01 << (7-bit))) != 0 ? 0 : QuantumRange,q,exception);
    892           q+=GetPixelChannels(image);
    893           x++;
    894         }
    895         if (x != (ssize_t) image->columns)
    896           x--;
    897         continue;
    898       }
    899   }
    900   return(SyncAuthenticPixels(image,exception));
    901 }
    902 
    903 static MagickBooleanType ReadPSDChannelRaw(Image *image,const size_t channels,
    904   const ssize_t type,ExceptionInfo *exception)
    905 {
    906   MagickBooleanType
    907     status;
    908 
    909   size_t
    910     count,
    911     row_size;
    912 
    913   ssize_t
    914     y;
    915 
    916   unsigned char
    917     *pixels;
    918 
    919   if (image->debug != MagickFalse)
    920     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
    921        "      layer data is RAW");
    922 
    923   row_size=GetPSDRowSize(image);
    924   pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
    925   if (pixels == (unsigned char *) NULL)
    926     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    927       image->filename);
    928 
    929   status=MagickTrue;
    930   for (y=0; y < (ssize_t) image->rows; y++)
    931   {
    932     status=MagickFalse;
    933 
    934     count=ReadBlob(image,row_size,pixels);
    935     if (count != row_size)
    936       break;
    937 
    938     status=ReadPSDChannelPixels(image,channels,y,type,pixels,exception);
    939     if (status == MagickFalse)
    940       break;
    941   }
    942 
    943   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
    944   return(status);
    945 }
    946 
    947 static inline MagickOffsetType *ReadPSDRLEOffsets(Image *image,
    948   const PSDInfo *psd_info,const size_t size)
    949 {
    950   MagickOffsetType
    951     *offsets;
    952 
    953   ssize_t
    954     y;
    955 
    956   offsets=(MagickOffsetType *) AcquireQuantumMemory(size,sizeof(*offsets));
    957   if(offsets != (MagickOffsetType *) NULL)
    958     {
    959       for (y=0; y < (ssize_t) size; y++)
    960       {
    961         if (psd_info->version == 1)
    962           offsets[y]=(MagickOffsetType) ReadBlobShort(image);
    963         else
    964           offsets[y]=(MagickOffsetType) ReadBlobLong(image);
    965       }
    966     }
    967   return offsets;
    968 }
    969 
    970 static MagickBooleanType ReadPSDChannelRLE(Image *image,const PSDInfo *psd_info,
    971   const ssize_t type,MagickOffsetType *offsets,ExceptionInfo *exception)
    972 {
    973   MagickBooleanType
    974     status;
    975 
    976   size_t
    977     length,
    978     row_size;
    979 
    980   ssize_t
    981     count,
    982     y;
    983 
    984   unsigned char
    985     *compact_pixels,
    986     *pixels;
    987 
    988   if (image->debug != MagickFalse)
    989     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
    990        "      layer data is RLE compressed");
    991 
    992   row_size=GetPSDRowSize(image);
    993   pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
    994   if (pixels == (unsigned char *) NULL)
    995     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    996       image->filename);
    997 
    998   length=0;
    999   for (y=0; y < (ssize_t) image->rows; y++)
   1000     if ((MagickOffsetType) length < offsets[y])
   1001       length=(size_t) offsets[y];
   1002 
   1003   if (length > row_size + 256) // arbitrary number
   1004     {
   1005       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1006       ThrowBinaryException(ResourceLimitError,"InvalidLength",
   1007         image->filename);
   1008     }
   1009 
   1010   compact_pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
   1011   if (compact_pixels == (unsigned char *) NULL)
   1012     {
   1013       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1014       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1015         image->filename);
   1016     }
   1017 
   1018   (void) ResetMagickMemory(compact_pixels,0,length*sizeof(*compact_pixels));
   1019 
   1020   status=MagickTrue;
   1021   for (y=0; y < (ssize_t) image->rows; y++)
   1022   {
   1023     status=MagickFalse;
   1024 
   1025     count=ReadBlob(image,(size_t) offsets[y],compact_pixels);
   1026     if (count != (ssize_t) offsets[y])
   1027       break;
   1028 
   1029     count=DecodePSDPixels((size_t) offsets[y],compact_pixels,
   1030       (ssize_t) (image->depth == 1 ? 123456 : image->depth),row_size,pixels);
   1031     if (count != (ssize_t) row_size)
   1032       break;
   1033 
   1034     status=ReadPSDChannelPixels(image,psd_info->channels,y,type,pixels,
   1035       exception);
   1036     if (status == MagickFalse)
   1037       break;
   1038   }
   1039 
   1040   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   1041   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1042   return(status);
   1043 }
   1044 
   1045 #ifdef MAGICKCORE_ZLIB_DELEGATE
   1046 static MagickBooleanType ReadPSDChannelZip(Image *image,const size_t channels,
   1047   const ssize_t type,const PSDCompressionType compression,
   1048   const size_t compact_size,ExceptionInfo *exception)
   1049 {
   1050   MagickBooleanType
   1051     status;
   1052 
   1053   register unsigned char
   1054     *p;
   1055 
   1056   size_t
   1057     count,
   1058     length,
   1059     packet_size,
   1060     row_size;
   1061 
   1062   ssize_t
   1063     y;
   1064 
   1065   unsigned char
   1066     *compact_pixels,
   1067     *pixels;
   1068 
   1069   z_stream
   1070     stream;
   1071 
   1072   if (image->debug != MagickFalse)
   1073     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1074        "      layer data is ZIP compressed");
   1075 
   1076   compact_pixels=(unsigned char *) AcquireQuantumMemory(compact_size,
   1077     sizeof(*compact_pixels));
   1078   if (compact_pixels == (unsigned char *) NULL)
   1079     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1080       image->filename);
   1081 
   1082   packet_size=GetPSDPacketSize(image);
   1083   row_size=image->columns*packet_size;
   1084   count=image->rows*row_size;
   1085 
   1086   pixels=(unsigned char *) AcquireQuantumMemory(count,sizeof(*pixels));
   1087   if (pixels == (unsigned char *) NULL)
   1088     {
   1089       compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   1090       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1091         image->filename);
   1092     }
   1093 
   1094   ResetMagickMemory(&stream, 0, sizeof(z_stream));
   1095   stream.data_type=Z_BINARY;
   1096   (void) ReadBlob(image,compact_size,compact_pixels);
   1097 
   1098   stream.next_in=(Bytef *)compact_pixels;
   1099   stream.avail_in=(unsigned int) compact_size;
   1100   stream.next_out=(Bytef *)pixels;
   1101   stream.avail_out=(unsigned int) count;
   1102 
   1103   if(inflateInit(&stream) == Z_OK)
   1104     {
   1105       int
   1106         ret;
   1107 
   1108       while (stream.avail_out > 0)
   1109       {
   1110         ret=inflate(&stream, Z_SYNC_FLUSH);
   1111         if (ret != Z_OK && ret != Z_STREAM_END)
   1112         {
   1113           compact_pixels=(unsigned char *) RelinquishMagickMemory(
   1114             compact_pixels);
   1115           pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1116           return(MagickFalse);
   1117         }
   1118       }
   1119     }
   1120 
   1121   if (compression == ZipWithPrediction)
   1122   {
   1123      p=pixels;
   1124      while(count > 0)
   1125      {
   1126        length=image->columns;
   1127        while(--length)
   1128        {
   1129          if (packet_size == 2)
   1130            {
   1131              p[2]+=p[0]+((p[1]+p[3]) >> 8);
   1132              p[3]+=p[1];
   1133            }
   1134          else
   1135           *(p+1)+=*p;
   1136          p+=packet_size;
   1137        }
   1138        p+=packet_size;
   1139        count-=row_size;
   1140      }
   1141   }
   1142 
   1143   status=MagickTrue;
   1144   p=pixels;
   1145   for (y=0; y < (ssize_t) image->rows; y++)
   1146   {
   1147     status=ReadPSDChannelPixels(image,channels,y,type,p,exception);
   1148     if (status == MagickFalse)
   1149       break;
   1150 
   1151     p+=row_size;
   1152   }
   1153 
   1154   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   1155   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1156   return(status);
   1157 }
   1158 #endif
   1159 
   1160 static MagickBooleanType ReadPSDChannel(Image *image,const PSDInfo *psd_info,
   1161   LayerInfo* layer_info,const size_t channel,
   1162   const PSDCompressionType compression,ExceptionInfo *exception)
   1163 {
   1164   Image
   1165     *channel_image,
   1166     *mask;
   1167 
   1168   MagickOffsetType
   1169     offset;
   1170 
   1171   MagickBooleanType
   1172     status;
   1173 
   1174   channel_image=image;
   1175   mask=(Image *) NULL;
   1176   if (layer_info->channel_info[channel].type < -1)
   1177   {
   1178     /*
   1179       Ignore mask that is not a user supplied layer mask, if the mask is
   1180       disabled or if the flags have unsupported values.
   1181     */
   1182     if (layer_info->channel_info[channel].type != -2 ||
   1183         (layer_info->mask.flags > 3) || (layer_info->mask.flags & 0x02))
   1184     {
   1185       SeekBlob(image,layer_info->channel_info[channel].size-2,SEEK_CUR);
   1186       return(MagickTrue);
   1187     }
   1188     mask=CloneImage(image,layer_info->mask.page.width,
   1189       layer_info->mask.page.height,MagickFalse,exception);
   1190     SetImageType(mask,GrayscaleType,exception);
   1191     channel_image=mask;
   1192   }
   1193 
   1194   offset=TellBlob(image);
   1195   status=MagickTrue;
   1196   switch(compression)
   1197   {
   1198     case Raw:
   1199       status=ReadPSDChannelRaw(channel_image,psd_info->channels,
   1200         layer_info->channel_info[channel].type,exception);
   1201       break;
   1202     case RLE:
   1203       {
   1204         MagickOffsetType
   1205           *offsets;
   1206 
   1207         offsets=ReadPSDRLEOffsets(channel_image,psd_info,channel_image->rows);
   1208         if (offsets == (MagickOffsetType *) NULL)
   1209           ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1210             image->filename);
   1211         status=ReadPSDChannelRLE(channel_image,psd_info,
   1212           layer_info->channel_info[channel].type,offsets,exception);
   1213         offsets=(MagickOffsetType *) RelinquishMagickMemory(offsets);
   1214       }
   1215       break;
   1216     case ZipWithPrediction:
   1217     case ZipWithoutPrediction:
   1218 #ifdef MAGICKCORE_ZLIB_DELEGATE
   1219       status=ReadPSDChannelZip(channel_image,layer_info->channels,
   1220         layer_info->channel_info[channel].type,compression,
   1221         layer_info->channel_info[channel].size-2,exception);
   1222 #else
   1223       (void) ThrowMagickException(exception,GetMagickModule(),
   1224           MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
   1225             "'%s' (ZLIB)",image->filename);
   1226 #endif
   1227       break;
   1228     default:
   1229       (void) ThrowMagickException(exception,GetMagickModule(),TypeWarning,
   1230         "CompressionNotSupported","'%.20g'",(double) compression);
   1231       break;
   1232   }
   1233 
   1234   SeekBlob(image,offset+layer_info->channel_info[channel].size-2,SEEK_SET);
   1235   if (status == MagickFalse)
   1236     {
   1237       if (mask != (Image *) NULL)
   1238         DestroyImage(mask);
   1239       ThrowBinaryException(CoderError,"UnableToDecompressImage",
   1240         image->filename);
   1241     }
   1242   if (mask != (Image *) NULL)
   1243   {
   1244     if (status != MagickFalse)
   1245       {
   1246         PixelInfo
   1247           color;
   1248 
   1249         layer_info->mask.image=CloneImage(image,image->columns,image->rows,
   1250           MagickTrue,exception);
   1251         layer_info->mask.image->alpha_trait=UndefinedPixelTrait;
   1252         GetPixelInfo(layer_info->mask.image,&color);
   1253         color.red=layer_info->mask.background == 0 ? 0 : QuantumRange;
   1254         SetImageColor(layer_info->mask.image,&color,exception);
   1255         (void) CompositeImage(layer_info->mask.image,mask,OverCompositeOp,
   1256           MagickTrue,layer_info->mask.page.x,layer_info->mask.page.y,
   1257           exception);
   1258       }
   1259     DestroyImage(mask);
   1260   }
   1261 
   1262   return(status);
   1263 }
   1264 
   1265 static MagickBooleanType ReadPSDLayer(Image *image,const PSDInfo *psd_info,
   1266   LayerInfo* layer_info,ExceptionInfo *exception)
   1267 {
   1268   char
   1269     message[MagickPathExtent];
   1270 
   1271   MagickBooleanType
   1272     status;
   1273 
   1274   PSDCompressionType
   1275     compression;
   1276 
   1277   ssize_t
   1278     j;
   1279 
   1280   if (image->debug != MagickFalse)
   1281     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1282       "    setting up new layer image");
   1283   (void) SetImageBackgroundColor(layer_info->image,exception);
   1284   layer_info->image->compose=PSDBlendModeToCompositeOperator(
   1285     layer_info->blendkey);
   1286   if (layer_info->visible == MagickFalse)
   1287     layer_info->image->compose=NoCompositeOp;
   1288   if (psd_info->mode == CMYKMode)
   1289     SetImageColorspace(layer_info->image,CMYKColorspace,exception);
   1290   if ((psd_info->mode == BitmapMode) || (psd_info->mode == GrayscaleMode) ||
   1291       (psd_info->mode == DuotoneMode))
   1292     SetImageColorspace(layer_info->image,GRAYColorspace,exception);
   1293   /*
   1294     Set up some hidden attributes for folks that need them.
   1295   */
   1296   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
   1297     (double) layer_info->page.x);
   1298   (void) SetImageArtifact(layer_info->image,"psd:layer.x",message);
   1299   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
   1300     (double) layer_info->page.y);
   1301   (void) SetImageArtifact(layer_info->image,"psd:layer.y",message);
   1302   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
   1303     layer_info->opacity);
   1304   (void) SetImageArtifact(layer_info->image,"psd:layer.opacity",message);
   1305   (void) SetImageProperty(layer_info->image,"label",(char *) layer_info->name,
   1306     exception);
   1307 
   1308   status=MagickTrue;
   1309   for (j=0; j < (ssize_t) layer_info->channels; j++)
   1310   {
   1311     if (image->debug != MagickFalse)
   1312       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1313         "    reading data for channel %.20g",(double) j);
   1314 
   1315     compression=(PSDCompressionType) ReadBlobShort(layer_info->image);
   1316     layer_info->image->compression=ConvertPSDCompression(compression);
   1317     if (layer_info->channel_info[j].type == -1)
   1318       layer_info->image->alpha_trait=BlendPixelTrait;
   1319 
   1320     status=ReadPSDChannel(layer_info->image,psd_info,layer_info,j,
   1321       compression,exception);
   1322 
   1323     if (status == MagickFalse)
   1324       break;
   1325   }
   1326 
   1327   if (status != MagickFalse)
   1328     status=CorrectPSDOpacity(layer_info,exception);
   1329 
   1330   if ((status != MagickFalse) &&
   1331       (layer_info->image->colorspace == CMYKColorspace))
   1332     status=NegateCMYK(layer_info->image,exception);
   1333 
   1334   if ((status != MagickFalse) && (layer_info->mask.image != (Image *) NULL))
   1335     {
   1336       status=CompositeImage(layer_info->image,layer_info->mask.image,
   1337         CopyAlphaCompositeOp,MagickTrue,0,0,exception);
   1338       layer_info->mask.image=DestroyImage(layer_info->mask.image);
   1339     }
   1340 
   1341   return(status);
   1342 }
   1343 
   1344 ModuleExport MagickBooleanType ReadPSDLayers(Image *image,
   1345   const ImageInfo *image_info,const PSDInfo *psd_info,
   1346   const MagickBooleanType skip_layers,ExceptionInfo *exception)
   1347 {
   1348   char
   1349     type[4];
   1350 
   1351   LayerInfo
   1352     *layer_info;
   1353 
   1354   MagickSizeType
   1355     size;
   1356 
   1357   MagickBooleanType
   1358     status;
   1359 
   1360   register ssize_t
   1361     i;
   1362 
   1363   ssize_t
   1364     count,
   1365     j,
   1366     number_layers;
   1367 
   1368   size=GetPSDSize(psd_info,image);
   1369   if (size == 0)
   1370     {
   1371       /*
   1372         Skip layers & masks.
   1373       */
   1374       (void) ReadBlobLong(image);
   1375       count=ReadBlob(image,4,(unsigned char *) type);
   1376       ReversePSDString(image,type,4);
   1377       status=MagickFalse;
   1378       if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
   1379         return(MagickTrue);
   1380       else
   1381         {
   1382           count=ReadBlob(image,4,(unsigned char *) type);
   1383           ReversePSDString(image,type,4);
   1384           if ((count != 0) && (LocaleNCompare(type,"Lr16",4) == 0))
   1385             size=GetPSDSize(psd_info,image);
   1386           else
   1387             return(MagickTrue);
   1388         }
   1389     }
   1390   status=MagickTrue;
   1391   if (size != 0)
   1392     {
   1393       layer_info=(LayerInfo *) NULL;
   1394       number_layers=(short) ReadBlobShort(image);
   1395 
   1396       if (number_layers < 0)
   1397         {
   1398           /*
   1399             The first alpha channel in the merged result contains the
   1400             transparency data for the merged result.
   1401           */
   1402           number_layers=MagickAbsoluteValue(number_layers);
   1403           if (image->debug != MagickFalse)
   1404             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1405               "  negative layer count corrected for");
   1406           image->alpha_trait=BlendPixelTrait;
   1407         }
   1408 
   1409       /*
   1410         We only need to know if the image has an alpha channel
   1411       */
   1412       if (skip_layers != MagickFalse)
   1413         return(MagickTrue);
   1414 
   1415       if (image->debug != MagickFalse)
   1416         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1417           "  image contains %.20g layers",(double) number_layers);
   1418 
   1419       if (number_layers == 0)
   1420         ThrowBinaryException(CorruptImageError,"InvalidNumberOfLayers",
   1421           image->filename);
   1422 
   1423       layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
   1424         sizeof(*layer_info));
   1425       if (layer_info == (LayerInfo *) NULL)
   1426         {
   1427           if (image->debug != MagickFalse)
   1428             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1429               "  allocation of LayerInfo failed");
   1430           ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1431             image->filename);
   1432         }
   1433       (void) ResetMagickMemory(layer_info,0,(size_t) number_layers*
   1434         sizeof(*layer_info));
   1435 
   1436       for (i=0; i < number_layers; i++)
   1437       {
   1438         ssize_t
   1439           x,
   1440           y;
   1441 
   1442         if (image->debug != MagickFalse)
   1443           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1444             "  reading layer #%.20g",(double) i+1);
   1445         layer_info[i].page.y=ReadBlobSignedLong(image);
   1446         layer_info[i].page.x=ReadBlobSignedLong(image);
   1447         y=ReadBlobSignedLong(image);
   1448         x=ReadBlobSignedLong(image);
   1449         layer_info[i].page.width=(size_t) (x-layer_info[i].page.x);
   1450         layer_info[i].page.height=(size_t) (y-layer_info[i].page.y);
   1451         layer_info[i].channels=ReadBlobShort(image);
   1452         if (layer_info[i].channels > MaxPSDChannels)
   1453           {
   1454             layer_info=DestroyLayerInfo(layer_info,number_layers);
   1455             ThrowBinaryException(CorruptImageError,"MaximumChannelsExceeded",
   1456               image->filename);
   1457           }
   1458         if (image->debug != MagickFalse)
   1459           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1460             "    offset(%.20g,%.20g), size(%.20g,%.20g), channels=%.20g",
   1461             (double) layer_info[i].page.x,(double) layer_info[i].page.y,
   1462             (double) layer_info[i].page.height,(double)
   1463             layer_info[i].page.width,(double) layer_info[i].channels);
   1464         for (j=0; j < (ssize_t) layer_info[i].channels; j++)
   1465         {
   1466           layer_info[i].channel_info[j].type=(short) ReadBlobShort(image);
   1467           layer_info[i].channel_info[j].size=(size_t) GetPSDSize(psd_info,
   1468             image);
   1469           if (image->debug != MagickFalse)
   1470             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1471               "    channel[%.20g]: type=%.20g, size=%.20g",(double) j,
   1472               (double) layer_info[i].channel_info[j].type,
   1473               (double) layer_info[i].channel_info[j].size);
   1474         }
   1475         count=ReadBlob(image,4,(unsigned char *) type);
   1476         ReversePSDString(image,type,4);
   1477         if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
   1478           {
   1479             if (image->debug != MagickFalse)
   1480               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1481                 "  layer type was %.4s instead of 8BIM", type);
   1482             layer_info=DestroyLayerInfo(layer_info,number_layers);
   1483             ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
   1484               image->filename);
   1485           }
   1486         count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
   1487         ReversePSDString(image,layer_info[i].blendkey,4);
   1488         layer_info[i].opacity=(Quantum) ScaleCharToQuantum((unsigned char)
   1489           ReadBlobByte(image));
   1490         layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
   1491         layer_info[i].flags=(unsigned char) ReadBlobByte(image);
   1492         layer_info[i].visible=!(layer_info[i].flags & 0x02);
   1493         if (image->debug != MagickFalse)
   1494           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1495             "   blend=%.4s, opacity=%.20g, clipping=%s, flags=%d, visible=%s",
   1496             layer_info[i].blendkey,(double) layer_info[i].opacity,
   1497             layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
   1498             layer_info[i].visible ? "true" : "false");
   1499         (void) ReadBlobByte(image);  /* filler */
   1500 
   1501         size=ReadBlobLong(image);
   1502         if (size != 0)
   1503           {
   1504             MagickSizeType
   1505               combined_length,
   1506               length;
   1507 
   1508             if (image->debug != MagickFalse)
   1509               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1510                 "    layer contains additional info");
   1511             length=ReadBlobLong(image);
   1512             combined_length=length+4;
   1513             if (length != 0)
   1514               {
   1515                 /*
   1516                   Layer mask info.
   1517                 */
   1518                 layer_info[i].mask.page.y=ReadBlobSignedLong(image);
   1519                 layer_info[i].mask.page.x=ReadBlobSignedLong(image);
   1520                 layer_info[i].mask.page.height=(size_t) (ReadBlobLong(image)-
   1521                   layer_info[i].mask.page.y);
   1522                 layer_info[i].mask.page.width=(size_t) (ReadBlobLong(image)-
   1523                   layer_info[i].mask.page.x);
   1524                 layer_info[i].mask.background=(unsigned char) ReadBlobByte(
   1525                   image);
   1526                 layer_info[i].mask.flags=(unsigned char) ReadBlobByte(image);
   1527                 if (!(layer_info[i].mask.flags & 0x01))
   1528                   {
   1529                     layer_info[i].mask.page.y=layer_info[i].mask.page.y-
   1530                       layer_info[i].page.y;
   1531                     layer_info[i].mask.page.x=layer_info[i].mask.page.x-
   1532                       layer_info[i].page.x;
   1533                   }
   1534                 if (image->debug != MagickFalse)
   1535                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1536                     "      layer mask: offset(%.20g,%.20g), size(%.20g,%.20g), length=%.20g",
   1537                     (double) layer_info[i].mask.page.x,(double)
   1538                     layer_info[i].mask.page.y,(double) layer_info[i].mask.page.width,
   1539                     (double) layer_info[i].mask.page.height,(double)
   1540                     ((MagickOffsetType) length)-18);
   1541                 /*
   1542                   Skip over the rest of the layer mask information.
   1543                 */
   1544                 if (DiscardBlobBytes(image,(MagickSizeType) (length-18)) == MagickFalse)
   1545                   {
   1546                     layer_info=DestroyLayerInfo(layer_info,number_layers);
   1547                     ThrowBinaryException(CorruptImageError,"UnexpectedEndOfFile",
   1548                       image->filename);
   1549                   }
   1550               }
   1551             length=ReadBlobLong(image);
   1552             combined_length+=length+4;
   1553             if (length != 0)
   1554               {
   1555                 /*
   1556                   Layer blending ranges info.
   1557                 */
   1558                 if (image->debug != MagickFalse)
   1559                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1560                     "      layer blending ranges: length=%.20g",(double)
   1561                     ((MagickOffsetType) length));
   1562                 /*
   1563                   We read it, but don't use it...
   1564                 */
   1565                 for (j=0; j < (ssize_t) (length); j+=8)
   1566                 {
   1567                   size_t blend_source=ReadBlobLong(image);
   1568                   size_t blend_dest=ReadBlobLong(image);
   1569                   if (image->debug != MagickFalse)
   1570                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1571                       "        source(%x), dest(%x)",(unsigned int)
   1572                       blend_source,(unsigned int) blend_dest);
   1573                 }
   1574               }
   1575             /*
   1576               Layer name.
   1577             */
   1578             length=(size_t) ReadBlobByte(image);
   1579             combined_length+=length+1;
   1580             if (length > 0)
   1581               (void) ReadBlob(image,(size_t) length++,layer_info[i].name);
   1582             layer_info[i].name[length]='\0';
   1583             if (image->debug != MagickFalse)
   1584               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1585                 "      layer name: %s",layer_info[i].name);
   1586             /*
   1587                Skip the rest of the variable data until we support it.
   1588              */
   1589              if (image->debug != MagickFalse)
   1590                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1591                  "      unsupported data: length=%.20g",(double)
   1592                  ((MagickOffsetType) (size-combined_length)));
   1593              if (DiscardBlobBytes(image,(MagickSizeType) (size-combined_length)) == MagickFalse)
   1594                {
   1595                  layer_info=DestroyLayerInfo(layer_info,number_layers);
   1596                  ThrowBinaryException(CorruptImageError,
   1597                    "UnexpectedEndOfFile",image->filename);
   1598                }
   1599           }
   1600       }
   1601 
   1602       for (i=0; i < number_layers; i++)
   1603       {
   1604         if ((layer_info[i].page.width == 0) ||
   1605               (layer_info[i].page.height == 0))
   1606           {
   1607             if (image->debug != MagickFalse)
   1608               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1609                 "      layer data is empty");
   1610             continue;
   1611           }
   1612 
   1613         /*
   1614           Allocate layered image.
   1615         */
   1616         layer_info[i].image=CloneImage(image,layer_info[i].page.width,
   1617           layer_info[i].page.height,MagickFalse,exception);
   1618         if (layer_info[i].image == (Image *) NULL)
   1619           {
   1620             layer_info=DestroyLayerInfo(layer_info,number_layers);
   1621             if (image->debug != MagickFalse)
   1622               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1623                 "  allocation of image for layer %.20g failed",(double) i);
   1624             ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1625               image->filename);
   1626           }
   1627       }
   1628 
   1629       if (image_info->ping == MagickFalse)
   1630         {
   1631           for (i=0; i < number_layers; i++)
   1632           {
   1633             if (layer_info[i].image == (Image *) NULL)
   1634               {
   1635                 for (j=0; j < layer_info[i].channels; j++)
   1636                 {
   1637                   if (DiscardBlobBytes(image,(MagickSizeType)
   1638                       layer_info[i].channel_info[j].size) == MagickFalse)
   1639                     {
   1640                       layer_info=DestroyLayerInfo(layer_info,number_layers);
   1641                       ThrowBinaryException(CorruptImageError,
   1642                         "UnexpectedEndOfFile",image->filename);
   1643                     }
   1644                 }
   1645                 continue;
   1646               }
   1647 
   1648             if (image->debug != MagickFalse)
   1649               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1650                 "  reading data for layer %.20g",(double) i);
   1651 
   1652             status=ReadPSDLayer(image,psd_info,&layer_info[i],exception);
   1653             if (status == MagickFalse)
   1654               break;
   1655 
   1656             status=SetImageProgress(image,LoadImagesTag,i,(MagickSizeType)
   1657               number_layers);
   1658             if (status == MagickFalse)
   1659               break;
   1660           }
   1661         }
   1662 
   1663       if (status != MagickFalse)
   1664       {
   1665         for (i=0; i < number_layers; i++)
   1666         {
   1667           if (layer_info[i].image == (Image *) NULL)
   1668           {
   1669             for (j=i; j < number_layers - 1; j++)
   1670               layer_info[j] = layer_info[j+1];
   1671             number_layers--;
   1672             i--;
   1673           }
   1674         }
   1675 
   1676         if (number_layers > 0)
   1677           {
   1678             for (i=0; i < number_layers; i++)
   1679             {
   1680               if (i > 0)
   1681                 layer_info[i].image->previous=layer_info[i-1].image;
   1682               if (i < (number_layers-1))
   1683                 layer_info[i].image->next=layer_info[i+1].image;
   1684               layer_info[i].image->page=layer_info[i].page;
   1685             }
   1686             image->next=layer_info[0].image;
   1687             layer_info[0].image->previous=image;
   1688           }
   1689         layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
   1690       }
   1691       else
   1692         layer_info=DestroyLayerInfo(layer_info,number_layers);
   1693     }
   1694 
   1695   return(status);
   1696 }
   1697 
   1698 static MagickBooleanType ReadPSDMergedImage(const ImageInfo *image_info,
   1699   Image *image,const PSDInfo *psd_info,ExceptionInfo *exception)
   1700 {
   1701   MagickOffsetType
   1702     *offsets;
   1703 
   1704   MagickBooleanType
   1705     status;
   1706 
   1707   PSDCompressionType
   1708     compression;
   1709 
   1710   register ssize_t
   1711     i;
   1712 
   1713   compression=(PSDCompressionType) ReadBlobMSBShort(image);
   1714   image->compression=ConvertPSDCompression(compression);
   1715 
   1716   if (compression != Raw && compression != RLE)
   1717     {
   1718       (void) ThrowMagickException(exception,GetMagickModule(),
   1719         TypeWarning,"CompressionNotSupported","'%.20g'",(double) compression);
   1720       return(MagickFalse);
   1721     }
   1722 
   1723   offsets=(MagickOffsetType *) NULL;
   1724   if (compression == RLE)
   1725   {
   1726     offsets=ReadPSDRLEOffsets(image,psd_info,image->rows*psd_info->channels);
   1727     if (offsets == (MagickOffsetType *) NULL)
   1728       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1729         image->filename);
   1730   }
   1731 
   1732   status=MagickTrue;
   1733   for (i=0; i < (ssize_t) psd_info->channels; i++)
   1734   {
   1735     if (compression == RLE)
   1736       status=ReadPSDChannelRLE(image,psd_info,i,offsets+(i*image->rows),
   1737         exception);
   1738     else
   1739       status=ReadPSDChannelRaw(image,psd_info->channels,i,exception);
   1740 
   1741     if (status != MagickFalse)
   1742       status=SetImageProgress(image,LoadImagesTag,i,psd_info->channels);
   1743 
   1744     if (status == MagickFalse)
   1745       break;
   1746   }
   1747 
   1748   if ((status != MagickFalse) && (image->colorspace == CMYKColorspace))
   1749     status=NegateCMYK(image,exception);
   1750 
   1751   if (status != MagickFalse)
   1752     status=CorrectPSDAlphaBlend(image_info,image,exception);
   1753 
   1754   if (offsets != (MagickOffsetType *) NULL)
   1755     offsets=(MagickOffsetType *) RelinquishMagickMemory(offsets);
   1756 
   1757   return(status);
   1758 }
   1759 
   1760 static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
   1761 {
   1762   Image
   1763     *image;
   1764 
   1765   MagickBooleanType
   1766     has_merged_image,
   1767     skip_layers;
   1768 
   1769   MagickOffsetType
   1770     offset;
   1771 
   1772   MagickSizeType
   1773     length;
   1774 
   1775   MagickBooleanType
   1776     status;
   1777 
   1778   PSDInfo
   1779     psd_info;
   1780 
   1781   register ssize_t
   1782     i;
   1783 
   1784   ssize_t
   1785     count;
   1786 
   1787   unsigned char
   1788     *data;
   1789 
   1790   /*
   1791     Open image file.
   1792   */
   1793   assert(image_info != (const ImageInfo *) NULL);
   1794   assert(image_info->signature == MagickCoreSignature);
   1795   if (image_info->debug != MagickFalse)
   1796     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   1797       image_info->filename);
   1798   assert(exception != (ExceptionInfo *) NULL);
   1799   assert(exception->signature == MagickCoreSignature);
   1800 
   1801   image=AcquireImage(image_info,exception);
   1802   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   1803   if (status == MagickFalse)
   1804     {
   1805       image=DestroyImageList(image);
   1806       return((Image *) NULL);
   1807     }
   1808   /*
   1809     Read image header.
   1810   */
   1811   image->endian=MSBEndian;
   1812   count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
   1813   psd_info.version=ReadBlobMSBShort(image);
   1814   if ((count == 0) || (LocaleNCompare(psd_info.signature,"8BPS",4) != 0) ||
   1815       ((psd_info.version != 1) && (psd_info.version != 2)))
   1816     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   1817   (void) ReadBlob(image,6,psd_info.reserved);
   1818   psd_info.channels=ReadBlobMSBShort(image);
   1819   if (psd_info.channels > MaxPSDChannels)
   1820     ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
   1821   psd_info.rows=ReadBlobMSBLong(image);
   1822   psd_info.columns=ReadBlobMSBLong(image);
   1823   if ((psd_info.version == 1) && ((psd_info.rows > 30000) ||
   1824       (psd_info.columns > 30000)))
   1825     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   1826   psd_info.depth=ReadBlobMSBShort(image);
   1827   if ((psd_info.depth != 1) && (psd_info.depth != 8) && (psd_info.depth != 16))
   1828     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   1829   psd_info.mode=ReadBlobMSBShort(image);
   1830   if (image->debug != MagickFalse)
   1831     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1832       "  Image is %.20g x %.20g with channels=%.20g, depth=%.20g, mode=%s",
   1833       (double) psd_info.columns,(double) psd_info.rows,(double)
   1834       psd_info.channels,(double) psd_info.depth,ModeToString((PSDImageType)
   1835       psd_info.mode));
   1836   /*
   1837     Initialize image.
   1838   */
   1839   image->depth=psd_info.depth;
   1840   image->columns=psd_info.columns;
   1841   image->rows=psd_info.rows;
   1842   status=SetImageExtent(image,image->columns,image->rows,exception);
   1843   if (status == MagickFalse)
   1844     return(DestroyImageList(image));
   1845   if (SetImageBackgroundColor(image,exception) == MagickFalse)
   1846     {
   1847       image=DestroyImageList(image);
   1848       return((Image *) NULL);
   1849     }
   1850   if (psd_info.mode == LabMode)
   1851     SetImageColorspace(image,LabColorspace,exception);
   1852   if (psd_info.mode == CMYKMode)
   1853     {
   1854       SetImageColorspace(image,CMYKColorspace,exception);
   1855       image->alpha_trait=psd_info.channels > 4 ? BlendPixelTrait :
   1856         UndefinedPixelTrait;
   1857     }
   1858   else if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
   1859       (psd_info.mode == DuotoneMode))
   1860     {
   1861       status=AcquireImageColormap(image,psd_info.depth != 16 ? 256 : 65536,
   1862         exception);
   1863       if (status == MagickFalse)
   1864         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1865       if (image->debug != MagickFalse)
   1866         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1867           "  Image colormap allocated");
   1868       SetImageColorspace(image,GRAYColorspace,exception);
   1869       image->alpha_trait=psd_info.channels > 1 ? BlendPixelTrait :
   1870         UndefinedPixelTrait;
   1871     }
   1872   else
   1873     image->alpha_trait=psd_info.channels > 3 ? BlendPixelTrait :
   1874       UndefinedPixelTrait;
   1875   /*
   1876     Read PSD raster colormap only present for indexed and duotone images.
   1877   */
   1878   length=ReadBlobMSBLong(image);
   1879   if (length != 0)
   1880     {
   1881       if (image->debug != MagickFalse)
   1882         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1883           "  reading colormap");
   1884       if (psd_info.mode == DuotoneMode)
   1885         {
   1886           /*
   1887             Duotone image data;  the format of this data is undocumented.
   1888           */
   1889           data=(unsigned char *) AcquireQuantumMemory((size_t) length,
   1890             sizeof(*data));
   1891           if (data == (unsigned char *) NULL)
   1892             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1893           (void) ReadBlob(image,(size_t) length,data);
   1894           data=(unsigned char *) RelinquishMagickMemory(data);
   1895         }
   1896       else
   1897         {
   1898           size_t
   1899             number_colors;
   1900 
   1901           /*
   1902             Read PSD raster colormap.
   1903           */
   1904           number_colors=length/3;
   1905           if (number_colors > 65536)
   1906             ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   1907           if (AcquireImageColormap(image,number_colors,exception) == MagickFalse)
   1908             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1909           for (i=0; i < (ssize_t) image->colors; i++)
   1910             image->colormap[i].red=ScaleCharToQuantum((unsigned char)
   1911               ReadBlobByte(image));
   1912           for (i=0; i < (ssize_t) image->colors; i++)
   1913             image->colormap[i].green=ScaleCharToQuantum((unsigned char)
   1914               ReadBlobByte(image));
   1915           for (i=0; i < (ssize_t) image->colors; i++)
   1916             image->colormap[i].blue=ScaleCharToQuantum((unsigned char)
   1917               ReadBlobByte(image));
   1918           image->alpha_trait=UndefinedPixelTrait;
   1919         }
   1920     }
   1921   if ((image->depth == 1) && (image->storage_class != PseudoClass))
   1922     ThrowReaderException(CorruptImageError, "ImproperImageHeader");
   1923   has_merged_image=MagickTrue;
   1924   length=ReadBlobMSBLong(image);
   1925   if (length != 0)
   1926     {
   1927       unsigned char
   1928         *blocks;
   1929 
   1930       /*
   1931         Image resources block.
   1932       */
   1933       if (image->debug != MagickFalse)
   1934         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1935           "  reading image resource blocks - %.20g bytes",(double)
   1936           ((MagickOffsetType) length));
   1937       blocks=(unsigned char *) AcquireQuantumMemory((size_t) length,
   1938         sizeof(*blocks));
   1939       if (blocks == (unsigned char *) NULL)
   1940         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1941       count=ReadBlob(image,(size_t) length,blocks);
   1942       if ((count != (ssize_t) length) || (length < 4) ||
   1943           (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
   1944         {
   1945           blocks=(unsigned char *) RelinquishMagickMemory(blocks);
   1946           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   1947         }
   1948       ParseImageResourceBlocks(image,blocks,(size_t) length,&has_merged_image,
   1949         exception);
   1950       blocks=(unsigned char *) RelinquishMagickMemory(blocks);
   1951     }
   1952   /*
   1953     Layer and mask block.
   1954   */
   1955   length=GetPSDSize(&psd_info,image);
   1956   if (length == 8)
   1957     {
   1958       length=ReadBlobMSBLong(image);
   1959       length=ReadBlobMSBLong(image);
   1960     }
   1961   offset=TellBlob(image);
   1962   skip_layers=MagickFalse;
   1963   if ((image_info->number_scenes == 1) && (image_info->scene == 0) &&
   1964       (has_merged_image != MagickFalse))
   1965     {
   1966       if (image->debug != MagickFalse)
   1967         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1968           "  read composite only");
   1969       skip_layers=MagickTrue;
   1970     }
   1971   if (length == 0)
   1972     {
   1973       if (image->debug != MagickFalse)
   1974         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1975           "  image has no layers");
   1976     }
   1977   else
   1978     {
   1979       if (ReadPSDLayers(image,image_info,&psd_info,skip_layers,exception) !=
   1980           MagickTrue)
   1981         {
   1982           (void) CloseBlob(image);
   1983           image=DestroyImageList(image);
   1984           return((Image *) NULL);
   1985         }
   1986 
   1987       /*
   1988          Skip the rest of the layer and mask information.
   1989       */
   1990       SeekBlob(image,offset+length,SEEK_SET);
   1991     }
   1992   /*
   1993     If we are only "pinging" the image, then we're done - so return.
   1994   */
   1995   if (image_info->ping != MagickFalse)
   1996     {
   1997       (void) CloseBlob(image);
   1998       return(GetFirstImageInList(image));
   1999     }
   2000   /*
   2001     Read the precombined layer, present for PSD < 4 compatibility.
   2002   */
   2003   if (image->debug != MagickFalse)
   2004     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2005       "  reading the precombined layer");
   2006   if ((has_merged_image != MagickFalse) || (GetImageListLength(image) == 1))
   2007     has_merged_image=(MagickBooleanType) ReadPSDMergedImage(image_info,image,
   2008       &psd_info,exception);
   2009   if ((has_merged_image == MagickFalse) && (GetImageListLength(image) == 1) &&
   2010       (length != 0))
   2011     {
   2012       SeekBlob(image,offset,SEEK_SET);
   2013       status=ReadPSDLayers(image,image_info,&psd_info,MagickFalse,exception);
   2014       if (status != MagickTrue)
   2015         {
   2016           (void) CloseBlob(image);
   2017           image=DestroyImageList(image);
   2018           return((Image *) NULL);
   2019         }
   2020     }
   2021   if ((has_merged_image == MagickFalse) && (GetImageListLength(image) > 1))
   2022     {
   2023       Image
   2024         *merged;
   2025 
   2026       SetImageAlphaChannel(image,TransparentAlphaChannel,exception);
   2027       image->background_color.alpha=TransparentAlpha;
   2028       image->background_color.alpha_trait=BlendPixelTrait;
   2029       merged=MergeImageLayers(image,FlattenLayer,exception);
   2030       ReplaceImageInList(&image,merged);
   2031     }
   2032   (void) CloseBlob(image);
   2033   return(GetFirstImageInList(image));
   2034 }
   2035 
   2036 /*
   2038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2039 %                                                                             %
   2040 %                                                                             %
   2041 %                                                                             %
   2042 %   R e g i s t e r P S D I m a g e                                           %
   2043 %                                                                             %
   2044 %                                                                             %
   2045 %                                                                             %
   2046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2047 %
   2048 %  RegisterPSDImage() adds properties for the PSD image format to
   2049 %  the list of supported formats.  The properties include the image format
   2050 %  tag, a method to read and/or write the format, whether the format
   2051 %  supports the saving of more than one frame to the same file or blob,
   2052 %  whether the format supports native in-memory I/O, and a brief
   2053 %  description of the format.
   2054 %
   2055 %  The format of the RegisterPSDImage method is:
   2056 %
   2057 %      size_t RegisterPSDImage(void)
   2058 %
   2059 */
   2060 ModuleExport size_t RegisterPSDImage(void)
   2061 {
   2062   MagickInfo
   2063     *entry;
   2064 
   2065   entry=AcquireMagickInfo("PSD","PSB","Adobe Large Document Format");
   2066   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
   2067   entry->encoder=(EncodeImageHandler *) WritePSDImage;
   2068   entry->magick=(IsImageFormatHandler *) IsPSD;
   2069   entry->flags|=CoderSeekableStreamFlag;
   2070   (void) RegisterMagickInfo(entry);
   2071   entry=AcquireMagickInfo("PSD","PSD","Adobe Photoshop bitmap");
   2072   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
   2073   entry->encoder=(EncodeImageHandler *) WritePSDImage;
   2074   entry->magick=(IsImageFormatHandler *) IsPSD;
   2075   entry->flags|=CoderSeekableStreamFlag;
   2076   (void) RegisterMagickInfo(entry);
   2077   return(MagickImageCoderSignature);
   2078 }
   2079 
   2080 /*
   2082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2083 %                                                                             %
   2084 %                                                                             %
   2085 %                                                                             %
   2086 %   U n r e g i s t e r P S D I m a g e                                       %
   2087 %                                                                             %
   2088 %                                                                             %
   2089 %                                                                             %
   2090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2091 %
   2092 %  UnregisterPSDImage() removes format registrations made by the
   2093 %  PSD module from the list of supported formats.
   2094 %
   2095 %  The format of the UnregisterPSDImage method is:
   2096 %
   2097 %      UnregisterPSDImage(void)
   2098 %
   2099 */
   2100 ModuleExport void UnregisterPSDImage(void)
   2101 {
   2102   (void) UnregisterMagickInfo("PSB");
   2103   (void) UnregisterMagickInfo("PSD");
   2104 }
   2105 
   2106 /*
   2108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2109 %                                                                             %
   2110 %                                                                             %
   2111 %                                                                             %
   2112 %   W r i t e P S D I m a g e                                                 %
   2113 %                                                                             %
   2114 %                                                                             %
   2115 %                                                                             %
   2116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2117 %
   2118 %  WritePSDImage() writes an image in the Adobe Photoshop encoded image format.
   2119 %
   2120 %  The format of the WritePSDImage method is:
   2121 %
   2122 %      MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image,
   2123 %        ExceptionInfo *exception)
   2124 %
   2125 %  A description of each parameter follows.
   2126 %
   2127 %    o image_info: the image info.
   2128 %
   2129 %    o image:  The image.
   2130 %
   2131 %    o exception: return any errors or warnings in this structure.
   2132 %
   2133 */
   2134 
   2135 static inline ssize_t SetPSDOffset(const PSDInfo *psd_info,Image *image,
   2136   const size_t offset)
   2137 {
   2138   if (psd_info->version == 1)
   2139     return(WriteBlobMSBShort(image,(unsigned short) offset));
   2140   return(WriteBlobMSBLong(image,(unsigned short) offset));
   2141 }
   2142 
   2143 static inline ssize_t SetPSDSize(const PSDInfo *psd_info,Image *image,
   2144   const MagickSizeType size)
   2145 {
   2146   if (psd_info->version == 1)
   2147     return(WriteBlobMSBLong(image,(unsigned int) size));
   2148   return(WriteBlobMSBLongLong(image,size));
   2149 }
   2150 
   2151 static size_t PSDPackbitsEncodeImage(Image *image,const size_t length,
   2152   const unsigned char *pixels,unsigned char *compact_pixels,
   2153   ExceptionInfo *exception)
   2154 {
   2155   int
   2156     count;
   2157 
   2158   register ssize_t
   2159     i,
   2160     j;
   2161 
   2162   register unsigned char
   2163     *q;
   2164 
   2165   unsigned char
   2166     *packbits;
   2167 
   2168   /*
   2169     Compress pixels with Packbits encoding.
   2170   */
   2171   assert(image != (Image *) NULL);
   2172   assert(image->signature == MagickCoreSignature);
   2173   if (image->debug != MagickFalse)
   2174     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2175   assert(pixels != (unsigned char *) NULL);
   2176   packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
   2177   if (packbits == (unsigned char *) NULL)
   2178     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   2179       image->filename);
   2180   q=compact_pixels;
   2181   for (i=(ssize_t) length; i != 0; )
   2182   {
   2183     switch (i)
   2184     {
   2185       case 1:
   2186       {
   2187         i--;
   2188         *q++=(unsigned char) 0;
   2189         *q++=(*pixels);
   2190         break;
   2191       }
   2192       case 2:
   2193       {
   2194         i-=2;
   2195         *q++=(unsigned char) 1;
   2196         *q++=(*pixels);
   2197         *q++=pixels[1];
   2198         break;
   2199       }
   2200       case 3:
   2201       {
   2202         i-=3;
   2203         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
   2204           {
   2205             *q++=(unsigned char) ((256-3)+1);
   2206             *q++=(*pixels);
   2207             break;
   2208           }
   2209         *q++=(unsigned char) 2;
   2210         *q++=(*pixels);
   2211         *q++=pixels[1];
   2212         *q++=pixels[2];
   2213         break;
   2214       }
   2215       default:
   2216       {
   2217         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
   2218           {
   2219             /*
   2220               Packed run.
   2221             */
   2222             count=3;
   2223             while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
   2224             {
   2225               count++;
   2226               if (count >= 127)
   2227                 break;
   2228             }
   2229             i-=count;
   2230             *q++=(unsigned char) ((256-count)+1);
   2231             *q++=(*pixels);
   2232             pixels+=count;
   2233             break;
   2234           }
   2235         /*
   2236           Literal run.
   2237         */
   2238         count=0;
   2239         while ((*(pixels+count) != *(pixels+count+1)) ||
   2240                (*(pixels+count+1) != *(pixels+count+2)))
   2241         {
   2242           packbits[count+1]=pixels[count];
   2243           count++;
   2244           if (((ssize_t) count >= (i-3)) || (count >= 127))
   2245             break;
   2246         }
   2247         i-=count;
   2248         *packbits=(unsigned char) (count-1);
   2249         for (j=0; j <= (ssize_t) count; j++)
   2250           *q++=packbits[j];
   2251         pixels+=count;
   2252         break;
   2253       }
   2254     }
   2255   }
   2256   *q++=(unsigned char) 128;  /* EOD marker */
   2257   packbits=(unsigned char *) RelinquishMagickMemory(packbits);
   2258   return((size_t) (q-compact_pixels));
   2259 }
   2260 
   2261 static void WritePackbitsLength(const PSDInfo *psd_info,
   2262   const ImageInfo *image_info,Image *image,Image *next_image,
   2263   unsigned char *compact_pixels,const QuantumType quantum_type,
   2264   ExceptionInfo *exception)
   2265 {
   2266   QuantumInfo
   2267     *quantum_info;
   2268 
   2269   register const Quantum
   2270     *p;
   2271 
   2272   size_t
   2273     length,
   2274     packet_size;
   2275 
   2276   ssize_t
   2277     y;
   2278 
   2279   unsigned char
   2280     *pixels;
   2281 
   2282   if (next_image->depth > 8)
   2283     next_image->depth=16;
   2284   packet_size=next_image->depth > 8UL ? 2UL : 1UL;
   2285   (void) packet_size;
   2286   quantum_info=AcquireQuantumInfo(image_info,image);
   2287   pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   2288   for (y=0; y < (ssize_t) next_image->rows; y++)
   2289   {
   2290     p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception);
   2291     if (p == (const Quantum *) NULL)
   2292       break;
   2293     length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info,
   2294       quantum_type,pixels,exception);
   2295     length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels,
   2296       exception);
   2297     (void) SetPSDOffset(psd_info,image,length);
   2298   }
   2299   quantum_info=DestroyQuantumInfo(quantum_info);
   2300 }
   2301 
   2302 static void WriteOneChannel(const PSDInfo *psd_info,const ImageInfo *image_info,
   2303   Image *image,Image *next_image,unsigned char *compact_pixels,
   2304   const QuantumType quantum_type,const MagickBooleanType compression_flag,
   2305   ExceptionInfo *exception)
   2306 {
   2307   int
   2308     y;
   2309 
   2310   MagickBooleanType
   2311     monochrome;
   2312 
   2313   QuantumInfo
   2314     *quantum_info;
   2315 
   2316   register const Quantum
   2317     *p;
   2318 
   2319   register ssize_t
   2320     i;
   2321 
   2322   size_t
   2323     length,
   2324     packet_size;
   2325 
   2326   unsigned char
   2327     *pixels;
   2328 
   2329   (void) psd_info;
   2330   if ((compression_flag != MagickFalse) &&
   2331       (next_image->compression != RLECompression))
   2332     (void) WriteBlobMSBShort(image,0);
   2333   if (next_image->depth > 8)
   2334     next_image->depth=16;
   2335   monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
   2336     MagickTrue : MagickFalse;
   2337   packet_size=next_image->depth > 8UL ? 2UL : 1UL;
   2338   (void) packet_size;
   2339   quantum_info=AcquireQuantumInfo(image_info,image);
   2340   pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   2341   for (y=0; y < (ssize_t) next_image->rows; y++)
   2342   {
   2343     p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception);
   2344     if (p == (const Quantum *) NULL)
   2345       break;
   2346     length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info,
   2347       quantum_type,pixels,exception);
   2348     if (monochrome != MagickFalse)
   2349       for (i=0; i < (ssize_t) length; i++)
   2350         pixels[i]=(~pixels[i]);
   2351     if (next_image->compression != RLECompression)
   2352       (void) WriteBlob(image,length,pixels);
   2353     else
   2354       {
   2355         length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels,
   2356           exception);
   2357         (void) WriteBlob(image,length,compact_pixels);
   2358       }
   2359   }
   2360   quantum_info=DestroyQuantumInfo(quantum_info);
   2361 }
   2362 
   2363 static MagickBooleanType WriteImageChannels(const PSDInfo *psd_info,
   2364   const ImageInfo *image_info,Image *image,Image *next_image,
   2365   const MagickBooleanType separate,ExceptionInfo *exception)
   2366 {
   2367   size_t
   2368     channels,
   2369     packet_size;
   2370 
   2371   unsigned char
   2372     *compact_pixels;
   2373 
   2374   /*
   2375     Write uncompressed pixels as separate planes.
   2376   */
   2377   channels=1;
   2378   packet_size=next_image->depth > 8UL ? 2UL : 1UL;
   2379   compact_pixels=(unsigned char *) NULL;
   2380   if (next_image->compression == RLECompression)
   2381     {
   2382       compact_pixels=(unsigned char *) AcquireQuantumMemory((9*channels*
   2383         next_image->columns)+1,packet_size*sizeof(*compact_pixels));
   2384       if (compact_pixels == (unsigned char *) NULL)
   2385         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   2386     }
   2387   if (IsImageGray(next_image) != MagickFalse)
   2388     {
   2389       if (next_image->compression == RLECompression)
   2390         {
   2391           /*
   2392             Packbits compression.
   2393           */
   2394           (void) WriteBlobMSBShort(image,1);
   2395           WritePackbitsLength(psd_info,image_info,image,next_image,
   2396             compact_pixels,GrayQuantum,exception);
   2397           if (next_image->alpha_trait != UndefinedPixelTrait)
   2398             WritePackbitsLength(psd_info,image_info,image,next_image,
   2399               compact_pixels,AlphaQuantum,exception);
   2400         }
   2401       WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2402         GrayQuantum,MagickTrue,exception);
   2403       if (next_image->alpha_trait != UndefinedPixelTrait)
   2404         WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2405           AlphaQuantum,separate,exception);
   2406       (void) SetImageProgress(image,SaveImagesTag,0,1);
   2407     }
   2408   else
   2409     if (next_image->storage_class == PseudoClass)
   2410       {
   2411         if (next_image->compression == RLECompression)
   2412           {
   2413             /*
   2414               Packbits compression.
   2415             */
   2416             (void) WriteBlobMSBShort(image,1);
   2417             WritePackbitsLength(psd_info,image_info,image,next_image,
   2418               compact_pixels,IndexQuantum,exception);
   2419             if (next_image->alpha_trait != UndefinedPixelTrait)
   2420               WritePackbitsLength(psd_info,image_info,image,next_image,
   2421                 compact_pixels,AlphaQuantum,exception);
   2422           }
   2423         WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2424           IndexQuantum,MagickTrue,exception);
   2425         if (next_image->alpha_trait != UndefinedPixelTrait)
   2426           WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2427             AlphaQuantum,separate,exception);
   2428         (void) SetImageProgress(image,SaveImagesTag,0,1);
   2429       }
   2430     else
   2431       {
   2432         if (next_image->colorspace == CMYKColorspace)
   2433           (void) NegateCMYK(next_image,exception);
   2434         if (next_image->compression == RLECompression)
   2435           {
   2436             /*
   2437               Packbits compression.
   2438             */
   2439             (void) WriteBlobMSBShort(image,1);
   2440             WritePackbitsLength(psd_info,image_info,image,next_image,
   2441               compact_pixels,RedQuantum,exception);
   2442             WritePackbitsLength(psd_info,image_info,image,next_image,
   2443               compact_pixels,GreenQuantum,exception);
   2444             WritePackbitsLength(psd_info,image_info,image,next_image,
   2445               compact_pixels,BlueQuantum,exception);
   2446             if (next_image->colorspace == CMYKColorspace)
   2447               WritePackbitsLength(psd_info,image_info,image,next_image,
   2448                 compact_pixels,BlackQuantum,exception);
   2449             if (next_image->alpha_trait != UndefinedPixelTrait)
   2450               WritePackbitsLength(psd_info,image_info,image,next_image,
   2451                 compact_pixels,AlphaQuantum,exception);
   2452           }
   2453         (void) SetImageProgress(image,SaveImagesTag,0,6);
   2454         WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2455           RedQuantum,MagickTrue,exception);
   2456         (void) SetImageProgress(image,SaveImagesTag,1,6);
   2457         WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2458           GreenQuantum,separate,exception);
   2459         (void) SetImageProgress(image,SaveImagesTag,2,6);
   2460         WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2461           BlueQuantum,separate,exception);
   2462         (void) SetImageProgress(image,SaveImagesTag,3,6);
   2463         if (next_image->colorspace == CMYKColorspace)
   2464           WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2465             BlackQuantum,separate,exception);
   2466         (void) SetImageProgress(image,SaveImagesTag,4,6);
   2467         if (next_image->alpha_trait != UndefinedPixelTrait)
   2468           WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels,
   2469             AlphaQuantum,separate,exception);
   2470         (void) SetImageProgress(image,SaveImagesTag,5,6);
   2471         if (next_image->colorspace == CMYKColorspace)
   2472           (void) NegateCMYK(next_image,exception);
   2473       }
   2474   if (next_image->compression == RLECompression)
   2475     compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   2476   return(MagickTrue);
   2477 }
   2478 
   2479 static void WritePascalString(Image* inImage,const char *inString,int inPad)
   2480 {
   2481   size_t
   2482     length;
   2483 
   2484   register ssize_t
   2485     i;
   2486 
   2487   /*
   2488     Max length is 255.
   2489   */
   2490   length=(strlen(inString) > 255UL ) ? 255UL : strlen(inString);
   2491   if (length ==  0)
   2492     (void) WriteBlobByte(inImage,0);
   2493   else
   2494     {
   2495       (void) WriteBlobByte(inImage,(unsigned char) length);
   2496       (void) WriteBlob(inImage, length, (const unsigned char *) inString);
   2497     }
   2498   length++;
   2499   if ((length % inPad) == 0)
   2500     return;
   2501   for (i=0; i < (ssize_t) (inPad-(length % inPad)); i++)
   2502     (void) WriteBlobByte(inImage,0);
   2503 }
   2504 
   2505 static void WriteResolutionResourceBlock(Image *image)
   2506 {
   2507   double
   2508     x_resolution,
   2509     y_resolution;
   2510 
   2511   unsigned short
   2512     units;
   2513 
   2514   if (image->units == PixelsPerCentimeterResolution)
   2515     {
   2516       x_resolution=2.54*65536.0*image->resolution.x+0.5;
   2517       y_resolution=2.54*65536.0*image->resolution.y+0.5;
   2518       units=2;
   2519     }
   2520   else
   2521     {
   2522       x_resolution=65536.0*image->resolution.x+0.5;
   2523       y_resolution=65536.0*image->resolution.y+0.5;
   2524       units=1;
   2525     }
   2526   (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
   2527   (void) WriteBlobMSBShort(image,0x03ED);
   2528   (void) WriteBlobMSBShort(image,0);
   2529   (void) WriteBlobMSBLong(image,16); /* resource size */
   2530   (void) WriteBlobMSBLong(image,(unsigned int) (x_resolution+0.5));
   2531   (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
   2532   (void) WriteBlobMSBShort(image,units); /* width unit */
   2533   (void) WriteBlobMSBLong(image,(unsigned int) (y_resolution+0.5));
   2534   (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
   2535   (void) WriteBlobMSBShort(image,units); /* height unit */
   2536 }
   2537 
   2538 static void RemoveICCProfileFromResourceBlock(StringInfo *bim_profile)
   2539 {
   2540   register const unsigned char
   2541     *p;
   2542 
   2543   size_t
   2544     length;
   2545 
   2546   unsigned char
   2547     *datum;
   2548 
   2549   unsigned int
   2550     count,
   2551     long_sans;
   2552 
   2553   unsigned short
   2554     id,
   2555     short_sans;
   2556 
   2557   length=GetStringInfoLength(bim_profile);
   2558   if (length < 16)
   2559     return;
   2560   datum=GetStringInfoDatum(bim_profile);
   2561   for (p=datum; (p >= datum) && (p < (datum+length-16)); )
   2562   {
   2563     register unsigned char
   2564       *q;
   2565 
   2566     q=(unsigned char *) p;
   2567     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
   2568       break;
   2569     p=PushLongPixel(MSBEndian,p,&long_sans);
   2570     p=PushShortPixel(MSBEndian,p,&id);
   2571     p=PushShortPixel(MSBEndian,p,&short_sans);
   2572     p=PushLongPixel(MSBEndian,p,&count);
   2573     if (id == 0x0000040f)
   2574       {
   2575         ssize_t
   2576           quantum;
   2577 
   2578         quantum=PSDQuantum(count)+12;
   2579         if ((quantum >= 12) && (q+quantum < (datum+length-16)))
   2580           {
   2581             (void) CopyMagickMemory(q,q+quantum,length-quantum-(q-datum));
   2582             SetStringInfoLength(bim_profile,length-quantum);
   2583           }
   2584         break;
   2585       }
   2586     p+=count;
   2587     if ((count & 0x01) != 0)
   2588       p++;
   2589   }
   2590 }
   2591 
   2592 static void RemoveResolutionFromResourceBlock(StringInfo *bim_profile)
   2593 {
   2594   register const unsigned char
   2595     *p;
   2596 
   2597   size_t
   2598     length;
   2599 
   2600   unsigned char
   2601     *datum;
   2602 
   2603   unsigned int
   2604     count,
   2605     long_sans;
   2606 
   2607   unsigned short
   2608     id,
   2609     short_sans;
   2610 
   2611   length=GetStringInfoLength(bim_profile);
   2612   if (length < 16)
   2613     return;
   2614   datum=GetStringInfoDatum(bim_profile);
   2615   for (p=datum; (p >= datum) && (p < (datum+length-16)); )
   2616   {
   2617     register unsigned char
   2618       *q;
   2619 
   2620     ssize_t
   2621       cnt;
   2622 
   2623     q=(unsigned char *) p;
   2624     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
   2625       return;
   2626     p=PushLongPixel(MSBEndian,p,&long_sans);
   2627     p=PushShortPixel(MSBEndian,p,&id);
   2628     p=PushShortPixel(MSBEndian,p,&short_sans);
   2629     p=PushLongPixel(MSBEndian,p,&count);
   2630     cnt=PSDQuantum(count);
   2631     if (cnt < 0)
   2632       return;
   2633     if ((id == 0x000003ed) && (cnt < (ssize_t) (length-12)))
   2634       {
   2635         (void) CopyMagickMemory(q,q+cnt+12,length-(cnt+12)-(q-datum));
   2636         SetStringInfoLength(bim_profile,length-(cnt+12));
   2637         break;
   2638       }
   2639     p+=count;
   2640     if ((count & 0x01) != 0)
   2641       p++;
   2642   }
   2643 }
   2644 
   2645 static MagickBooleanType WritePSDImage(const ImageInfo *image_info,
   2646   Image *image,ExceptionInfo *exception)
   2647 {
   2648   const char
   2649     *property;
   2650 
   2651   const StringInfo
   2652     *icc_profile;
   2653 
   2654   Image
   2655     *base_image,
   2656     *next_image;
   2657 
   2658   MagickBooleanType
   2659     status;
   2660 
   2661   PSDInfo
   2662     psd_info;
   2663 
   2664   register ssize_t
   2665     i;
   2666 
   2667   size_t
   2668     channel_size,
   2669     channelLength,
   2670     layer_count,
   2671     layer_info_size,
   2672     length,
   2673     num_channels,
   2674     packet_size,
   2675     rounded_layer_info_size;
   2676 
   2677   StringInfo
   2678     *bim_profile;
   2679 
   2680   /*
   2681     Open image file.
   2682   */
   2683   assert(image_info != (const ImageInfo *) NULL);
   2684   assert(image_info->signature == MagickCoreSignature);
   2685   assert(image != (Image *) NULL);
   2686   assert(image->signature == MagickCoreSignature);
   2687   if (image->debug != MagickFalse)
   2688     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2689   assert(exception != (ExceptionInfo *) NULL);
   2690   assert(exception->signature == MagickCoreSignature);
   2691   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   2692   if (status == MagickFalse)
   2693     return(status);
   2694   packet_size=(size_t) (image->depth > 8 ? 6 : 3);
   2695   if (image->alpha_trait != UndefinedPixelTrait)
   2696     packet_size+=image->depth > 8 ? 2 : 1;
   2697   psd_info.version=1;
   2698   if ((LocaleCompare(image_info->magick,"PSB") == 0) ||
   2699       (image->columns > 30000) || (image->rows > 30000))
   2700     psd_info.version=2;
   2701   (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
   2702   (void) WriteBlobMSBShort(image,psd_info.version);  /* version */
   2703   for (i=1; i <= 6; i++)
   2704     (void) WriteBlobByte(image, 0);  /* 6 bytes of reserved */
   2705   if (SetImageGray(image,exception) != MagickFalse)
   2706     num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
   2707   else
   2708     if ((image_info->type != TrueColorType) && (image_info->type !=
   2709          TrueColorAlphaType) && (image->storage_class == PseudoClass))
   2710       num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
   2711     else
   2712       {
   2713         if (image->storage_class == PseudoClass)
   2714           (void) SetImageStorageClass(image,DirectClass,exception);
   2715         if (image->colorspace != CMYKColorspace)
   2716           num_channels=(image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL);
   2717         else
   2718           num_channels=(image->alpha_trait != UndefinedPixelTrait ? 5UL : 4UL);
   2719       }
   2720   (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
   2721   (void) WriteBlobMSBLong(image,(unsigned int) image->rows);
   2722   (void) WriteBlobMSBLong(image,(unsigned int) image->columns);
   2723   if (IsImageGray(image) != MagickFalse)
   2724     {
   2725       MagickBooleanType
   2726         monochrome;
   2727 
   2728       /*
   2729         Write depth & mode.
   2730       */
   2731       monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
   2732         MagickTrue : MagickFalse;
   2733       (void) WriteBlobMSBShort(image,(unsigned short)
   2734         (monochrome != MagickFalse ? 1 : image->depth > 8 ? 16 : 8));
   2735       (void) WriteBlobMSBShort(image,(unsigned short)
   2736         (monochrome != MagickFalse ? BitmapMode : GrayscaleMode));
   2737     }
   2738   else
   2739     {
   2740       (void) WriteBlobMSBShort(image,(unsigned short) (image->storage_class ==
   2741         PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
   2742 
   2743       if (((image_info->colorspace != UndefinedColorspace) ||
   2744            (image->colorspace != CMYKColorspace)) &&
   2745           (image_info->colorspace != CMYKColorspace))
   2746         {
   2747           (void) TransformImageColorspace(image,sRGBColorspace,exception);
   2748           (void) WriteBlobMSBShort(image,(unsigned short)
   2749             (image->storage_class == PseudoClass ? IndexedMode : RGBMode));
   2750         }
   2751       else
   2752         {
   2753           if (image->colorspace != CMYKColorspace)
   2754             (void) TransformImageColorspace(image,CMYKColorspace,exception);
   2755           (void) WriteBlobMSBShort(image,CMYKMode);
   2756         }
   2757     }
   2758   if ((IsImageGray(image) != MagickFalse) ||
   2759       (image->storage_class == DirectClass) || (image->colors > 256))
   2760     (void) WriteBlobMSBLong(image,0);
   2761   else
   2762     {
   2763       /*
   2764         Write PSD raster colormap.
   2765       */
   2766       (void) WriteBlobMSBLong(image,768);
   2767       for (i=0; i < (ssize_t) image->colors; i++)
   2768         (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
   2769       for ( ; i < 256; i++)
   2770         (void) WriteBlobByte(image,0);
   2771       for (i=0; i < (ssize_t) image->colors; i++)
   2772         (void) WriteBlobByte(image,ScaleQuantumToChar(
   2773           image->colormap[i].green));
   2774       for ( ; i < 256; i++)
   2775         (void) WriteBlobByte(image,0);
   2776       for (i=0; i < (ssize_t) image->colors; i++)
   2777         (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
   2778       for ( ; i < 256; i++)
   2779         (void) WriteBlobByte(image,0);
   2780     }
   2781   /*
   2782     Image resource block.
   2783   */
   2784   length=28; /* 0x03EB */
   2785   bim_profile=(StringInfo *) GetImageProfile(image,"8bim");
   2786   icc_profile=GetImageProfile(image,"icc");
   2787   if (bim_profile != (StringInfo *) NULL)
   2788     {
   2789       bim_profile=CloneStringInfo(bim_profile);
   2790       if (icc_profile != (StringInfo *) NULL)
   2791         RemoveICCProfileFromResourceBlock(bim_profile);
   2792       RemoveResolutionFromResourceBlock(bim_profile);
   2793       length+=PSDQuantum(GetStringInfoLength(bim_profile));
   2794     }
   2795   if (icc_profile != (const StringInfo *) NULL)
   2796     length+=PSDQuantum(GetStringInfoLength(icc_profile))+12;
   2797   (void) WriteBlobMSBLong(image,(unsigned int) length);
   2798   WriteResolutionResourceBlock(image);
   2799   if (bim_profile != (StringInfo *) NULL)
   2800     {
   2801       (void) WriteBlob(image,GetStringInfoLength(bim_profile),
   2802         GetStringInfoDatum(bim_profile));
   2803       bim_profile=DestroyStringInfo(bim_profile);
   2804     }
   2805   if (icc_profile != (StringInfo *) NULL)
   2806     {
   2807       (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
   2808       (void) WriteBlobMSBShort(image,0x0000040F);
   2809       (void) WriteBlobMSBShort(image,0);
   2810       (void) WriteBlobMSBLong(image,(unsigned int) GetStringInfoLength(
   2811         icc_profile));
   2812       (void) WriteBlob(image,GetStringInfoLength(icc_profile),
   2813         GetStringInfoDatum(icc_profile));
   2814       if ((MagickOffsetType) GetStringInfoLength(icc_profile) !=
   2815           PSDQuantum(GetStringInfoLength(icc_profile)))
   2816         (void) WriteBlobByte(image,0);
   2817     }
   2818   layer_count=0;
   2819   layer_info_size=2;
   2820   base_image=GetNextImageInList(image);
   2821   if (base_image == (Image *) NULL)
   2822     base_image=image;
   2823   next_image=base_image;
   2824   while (next_image != (Image *) NULL)
   2825   {
   2826     packet_size=next_image->depth > 8 ? 2UL : 1UL;
   2827     if (IsImageGray(next_image) != MagickFalse)
   2828       num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL;
   2829     else
   2830       if (next_image->storage_class == PseudoClass)
   2831         num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL;
   2832       else
   2833         if (next_image->colorspace != CMYKColorspace)
   2834           num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL;
   2835         else
   2836           num_channels=next_image->alpha_trait != UndefinedPixelTrait ? 5UL : 4UL;
   2837     channelLength=(size_t) (next_image->columns*next_image->rows*packet_size+2);
   2838     layer_info_size+=(size_t) (4*4+2+num_channels*6+(psd_info.version == 1 ? 8 :
   2839       16)+4*1+4+num_channels*channelLength);
   2840     property=(const char *) GetImageProperty(next_image,"label",exception);
   2841     if (property == (const char *) NULL)
   2842       layer_info_size+=16;
   2843     else
   2844       {
   2845         size_t
   2846           layer_length;
   2847 
   2848         layer_length=strlen(property);
   2849         layer_info_size+=8+layer_length+(4-(layer_length % 4));
   2850       }
   2851     layer_count++;
   2852     next_image=GetNextImageInList(next_image);
   2853   }
   2854   if (layer_count == 0)
   2855     (void) SetPSDSize(&psd_info,image,0);
   2856   else
   2857     {
   2858       CompressionType
   2859         compression;
   2860 
   2861       (void) SetPSDSize(&psd_info,image,layer_info_size+
   2862         (psd_info.version == 1 ? 8 : 16));
   2863       if ((layer_info_size/2) != ((layer_info_size+1)/2))
   2864         rounded_layer_info_size=layer_info_size+1;
   2865       else
   2866         rounded_layer_info_size=layer_info_size;
   2867       (void) SetPSDSize(&psd_info,image,rounded_layer_info_size);
   2868       if (image->alpha_trait != UndefinedPixelTrait)
   2869         (void) WriteBlobMSBShort(image,-(unsigned short) layer_count);
   2870       else
   2871         (void) WriteBlobMSBShort(image,(unsigned short) layer_count);
   2872       layer_count=1;
   2873       compression=base_image->compression;
   2874       for (next_image=base_image; next_image != NULL; )
   2875       {
   2876         next_image->compression=NoCompression;
   2877         (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.y);
   2878         (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.x);
   2879         (void) WriteBlobMSBLong(image,(unsigned int) (next_image->page.y+
   2880           next_image->rows));
   2881         (void) WriteBlobMSBLong(image,(unsigned int) (next_image->page.x+
   2882           next_image->columns));
   2883         packet_size=next_image->depth > 8 ? 2UL : 1UL;
   2884         channel_size=(unsigned int) ((packet_size*next_image->rows*
   2885           next_image->columns)+2);
   2886         if ((IsImageGray(next_image) != MagickFalse) ||
   2887             (next_image->storage_class == PseudoClass))
   2888           {
   2889              (void) WriteBlobMSBShort(image,(unsigned short)
   2890                (next_image->alpha_trait != UndefinedPixelTrait ? 2 : 1));
   2891              (void) WriteBlobMSBShort(image,0);
   2892              (void) SetPSDSize(&psd_info,image,channel_size);
   2893              if (next_image->alpha_trait != UndefinedPixelTrait)
   2894                {
   2895                  (void) WriteBlobMSBShort(image,(unsigned short) -1);
   2896                  (void) SetPSDSize(&psd_info,image,channel_size);
   2897                }
   2898            }
   2899           else
   2900             if (next_image->colorspace != CMYKColorspace)
   2901               {
   2902                 (void) WriteBlobMSBShort(image,(unsigned short)
   2903                   (next_image->alpha_trait != UndefinedPixelTrait ? 4 : 3));
   2904                (void) WriteBlobMSBShort(image,0);
   2905                (void) SetPSDSize(&psd_info,image,channel_size);
   2906                (void) WriteBlobMSBShort(image,1);
   2907                (void) SetPSDSize(&psd_info,image,channel_size);
   2908                (void) WriteBlobMSBShort(image,2);
   2909                (void) SetPSDSize(&psd_info,image,channel_size);
   2910                if (next_image->alpha_trait != UndefinedPixelTrait)
   2911                  {
   2912                    (void) WriteBlobMSBShort(image,(unsigned short) -1);
   2913                    (void) SetPSDSize(&psd_info,image,channel_size);
   2914                  }
   2915              }
   2916            else
   2917              {
   2918                (void) WriteBlobMSBShort(image,(unsigned short)
   2919                  (next_image->alpha_trait ? 5 : 4));
   2920                (void) WriteBlobMSBShort(image,0);
   2921                (void) SetPSDSize(&psd_info,image,channel_size);
   2922                (void) WriteBlobMSBShort(image,1);
   2923                (void) SetPSDSize(&psd_info,image,channel_size);
   2924                (void) WriteBlobMSBShort(image,2);
   2925                (void) SetPSDSize(&psd_info,image,channel_size);
   2926                (void) WriteBlobMSBShort(image,3);
   2927                (void) SetPSDSize(&psd_info,image,channel_size);
   2928                if (next_image->alpha_trait)
   2929                  {
   2930                    (void) WriteBlobMSBShort(image,(unsigned short) -1);
   2931                    (void) SetPSDSize(&psd_info,image,channel_size);
   2932                  }
   2933              }
   2934         (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
   2935         (void) WriteBlob(image,4,(const unsigned char *)
   2936           CompositeOperatorToPSDBlendMode(next_image->compose));
   2937         (void) WriteBlobByte(image,255); /* layer opacity */
   2938         (void) WriteBlobByte(image,0);
   2939         (void) WriteBlobByte(image,next_image->compose==NoCompositeOp ?
   2940           1 << 0x02 : 1); /* layer properties - visible, etc. */
   2941         (void) WriteBlobByte(image,0);
   2942         property=(const char *) GetImageProperty(next_image,"label",exception);
   2943         if (property == (const char *) NULL)
   2944           {
   2945             char
   2946               layer_name[MagickPathExtent];
   2947 
   2948             (void) WriteBlobMSBLong(image,16);
   2949             (void) WriteBlobMSBLong(image,0);
   2950             (void) WriteBlobMSBLong(image,0);
   2951             (void) FormatLocaleString(layer_name,MagickPathExtent,"L%04ld",(long)
   2952               layer_count++);
   2953             WritePascalString(image,layer_name,4);
   2954           }
   2955         else
   2956           {
   2957             size_t
   2958               label_length;
   2959 
   2960             label_length=strlen(property);
   2961             (void) WriteBlobMSBLong(image,(unsigned int) (label_length+(4-
   2962               (label_length % 4))+8));
   2963             (void) WriteBlobMSBLong(image,0);
   2964             (void) WriteBlobMSBLong(image,0);
   2965             WritePascalString(image,property,4);
   2966           }
   2967         next_image=GetNextImageInList(next_image);
   2968       }
   2969       /*
   2970         Now the image data!
   2971       */
   2972       next_image=base_image;
   2973       while (next_image != NULL)
   2974       {
   2975         status=WriteImageChannels(&psd_info,image_info,image,next_image,
   2976           MagickTrue,exception);
   2977         next_image=GetNextImageInList(next_image);
   2978       }
   2979       (void) WriteBlobMSBLong(image,0);  /* user mask data */
   2980       base_image->compression=compression;
   2981     }
   2982   /*
   2983     Write composite image.
   2984   */
   2985   if (status != MagickFalse)
   2986     status=WriteImageChannels(&psd_info,image_info,image,image,MagickFalse,
   2987       exception);
   2988   (void) CloseBlob(image);
   2989   return(status);
   2990 }
   2991