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-2019 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 %    https://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 % Photoshop spec @ https://www.adobe.com/devnet-apps/photoshop/fileformatashtml
     40 %
     41 */
     42 
     43 /*
     45   Include declarations.
     46 */
     47 #include "MagickCore/studio.h"
     48 #include "MagickCore/artifact.h"
     49 #include "MagickCore/attribute.h"
     50 #include "MagickCore/blob.h"
     51 #include "MagickCore/blob-private.h"
     52 #include "MagickCore/cache.h"
     53 #include "MagickCore/channel.h"
     54 #include "MagickCore/colormap.h"
     55 #include "MagickCore/colormap-private.h"
     56 #include "MagickCore/colorspace.h"
     57 #include "MagickCore/colorspace-private.h"
     58 #include "MagickCore/constitute.h"
     59 #include "MagickCore/enhance.h"
     60 #include "MagickCore/exception.h"
     61 #include "MagickCore/exception-private.h"
     62 #include "MagickCore/image.h"
     63 #include "MagickCore/image-private.h"
     64 #include "MagickCore/list.h"
     65 #include "MagickCore/log.h"
     66 #include "MagickCore/magick.h"
     67 #include "MagickCore/memory_.h"
     68 #include "MagickCore/module.h"
     69 #include "MagickCore/monitor-private.h"
     70 #include "MagickCore/option.h"
     71 #include "MagickCore/pixel.h"
     72 #include "MagickCore/pixel-accessor.h"
     73 #include "MagickCore/policy.h"
     74 #include "MagickCore/profile.h"
     75 #include "MagickCore/property.h"
     76 #include "MagickCore/registry.h"
     77 #include "MagickCore/quantum-private.h"
     78 #include "MagickCore/static.h"
     79 #include "MagickCore/string_.h"
     80 #include "MagickCore/string-private.h"
     81 #include "MagickCore/thread-private.h"
     82 #ifdef MAGICKCORE_ZLIB_DELEGATE
     83 #include <zlib.h>
     84 #endif
     85 #include "psd-private.h"
     86 
     87 /*
     88   Define declaractions.
     89 */
     90 #define MaxPSDChannels  56
     91 #define PSDQuantum(x) (((ssize_t) (x)+1) & -2)
     92 
     93 /*
     95   Enumerated declaractions.
     96 */
     97 typedef enum
     98 {
     99   Raw = 0,
    100   RLE = 1,
    101   ZipWithoutPrediction = 2,
    102   ZipWithPrediction = 3
    103 } PSDCompressionType;
    104 
    105 typedef enum
    106 {
    107   BitmapMode = 0,
    108   GrayscaleMode = 1,
    109   IndexedMode = 2,
    110   RGBMode = 3,
    111   CMYKMode = 4,
    112   MultichannelMode = 7,
    113   DuotoneMode = 8,
    114   LabMode = 9
    115 } PSDImageType;
    116 
    117 /*
    119   Typedef declaractions.
    120 */
    121 typedef struct _ChannelInfo
    122 {
    123   short
    124     type;
    125 
    126   size_t
    127     size;
    128 } ChannelInfo;
    129 
    130 typedef struct _MaskInfo
    131 {
    132   Image
    133     *image;
    134 
    135   RectangleInfo
    136     page;
    137 
    138   unsigned char
    139     background,
    140     flags;
    141 } MaskInfo;
    142 
    143 typedef struct _LayerInfo
    144 {
    145   ChannelInfo
    146     channel_info[MaxPSDChannels];
    147 
    148   char
    149     blendkey[4];
    150 
    151   Image
    152     *image;
    153 
    154   MaskInfo
    155     mask;
    156 
    157   Quantum
    158     opacity;
    159 
    160   RectangleInfo
    161     page;
    162 
    163   size_t
    164     offset_x,
    165     offset_y;
    166 
    167   unsigned char
    168     clipping,
    169     flags,
    170     name[257],
    171     visible;
    172 
    173   unsigned short
    174     channels;
    175 
    176   StringInfo
    177     *info;
    178 } LayerInfo;
    179 
    180 /*
    181   Forward declarations.
    182 */
    183 static MagickBooleanType
    184   WritePSDImage(const ImageInfo *,Image *,ExceptionInfo *);
    185 
    186 /*
    188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    189 %                                                                             %
    190 %                                                                             %
    191 %                                                                             %
    192 %   I s P S D                                                                 %
    193 %                                                                             %
    194 %                                                                             %
    195 %                                                                             %
    196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    197 %
    198 %  IsPSD()() returns MagickTrue if the image format type, identified by the
    199 %  magick string, is PSD.
    200 %
    201 %  The format of the IsPSD method is:
    202 %
    203 %      MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
    204 %
    205 %  A description of each parameter follows:
    206 %
    207 %    o magick: compare image format pattern against these bytes.
    208 %
    209 %    o length: Specifies the length of the magick string.
    210 %
    211 */
    212 static MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
    213 {
    214   if (length < 4)
    215     return(MagickFalse);
    216   if (LocaleNCompare((const char *) magick,"8BPS",4) == 0)
    217     return(MagickTrue);
    218   return(MagickFalse);
    219 }
    220 
    221 /*
    223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    224 %                                                                             %
    225 %                                                                             %
    226 %                                                                             %
    227 %   R e a d P S D I m a g e                                                   %
    228 %                                                                             %
    229 %                                                                             %
    230 %                                                                             %
    231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    232 %
    233 %  ReadPSDImage() reads an Adobe Photoshop image file and returns it.  It
    234 %  allocates the memory necessary for the new Image structure and returns a
    235 %  pointer to the new image.
    236 %
    237 %  The format of the ReadPSDImage method is:
    238 %
    239 %      Image *ReadPSDImage(image_info,ExceptionInfo *exception)
    240 %
    241 %  A description of each parameter follows:
    242 %
    243 %    o image_info: the image info.
    244 %
    245 %    o exception: return any errors or warnings in this structure.
    246 %
    247 */
    248 
    249 static const char *CompositeOperatorToPSDBlendMode(Image *image)
    250 {
    251   switch (image->compose)
    252   {
    253     case ColorBurnCompositeOp:
    254       return(image->endian == LSBEndian ? "vidi" : "idiv");
    255     case ColorDodgeCompositeOp:
    256       return(image->endian == LSBEndian ? " vid" : "div ");
    257     case ColorizeCompositeOp:
    258       return(image->endian == LSBEndian ? "rloc" : "colr");
    259     case DarkenCompositeOp:
    260       return(image->endian == LSBEndian ? "krad" : "dark");
    261     case DifferenceCompositeOp:
    262       return(image->endian == LSBEndian ? "ffid" : "diff");
    263     case DissolveCompositeOp:
    264       return(image->endian == LSBEndian ? "ssid" : "diss");
    265     case ExclusionCompositeOp:
    266       return(image->endian == LSBEndian ? "dums" : "smud");
    267     case HardLightCompositeOp:
    268       return(image->endian == LSBEndian ? "tiLh" : "hLit");
    269     case HardMixCompositeOp:
    270       return(image->endian == LSBEndian ? "xiMh" : "hMix");
    271     case HueCompositeOp:
    272       return(image->endian == LSBEndian ? " euh" : "hue ");
    273     case LightenCompositeOp:
    274       return(image->endian == LSBEndian ? "etil" : "lite");
    275     case LinearBurnCompositeOp:
    276       return(image->endian == LSBEndian ? "nrbl" : "lbrn");
    277     case LinearDodgeCompositeOp:
    278       return(image->endian == LSBEndian ? "gddl" : "lddg");
    279     case LinearLightCompositeOp:
    280       return(image->endian == LSBEndian ? "tiLl" : "lLit");
    281     case LuminizeCompositeOp:
    282       return(image->endian == LSBEndian ? " mul" : "lum ");
    283     case MultiplyCompositeOp:
    284       return(image->endian == LSBEndian ? " lum" : "mul ");
    285     case OverlayCompositeOp:
    286       return(image->endian == LSBEndian ? "revo" : "over");
    287     case PinLightCompositeOp:
    288       return(image->endian == LSBEndian ? "tiLp" : "pLit");
    289     case SaturateCompositeOp:
    290       return(image->endian == LSBEndian ? " tas" : "sat ");
    291     case ScreenCompositeOp:
    292       return(image->endian == LSBEndian ? "nrcs" : "scrn");
    293     case SoftLightCompositeOp:
    294       return(image->endian == LSBEndian ? "tiLs" : "sLit");
    295     case VividLightCompositeOp:
    296       return(image->endian == LSBEndian ? "tiLv" : "vLit");
    297     case OverCompositeOp:
    298     default:
    299       return(image->endian == LSBEndian ? "mron" : "norm");
    300   }
    301 }
    302 
    303 /*
    304   For some reason Photoshop seems to blend semi-transparent pixels with white.
    305   This method reverts the blending. This can be disabled by setting the
    306   option 'psd:alpha-unblend' to off.
    307 */
    308 static MagickBooleanType CorrectPSDAlphaBlend(const ImageInfo *image_info,
    309   Image *image,ExceptionInfo* exception)
    310 {
    311   const char
    312     *option;
    313 
    314   MagickBooleanType
    315     status;
    316 
    317   ssize_t
    318     y;
    319 
    320   if (image->alpha_trait != BlendPixelTrait || image->colorspace != sRGBColorspace)
    321     return(MagickTrue);
    322   option=GetImageOption(image_info,"psd:alpha-unblend");
    323   if (IsStringFalse(option) != MagickFalse)
    324     return(MagickTrue);
    325   status=MagickTrue;
    326 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    327 #pragma omp parallel for schedule(static) shared(status) \
    328   magick_number_threads(image,image,image->rows,1)
    329 #endif
    330   for (y=0; y < (ssize_t) image->rows; y++)
    331   {
    332     register Quantum
    333       *magick_restrict q;
    334 
    335     register ssize_t
    336       x;
    337 
    338     if (status == MagickFalse)
    339       continue;
    340     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    341     if (q == (Quantum *) NULL)
    342     {
    343       status=MagickFalse;
    344       continue;
    345     }
    346     for (x=0; x < (ssize_t) image->columns; x++)
    347     {
    348       double
    349         gamma;
    350 
    351       register ssize_t
    352         i;
    353 
    354       gamma=QuantumScale*GetPixelAlpha(image, q);
    355       if (gamma != 0.0 && gamma != 1.0)
    356         {
    357           for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
    358           {
    359             PixelChannel channel = GetPixelChannelChannel(image,i);
    360             if (channel != AlphaPixelChannel)
    361               q[i]=ClampToQuantum((q[i]-((1.0-gamma)*QuantumRange))/gamma);
    362           }
    363         }
    364       q+=GetPixelChannels(image);
    365     }
    366     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    367       status=MagickFalse;
    368   }
    369 
    370   return(status);
    371 }
    372 
    373 static inline CompressionType ConvertPSDCompression(
    374   PSDCompressionType compression)
    375 {
    376   switch (compression)
    377   {
    378     case RLE:
    379       return RLECompression;
    380     case ZipWithPrediction:
    381     case ZipWithoutPrediction:
    382       return ZipCompression;
    383     default:
    384       return NoCompression;
    385   }
    386 }
    387 
    388 static MagickBooleanType ApplyPSDLayerOpacity(Image *image,Quantum opacity,
    389   MagickBooleanType revert,ExceptionInfo *exception)
    390 {
    391   MagickBooleanType
    392     status;
    393 
    394   ssize_t
    395     y;
    396 
    397   if (image->debug != MagickFalse)
    398     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
    399       "  applying layer opacity %.20g", (double) opacity);
    400   if (opacity == OpaqueAlpha)
    401     return(MagickTrue);
    402   if (image->alpha_trait != BlendPixelTrait)
    403     (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
    404   status=MagickTrue;
    405 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    406 #pragma omp parallel for schedule(static) shared(status) \
    407   magick_number_threads(image,image,image->rows,1)
    408 #endif
    409   for (y=0; y < (ssize_t) image->rows; y++)
    410   {
    411     register Quantum
    412       *magick_restrict q;
    413 
    414     register ssize_t
    415       x;
    416 
    417     if (status == MagickFalse)
    418       continue;
    419     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    420     if (q == (Quantum *) NULL)
    421       {
    422         status=MagickFalse;
    423         continue;
    424       }
    425     for (x=0; x < (ssize_t) image->columns; x++)
    426     {
    427       if (revert == MagickFalse)
    428         SetPixelAlpha(image,(Quantum) (QuantumScale*(GetPixelAlpha(image,q))*
    429           opacity),q);
    430       else if (opacity > 0)
    431         SetPixelAlpha(image,(Quantum) (QuantumRange*(GetPixelAlpha(image,q)/
    432           (MagickRealType) opacity)),q);
    433       q+=GetPixelChannels(image);
    434     }
    435     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    436       status=MagickFalse;
    437   }
    438 
    439   return(status);
    440 }
    441 
    442 static MagickBooleanType ApplyPSDOpacityMask(Image *image,const Image *mask,
    443   Quantum background,MagickBooleanType revert,ExceptionInfo *exception)
    444 {
    445   Image
    446     *complete_mask;
    447 
    448   MagickBooleanType
    449     status;
    450 
    451   PixelInfo
    452     color;
    453 
    454   ssize_t
    455     y;
    456 
    457   if (image->alpha_trait == UndefinedPixelTrait)
    458     return(MagickTrue);
    459   if (image->debug != MagickFalse)
    460     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
    461       "  applying opacity mask");
    462   complete_mask=CloneImage(image,0,0,MagickTrue,exception);
    463   if (complete_mask == (Image *) NULL)
    464     return(MagickFalse);
    465   complete_mask->alpha_trait=BlendPixelTrait;
    466   GetPixelInfo(complete_mask,&color);
    467   color.red=(MagickRealType) background;
    468   (void) SetImageColor(complete_mask,&color,exception);
    469   status=CompositeImage(complete_mask,mask,OverCompositeOp,MagickTrue,
    470     mask->page.x-image->page.x,mask->page.y-image->page.y,exception);
    471   if (status == MagickFalse)
    472     {
    473       complete_mask=DestroyImage(complete_mask);
    474       return(status);
    475     }
    476 
    477 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    478 #pragma omp parallel for schedule(static) shared(status) \
    479   magick_number_threads(image,image,image->rows,1)
    480 #endif
    481   for (y=0; y < (ssize_t) image->rows; y++)
    482   {
    483     register Quantum
    484       *magick_restrict q;
    485 
    486     register Quantum
    487       *p;
    488 
    489     register ssize_t
    490       x;
    491 
    492     if (status == MagickFalse)
    493       continue;
    494     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    495     p=GetAuthenticPixels(complete_mask,0,y,complete_mask->columns,1,exception);
    496     if ((q == (Quantum *) NULL) || (p == (Quantum *) NULL))
    497       {
    498         status=MagickFalse;
    499         continue;
    500       }
    501     for (x=0; x < (ssize_t) image->columns; x++)
    502     {
    503       MagickRealType
    504         alpha,
    505         intensity;
    506 
    507       alpha=(MagickRealType) GetPixelAlpha(image,q);
    508       intensity=GetPixelIntensity(complete_mask,p);
    509       if (revert == MagickFalse)
    510         SetPixelAlpha(image,ClampToQuantum(intensity*(QuantumScale*alpha)),q);
    511       else if (intensity > 0)
    512         SetPixelAlpha(image,ClampToQuantum((alpha/intensity)*QuantumRange),q);
    513       q+=GetPixelChannels(image);
    514       p+=GetPixelChannels(complete_mask);
    515     }
    516     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    517       status=MagickFalse;
    518   }
    519   complete_mask=DestroyImage(complete_mask);
    520   return(status);
    521 }
    522 
    523 static void PreservePSDOpacityMask(Image *image,LayerInfo* layer_info,
    524   ExceptionInfo *exception)
    525 {
    526   char
    527     *key;
    528 
    529   RandomInfo
    530     *random_info;
    531 
    532   StringInfo
    533     *key_info;
    534 
    535   if (image->debug != MagickFalse)
    536     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
    537       "  preserving opacity mask");
    538   random_info=AcquireRandomInfo();
    539   key_info=GetRandomKey(random_info,2+1);
    540   key=(char *) GetStringInfoDatum(key_info);
    541   key[8]=(char ) layer_info->mask.background;
    542   key[9]='\0';
    543   layer_info->mask.image->page.x+=layer_info->page.x;
    544   layer_info->mask.image->page.y+=layer_info->page.y;
    545   (void) SetImageRegistry(ImageRegistryType,(const char *) key,
    546     layer_info->mask.image,exception);
    547   (void) SetImageArtifact(layer_info->image,"psd:opacity-mask",
    548     (const char *) key);
    549   key_info=DestroyStringInfo(key_info);
    550   random_info=DestroyRandomInfo(random_info);
    551 }
    552 
    553 static ssize_t DecodePSDPixels(const size_t number_compact_pixels,
    554   const unsigned char *compact_pixels,const ssize_t depth,
    555   const size_t number_pixels,unsigned char *pixels)
    556 {
    557 #define CheckNumberCompactPixels \
    558   if (packets == 0) \
    559     return(i); \
    560   packets--
    561 
    562 #define CheckNumberPixels(count) \
    563   if (((ssize_t) i + count) > (ssize_t) number_pixels) \
    564     return(i); \
    565   i+=count
    566 
    567   int
    568     pixel;
    569 
    570   register ssize_t
    571     i,
    572     j;
    573 
    574   size_t
    575     length;
    576 
    577   ssize_t
    578     packets;
    579 
    580   packets=(ssize_t) number_compact_pixels;
    581   for (i=0; (packets > 1) && (i < (ssize_t) number_pixels); )
    582   {
    583     packets--;
    584     length=(size_t) (*compact_pixels++);
    585     if (length == 128)
    586       continue;
    587     if (length > 128)
    588       {
    589         length=256-length+1;
    590         CheckNumberCompactPixels;
    591         pixel=(*compact_pixels++);
    592         for (j=0; j < (ssize_t) length; j++)
    593         {
    594           switch (depth)
    595           {
    596             case 1:
    597             {
    598               CheckNumberPixels(8);
    599               *pixels++=(pixel >> 7) & 0x01 ? 0U : 255U;
    600               *pixels++=(pixel >> 6) & 0x01 ? 0U : 255U;
    601               *pixels++=(pixel >> 5) & 0x01 ? 0U : 255U;
    602               *pixels++=(pixel >> 4) & 0x01 ? 0U : 255U;
    603               *pixels++=(pixel >> 3) & 0x01 ? 0U : 255U;
    604               *pixels++=(pixel >> 2) & 0x01 ? 0U : 255U;
    605               *pixels++=(pixel >> 1) & 0x01 ? 0U : 255U;
    606               *pixels++=(pixel >> 0) & 0x01 ? 0U : 255U;
    607               break;
    608             }
    609             case 2:
    610             {
    611               CheckNumberPixels(4);
    612               *pixels++=(unsigned char) ((pixel >> 6) & 0x03);
    613               *pixels++=(unsigned char) ((pixel >> 4) & 0x03);
    614               *pixels++=(unsigned char) ((pixel >> 2) & 0x03);
    615               *pixels++=(unsigned char) ((pixel & 0x03) & 0x03);
    616               break;
    617             }
    618             case 4:
    619             {
    620               CheckNumberPixels(2);
    621               *pixels++=(unsigned char) ((pixel >> 4) & 0xff);
    622               *pixels++=(unsigned char) ((pixel & 0x0f) & 0xff);
    623               break;
    624             }
    625             default:
    626             {
    627               CheckNumberPixels(1);
    628               *pixels++=(unsigned char) pixel;
    629               break;
    630             }
    631           }
    632         }
    633         continue;
    634       }
    635     length++;
    636     for (j=0; j < (ssize_t) length; j++)
    637     {
    638       CheckNumberCompactPixels;
    639       switch (depth)
    640       {
    641         case 1:
    642         {
    643           CheckNumberPixels(8);
    644           *pixels++=(*compact_pixels >> 7) & 0x01 ? 0U : 255U;
    645           *pixels++=(*compact_pixels >> 6) & 0x01 ? 0U : 255U;
    646           *pixels++=(*compact_pixels >> 5) & 0x01 ? 0U : 255U;
    647           *pixels++=(*compact_pixels >> 4) & 0x01 ? 0U : 255U;
    648           *pixels++=(*compact_pixels >> 3) & 0x01 ? 0U : 255U;
    649           *pixels++=(*compact_pixels >> 2) & 0x01 ? 0U : 255U;
    650           *pixels++=(*compact_pixels >> 1) & 0x01 ? 0U : 255U;
    651           *pixels++=(*compact_pixels >> 0) & 0x01 ? 0U : 255U;
    652           break;
    653         }
    654         case 2:
    655         {
    656           CheckNumberPixels(4);
    657           *pixels++=(*compact_pixels >> 6) & 0x03;
    658           *pixels++=(*compact_pixels >> 4) & 0x03;
    659           *pixels++=(*compact_pixels >> 2) & 0x03;
    660           *pixels++=(*compact_pixels & 0x03) & 0x03;
    661           break;
    662         }
    663         case 4:
    664         {
    665           CheckNumberPixels(2);
    666           *pixels++=(*compact_pixels >> 4) & 0xff;
    667           *pixels++=(*compact_pixels & 0x0f) & 0xff;
    668           break;
    669         }
    670         default:
    671         {
    672           CheckNumberPixels(1);
    673           *pixels++=(*compact_pixels);
    674           break;
    675         }
    676       }
    677       compact_pixels++;
    678     }
    679   }
    680   return(i);
    681 }
    682 
    683 static inline LayerInfo *DestroyLayerInfo(LayerInfo *layer_info,
    684   const ssize_t number_layers)
    685 {
    686   ssize_t
    687     i;
    688 
    689   for (i=0; i<number_layers; i++)
    690   {
    691     if (layer_info[i].image != (Image *) NULL)
    692       layer_info[i].image=DestroyImage(layer_info[i].image);
    693     if (layer_info[i].mask.image != (Image *) NULL)
    694       layer_info[i].mask.image=DestroyImage(layer_info[i].mask.image);
    695     if (layer_info[i].info != (StringInfo *) NULL)
    696       layer_info[i].info=DestroyStringInfo(layer_info[i].info);
    697   }
    698 
    699   return (LayerInfo *) RelinquishMagickMemory(layer_info);
    700 }
    701 
    702 static inline size_t GetPSDPacketSize(const Image *image)
    703 {
    704   if (image->storage_class == PseudoClass)
    705     {
    706       if (image->colors > 256)
    707         return(2);
    708     }
    709   if (image->depth > 16)
    710     return(4);
    711   if (image->depth > 8)
    712     return(2);
    713 
    714   return(1);
    715 }
    716 
    717 static inline MagickSizeType GetPSDSize(const PSDInfo *psd_info,Image *image)
    718 {
    719   if (psd_info->version == 1)
    720     return((MagickSizeType) ReadBlobLong(image));
    721   return((MagickSizeType) ReadBlobLongLong(image));
    722 }
    723 
    724 static inline size_t GetPSDRowSize(Image *image)
    725 {
    726   if (image->depth == 1)
    727     return(((image->columns+7)/8)*GetPSDPacketSize(image));
    728   else
    729     return(image->columns*GetPSDPacketSize(image));
    730 }
    731 
    732 static const char *ModeToString(PSDImageType type)
    733 {
    734   switch (type)
    735   {
    736     case BitmapMode: return "Bitmap";
    737     case GrayscaleMode: return "Grayscale";
    738     case IndexedMode: return "Indexed";
    739     case RGBMode: return "RGB";
    740     case CMYKMode:  return "CMYK";
    741     case MultichannelMode: return "Multichannel";
    742     case DuotoneMode: return "Duotone";
    743     case LabMode: return "L*A*B";
    744     default: return "unknown";
    745   }
    746 }
    747 
    748 static MagickBooleanType NegateCMYK(Image *image,ExceptionInfo *exception)
    749 {
    750   ChannelType
    751     channel_mask;
    752 
    753   MagickBooleanType
    754     status;
    755 
    756   channel_mask=SetImageChannelMask(image,(ChannelType)(AllChannels &~
    757     AlphaChannel));
    758   status=NegateImage(image,MagickFalse,exception);
    759   (void) SetImageChannelMask(image,channel_mask);
    760   return(status);
    761 }
    762 
    763 static StringInfo *ParseImageResourceBlocks(Image *image,
    764   const unsigned char *blocks,size_t length,
    765   MagickBooleanType *has_merged_image,ExceptionInfo *exception)
    766 {
    767   const unsigned char
    768     *p;
    769 
    770   ssize_t
    771     offset;
    772 
    773   StringInfo
    774     *profile;
    775 
    776   unsigned char
    777     name_length;
    778 
    779   unsigned int
    780     count;
    781 
    782   unsigned short
    783     id,
    784     short_sans;
    785 
    786   if (length < 16)
    787     return((StringInfo *) NULL);
    788   profile=BlobToStringInfo((const unsigned char *) NULL,length);
    789   SetStringInfoDatum(profile,blocks);
    790   SetStringInfoName(profile,"8bim");
    791   for (p=blocks; (p >= blocks) && (p < (blocks+length-7)); )
    792   {
    793     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
    794       break;
    795     p+=4;
    796     p=PushShortPixel(MSBEndian,p,&id);
    797     p=PushCharPixel(p,&name_length);
    798     if ((name_length % 2) == 0)
    799       name_length++;
    800     p+=name_length;
    801     if (p > (blocks+length-4))
    802       break;
    803     p=PushLongPixel(MSBEndian,p,&count);
    804     offset=(ssize_t) count;
    805     if (((p+offset) < blocks) || ((p+offset) > (blocks+length)))
    806       break;
    807     switch (id)
    808     {
    809       case 0x03ed:
    810       {
    811         char
    812           value[MagickPathExtent];
    813 
    814         unsigned short
    815           resolution;
    816 
    817         /*
    818           Resolution info.
    819         */
    820         if (offset < 16)
    821           break;
    822         p=PushShortPixel(MSBEndian,p,&resolution);
    823         image->resolution.x=(double) resolution;
    824         (void) FormatLocaleString(value,MagickPathExtent,"%g",
    825           image->resolution.x);
    826         (void) SetImageProperty(image,"tiff:XResolution",value,exception);
    827         p=PushShortPixel(MSBEndian,p,&short_sans);
    828         p=PushShortPixel(MSBEndian,p,&short_sans);
    829         p=PushShortPixel(MSBEndian,p,&short_sans);
    830         p=PushShortPixel(MSBEndian,p,&resolution);
    831         image->resolution.y=(double) resolution;
    832         (void) FormatLocaleString(value,MagickPathExtent,"%g",
    833           image->resolution.y);
    834         (void) SetImageProperty(image,"tiff:YResolution",value,exception);
    835         p=PushShortPixel(MSBEndian,p,&short_sans);
    836         p=PushShortPixel(MSBEndian,p,&short_sans);
    837         p=PushShortPixel(MSBEndian,p,&short_sans);
    838         image->units=PixelsPerInchResolution;
    839         break;
    840       }
    841       case 0x0421:
    842       {
    843         if ((offset > 4) && (*(p+4) == 0))
    844           *has_merged_image=MagickFalse;
    845         p+=offset;
    846         break;
    847       }
    848       default:
    849       {
    850         p+=offset;
    851         break;
    852       }
    853     }
    854     if ((offset & 0x01) != 0)
    855       p++;
    856   }
    857   return(profile);
    858 }
    859 
    860 static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
    861 {
    862   if (mode == (const char *) NULL)
    863     return(OverCompositeOp);
    864   if (LocaleNCompare(mode,"norm",4) == 0)
    865     return(OverCompositeOp);
    866   if (LocaleNCompare(mode,"mul ",4) == 0)
    867     return(MultiplyCompositeOp);
    868   if (LocaleNCompare(mode,"diss",4) == 0)
    869     return(DissolveCompositeOp);
    870   if (LocaleNCompare(mode,"diff",4) == 0)
    871     return(DifferenceCompositeOp);
    872   if (LocaleNCompare(mode,"dark",4) == 0)
    873     return(DarkenCompositeOp);
    874   if (LocaleNCompare(mode,"lite",4) == 0)
    875     return(LightenCompositeOp);
    876   if (LocaleNCompare(mode,"hue ",4) == 0)
    877     return(HueCompositeOp);
    878   if (LocaleNCompare(mode,"sat ",4) == 0)
    879     return(SaturateCompositeOp);
    880   if (LocaleNCompare(mode,"colr",4) == 0)
    881     return(ColorizeCompositeOp);
    882   if (LocaleNCompare(mode,"lum ",4) == 0)
    883     return(LuminizeCompositeOp);
    884   if (LocaleNCompare(mode,"scrn",4) == 0)
    885     return(ScreenCompositeOp);
    886   if (LocaleNCompare(mode,"over",4) == 0)
    887     return(OverlayCompositeOp);
    888   if (LocaleNCompare(mode,"hLit",4) == 0)
    889     return(HardLightCompositeOp);
    890   if (LocaleNCompare(mode,"sLit",4) == 0)
    891     return(SoftLightCompositeOp);
    892   if (LocaleNCompare(mode,"smud",4) == 0)
    893     return(ExclusionCompositeOp);
    894   if (LocaleNCompare(mode,"div ",4) == 0)
    895     return(ColorDodgeCompositeOp);
    896   if (LocaleNCompare(mode,"idiv",4) == 0)
    897     return(ColorBurnCompositeOp);
    898   if (LocaleNCompare(mode,"lbrn",4) == 0)
    899     return(LinearBurnCompositeOp);
    900   if (LocaleNCompare(mode,"lddg",4) == 0)
    901     return(LinearDodgeCompositeOp);
    902   if (LocaleNCompare(mode,"lLit",4) == 0)
    903     return(LinearLightCompositeOp);
    904   if (LocaleNCompare(mode,"vLit",4) == 0)
    905     return(VividLightCompositeOp);
    906   if (LocaleNCompare(mode,"pLit",4) == 0)
    907     return(PinLightCompositeOp);
    908   if (LocaleNCompare(mode,"hMix",4) == 0)
    909     return(HardMixCompositeOp);
    910   return(OverCompositeOp);
    911 }
    912 
    913 static inline void ReversePSDString(Image *image,char *p,size_t length)
    914 {
    915   char
    916     *q;
    917 
    918   if (image->endian == MSBEndian)
    919     return;
    920 
    921   q=p+length;
    922   for(--q; p < q; ++p, --q)
    923   {
    924     *p = *p ^ *q,
    925     *q = *p ^ *q,
    926     *p = *p ^ *q;
    927   }
    928 }
    929 
    930 static inline void SetPSDPixel(Image *image,const size_t channels,
    931   const ssize_t type,const size_t packet_size,const Quantum pixel,Quantum *q,
    932   ExceptionInfo *exception)
    933 {
    934   if (image->storage_class == PseudoClass)
    935     {
    936       PixelInfo
    937         *color;
    938 
    939       if (type == 0)
    940         {
    941           if (packet_size == 1)
    942             SetPixelIndex(image,ScaleQuantumToChar(pixel),q);
    943           else
    944             SetPixelIndex(image,ScaleQuantumToShort(pixel),q);
    945         }
    946       color=image->colormap+(ssize_t) ConstrainColormapIndex(image,
    947         (ssize_t) GetPixelIndex(image,q),exception);
    948       if ((type == 0) && (channels > 1))
    949         return;
    950       else
    951         color->alpha=(MagickRealType) pixel;
    952       SetPixelViaPixelInfo(image,color,q);
    953       return;
    954     }
    955   switch (type)
    956   {
    957     case -1:
    958     {
    959       SetPixelAlpha(image,pixel,q);
    960       break;
    961     }
    962     case -2:
    963     case 0:
    964     {
    965       SetPixelRed(image,pixel,q);
    966       break;
    967     }
    968     case -3:
    969     case 1:
    970     {
    971       SetPixelGreen(image,pixel,q);
    972       break;
    973     }
    974     case -4:
    975     case 2:
    976     {
    977       SetPixelBlue(image,pixel,q);
    978       break;
    979     }
    980     case 3:
    981     {
    982       if (image->colorspace == CMYKColorspace)
    983         SetPixelBlack(image,pixel,q);
    984       else
    985         if (image->alpha_trait != UndefinedPixelTrait)
    986           SetPixelAlpha(image,pixel,q);
    987       break;
    988     }
    989     case 4:
    990     {
    991       if ((IssRGBCompatibleColorspace(image->colorspace) != MagickFalse) &&
    992           (channels > 3))
    993         break;
    994       if (image->alpha_trait != UndefinedPixelTrait)
    995         SetPixelAlpha(image,pixel,q);
    996       break;
    997     }
    998   }
    999 }
   1000 
   1001 static MagickBooleanType ReadPSDChannelPixels(Image *image,
   1002   const size_t channels,const ssize_t row,const ssize_t type,
   1003   const unsigned char *pixels,ExceptionInfo *exception)
   1004 {
   1005   Quantum
   1006     pixel;
   1007 
   1008   register const unsigned char
   1009     *p;
   1010 
   1011   register Quantum
   1012     *q;
   1013 
   1014   register ssize_t
   1015     x;
   1016 
   1017   size_t
   1018     packet_size;
   1019 
   1020   p=pixels;
   1021   q=GetAuthenticPixels(image,0,row,image->columns,1,exception);
   1022   if (q == (Quantum *) NULL)
   1023     return MagickFalse;
   1024   packet_size=GetPSDPacketSize(image);
   1025   for (x=0; x < (ssize_t) image->columns; x++)
   1026   {
   1027     if (packet_size == 1)
   1028       pixel=ScaleCharToQuantum(*p++);
   1029     else if (packet_size == 2)
   1030       {
   1031         unsigned short
   1032           nibble;
   1033 
   1034         p=PushShortPixel(MSBEndian,p,&nibble);
   1035         pixel=ScaleShortToQuantum(nibble);
   1036       }
   1037     else
   1038       {
   1039         MagickFloatType
   1040           nibble;
   1041 
   1042         p=PushFloatPixel(MSBEndian,p,&nibble);
   1043         pixel=ClampToQuantum((MagickRealType)QuantumRange*nibble);
   1044       }
   1045     if (image->depth > 1)
   1046       {
   1047         SetPSDPixel(image,channels,type,packet_size,pixel,q,exception);
   1048         q+=GetPixelChannels(image);
   1049       }
   1050     else
   1051       {
   1052         ssize_t
   1053           bit,
   1054           number_bits;
   1055 
   1056         number_bits=(ssize_t) image->columns-x;
   1057         if (number_bits > 8)
   1058           number_bits=8;
   1059         for (bit = 0; bit < (ssize_t) number_bits; bit++)
   1060         {
   1061           SetPSDPixel(image,channels,type,packet_size,(((unsigned char) pixel)
   1062             & (0x01 << (7-bit))) != 0 ? 0 : QuantumRange,q,exception);
   1063           q+=GetPixelChannels(image);
   1064           x++;
   1065         }
   1066         if (x != (ssize_t) image->columns)
   1067           x--;
   1068         continue;
   1069       }
   1070   }
   1071   return(SyncAuthenticPixels(image,exception));
   1072 }
   1073 
   1074 static MagickBooleanType ReadPSDChannelRaw(Image *image,const size_t channels,
   1075   const ssize_t type,ExceptionInfo *exception)
   1076 {
   1077   MagickBooleanType
   1078     status;
   1079 
   1080   size_t
   1081     row_size;
   1082 
   1083   ssize_t
   1084     count,
   1085     y;
   1086 
   1087   unsigned char
   1088     *pixels;
   1089 
   1090   if (image->debug != MagickFalse)
   1091     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1092        "      layer data is RAW");
   1093 
   1094   row_size=GetPSDRowSize(image);
   1095   pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
   1096   if (pixels == (unsigned char *) NULL)
   1097     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1098       image->filename);
   1099 
   1100   status=MagickTrue;
   1101   for (y=0; y < (ssize_t) image->rows; y++)
   1102   {
   1103     status=MagickFalse;
   1104 
   1105     count=ReadBlob(image,row_size,pixels);
   1106     if (count != (ssize_t) row_size)
   1107       {
   1108         status=MagickFalse;
   1109         break;
   1110       }
   1111 
   1112     status=ReadPSDChannelPixels(image,channels,y,type,pixels,exception);
   1113     if (status == MagickFalse)
   1114       break;
   1115   }
   1116 
   1117   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1118   return(status);
   1119 }
   1120 
   1121 static inline MagickOffsetType *ReadPSDRLESizes(Image *image,
   1122   const PSDInfo *psd_info,const size_t size)
   1123 {
   1124   MagickOffsetType
   1125     *sizes;
   1126 
   1127   ssize_t
   1128     y;
   1129 
   1130   sizes=(MagickOffsetType *) AcquireQuantumMemory(size,sizeof(*sizes));
   1131   if(sizes != (MagickOffsetType *) NULL)
   1132     {
   1133       for (y=0; y < (ssize_t) size; y++)
   1134       {
   1135         if (psd_info->version == 1)
   1136           sizes[y]=(MagickOffsetType) ReadBlobShort(image);
   1137         else
   1138           sizes[y]=(MagickOffsetType) ReadBlobLong(image);
   1139       }
   1140     }
   1141   return sizes;
   1142 }
   1143 
   1144 static MagickBooleanType ReadPSDChannelRLE(Image *image,const PSDInfo *psd_info,
   1145   const ssize_t type,MagickOffsetType *sizes,ExceptionInfo *exception)
   1146 {
   1147   MagickBooleanType
   1148     status;
   1149 
   1150   size_t
   1151     length,
   1152     row_size;
   1153 
   1154   ssize_t
   1155     count,
   1156     y;
   1157 
   1158   unsigned char
   1159     *compact_pixels,
   1160     *pixels;
   1161 
   1162   if (image->debug != MagickFalse)
   1163     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1164        "      layer data is RLE compressed");
   1165 
   1166   row_size=GetPSDRowSize(image);
   1167   pixels=(unsigned char *) AcquireQuantumMemory(row_size,sizeof(*pixels));
   1168   if (pixels == (unsigned char *) NULL)
   1169     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1170       image->filename);
   1171 
   1172   length=0;
   1173   for (y=0; y < (ssize_t) image->rows; y++)
   1174     if ((MagickOffsetType) length < sizes[y])
   1175       length=(size_t) sizes[y];
   1176 
   1177   if (length > (row_size+2048)) /* arbitrary number */
   1178     {
   1179       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1180       ThrowBinaryException(ResourceLimitError,"InvalidLength",image->filename);
   1181     }
   1182 
   1183   compact_pixels=(unsigned char *) AcquireQuantumMemory(length,sizeof(*pixels));
   1184   if (compact_pixels == (unsigned char *) NULL)
   1185     {
   1186       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1187       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1188         image->filename);
   1189     }
   1190 
   1191   (void) memset(compact_pixels,0,length*sizeof(*compact_pixels));
   1192 
   1193   status=MagickTrue;
   1194   for (y=0; y < (ssize_t) image->rows; y++)
   1195   {
   1196     status=MagickFalse;
   1197 
   1198     count=ReadBlob(image,(size_t) sizes[y],compact_pixels);
   1199     if (count != (ssize_t) sizes[y])
   1200       break;
   1201 
   1202     count=DecodePSDPixels((size_t) sizes[y],compact_pixels,
   1203       (ssize_t) (image->depth == 1 ? 123456 : image->depth),row_size,pixels);
   1204     if (count != (ssize_t) row_size)
   1205       break;
   1206 
   1207     status=ReadPSDChannelPixels(image,psd_info->channels,y,type,pixels,
   1208       exception);
   1209     if (status == MagickFalse)
   1210       break;
   1211   }
   1212 
   1213   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   1214   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1215   return(status);
   1216 }
   1217 
   1218 #ifdef MAGICKCORE_ZLIB_DELEGATE
   1219 static MagickBooleanType ReadPSDChannelZip(Image *image,const size_t channels,
   1220   const ssize_t type,const PSDCompressionType compression,
   1221   const size_t compact_size,ExceptionInfo *exception)
   1222 {
   1223   MagickBooleanType
   1224     status;
   1225 
   1226   register unsigned char
   1227     *p;
   1228 
   1229   size_t
   1230     count,
   1231     length,
   1232     packet_size,
   1233     row_size;
   1234 
   1235   ssize_t
   1236     y;
   1237 
   1238   unsigned char
   1239     *compact_pixels,
   1240     *pixels;
   1241 
   1242   z_stream
   1243     stream;
   1244 
   1245   if (image->debug != MagickFalse)
   1246     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1247        "      layer data is ZIP compressed");
   1248 
   1249   if ((MagickSizeType) compact_size > GetBlobSize(image))
   1250     ThrowBinaryException(CorruptImageError,"UnexpectedEndOfFile",
   1251       image->filename);
   1252   compact_pixels=(unsigned char *) AcquireQuantumMemory(compact_size,
   1253     sizeof(*compact_pixels));
   1254   if (compact_pixels == (unsigned char *) NULL)
   1255     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1256       image->filename);
   1257 
   1258   packet_size=GetPSDPacketSize(image);
   1259   row_size=image->columns*packet_size;
   1260   count=image->rows*row_size;
   1261 
   1262   pixels=(unsigned char *) AcquireQuantumMemory(count,sizeof(*pixels));
   1263   if (pixels == (unsigned char *) NULL)
   1264     {
   1265       compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   1266       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1267         image->filename);
   1268     }
   1269   if (ReadBlob(image,compact_size,compact_pixels) != (ssize_t) compact_size)
   1270     {
   1271       pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1272       compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   1273       ThrowBinaryException(CorruptImageError,"UnexpectedEndOfFile",
   1274         image->filename);
   1275     }
   1276 
   1277   memset(&stream,0,sizeof(stream));
   1278   stream.data_type=Z_BINARY;
   1279   stream.next_in=(Bytef *)compact_pixels;
   1280   stream.avail_in=(uInt) compact_size;
   1281   stream.next_out=(Bytef *)pixels;
   1282   stream.avail_out=(uInt) count;
   1283 
   1284   if (inflateInit(&stream) == Z_OK)
   1285     {
   1286       int
   1287         ret;
   1288 
   1289       while (stream.avail_out > 0)
   1290       {
   1291         ret=inflate(&stream,Z_SYNC_FLUSH);
   1292         if ((ret != Z_OK) && (ret != Z_STREAM_END))
   1293           {
   1294             (void) inflateEnd(&stream);
   1295             compact_pixels=(unsigned char *) RelinquishMagickMemory(
   1296               compact_pixels);
   1297             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1298             return(MagickFalse);
   1299           }
   1300         if (ret == Z_STREAM_END)
   1301           break;
   1302       }
   1303       (void) inflateEnd(&stream);
   1304     }
   1305 
   1306   if (compression == ZipWithPrediction)
   1307     {
   1308       p=pixels;
   1309       while (count > 0)
   1310       {
   1311         length=image->columns;
   1312         while (--length)
   1313         {
   1314           if (packet_size == 2)
   1315             {
   1316               p[2]+=p[0]+((p[1]+p[3]) >> 8);
   1317               p[3]+=p[1];
   1318             }
   1319           /*
   1320           else if (packet_size == 4)
   1321              {
   1322                TODO: Figure out what to do there.
   1323              }
   1324           */
   1325           else
   1326             *(p+1)+=*p;
   1327           p+=packet_size;
   1328         }
   1329         p+=packet_size;
   1330         count-=row_size;
   1331       }
   1332     }
   1333 
   1334   status=MagickTrue;
   1335   p=pixels;
   1336   for (y=0; y < (ssize_t) image->rows; y++)
   1337   {
   1338     status=ReadPSDChannelPixels(image,channels,y,type,p,exception);
   1339     if (status == MagickFalse)
   1340       break;
   1341 
   1342     p+=row_size;
   1343   }
   1344 
   1345   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   1346   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
   1347   return(status);
   1348 }
   1349 #endif
   1350 
   1351 static MagickBooleanType ReadPSDChannel(Image *image,
   1352   const ImageInfo *image_info,const PSDInfo *psd_info,LayerInfo* layer_info,
   1353   const size_t channel,const PSDCompressionType compression,
   1354   ExceptionInfo *exception)
   1355 {
   1356   Image
   1357     *channel_image,
   1358     *mask;
   1359 
   1360   MagickOffsetType
   1361     offset;
   1362 
   1363   MagickBooleanType
   1364     status;
   1365 
   1366   channel_image=image;
   1367   mask=(Image *) NULL;
   1368   if ((layer_info->channel_info[channel].type < -1) &&
   1369       (layer_info->mask.page.width > 0) && (layer_info->mask.page.height > 0))
   1370     {
   1371       const char
   1372         *option;
   1373 
   1374       /*
   1375         Ignore mask that is not a user supplied layer mask, if the mask is
   1376         disabled or if the flags have unsupported values.
   1377       */
   1378       option=GetImageOption(image_info,"psd:preserve-opacity-mask");
   1379       if ((layer_info->channel_info[channel].type != -2) ||
   1380           (layer_info->mask.flags > 2) || ((layer_info->mask.flags & 0x02) &&
   1381            (IsStringTrue(option) == MagickFalse)))
   1382         {
   1383           (void) SeekBlob(image,(MagickOffsetType)
   1384             layer_info->channel_info[channel].size-2,SEEK_CUR);
   1385           return(MagickTrue);
   1386         }
   1387       mask=CloneImage(image,layer_info->mask.page.width,
   1388         layer_info->mask.page.height,MagickFalse,exception);
   1389       if (mask != (Image *) NULL)
   1390         {
   1391           (void) SetImageType(mask,GrayscaleType,exception);
   1392           channel_image=mask;
   1393         }
   1394     }
   1395 
   1396   offset=TellBlob(image);
   1397   status=MagickFalse;
   1398   switch(compression)
   1399   {
   1400     case Raw:
   1401       status=ReadPSDChannelRaw(channel_image,psd_info->channels,
   1402         (ssize_t) layer_info->channel_info[channel].type,exception);
   1403       break;
   1404     case RLE:
   1405       {
   1406         MagickOffsetType
   1407           *sizes;
   1408 
   1409         sizes=ReadPSDRLESizes(channel_image,psd_info,channel_image->rows);
   1410         if (sizes == (MagickOffsetType *) NULL)
   1411           ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1412             image->filename);
   1413         status=ReadPSDChannelRLE(channel_image,psd_info,
   1414           (ssize_t) layer_info->channel_info[channel].type,sizes,exception);
   1415         sizes=(MagickOffsetType *) RelinquishMagickMemory(sizes);
   1416       }
   1417       break;
   1418     case ZipWithPrediction:
   1419     case ZipWithoutPrediction:
   1420 #ifdef MAGICKCORE_ZLIB_DELEGATE
   1421       status=ReadPSDChannelZip(channel_image,layer_info->channels,
   1422         (ssize_t) layer_info->channel_info[channel].type,compression,
   1423         layer_info->channel_info[channel].size-2,exception);
   1424 #else
   1425       (void) ThrowMagickException(exception,GetMagickModule(),
   1426           MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn",
   1427             "'%s' (ZLIB)",image->filename);
   1428 #endif
   1429       break;
   1430     default:
   1431       (void) ThrowMagickException(exception,GetMagickModule(),TypeWarning,
   1432         "CompressionNotSupported","'%.20g'",(double) compression);
   1433       break;
   1434   }
   1435 
   1436   (void) SeekBlob(image,offset+layer_info->channel_info[channel].size-2,
   1437     SEEK_SET);
   1438   if (status == MagickFalse)
   1439     {
   1440       if (mask != (Image *) NULL)
   1441         (void) DestroyImage(mask);
   1442       ThrowBinaryException(CoderError,"UnableToDecompressImage",
   1443         image->filename);
   1444     }
   1445   if (mask != (Image *) NULL)
   1446     {
   1447       if (layer_info->mask.image != (Image *) NULL)
   1448         layer_info->mask.image=DestroyImage(layer_info->mask.image);
   1449       layer_info->mask.image=mask;
   1450     }
   1451   return(status);
   1452 }
   1453 
   1454 static MagickBooleanType ReadPSDLayer(Image *image,const ImageInfo *image_info,
   1455   const PSDInfo *psd_info,LayerInfo* layer_info,ExceptionInfo *exception)
   1456 {
   1457   char
   1458     message[MagickPathExtent];
   1459 
   1460   MagickBooleanType
   1461     status;
   1462 
   1463   PSDCompressionType
   1464     compression;
   1465 
   1466   ssize_t
   1467     j;
   1468 
   1469   if (image->debug != MagickFalse)
   1470     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1471       "    setting up new layer image");
   1472   if (psd_info->mode != IndexedMode)
   1473     (void) SetImageBackgroundColor(layer_info->image,exception);
   1474   layer_info->image->compose=PSDBlendModeToCompositeOperator(
   1475     layer_info->blendkey);
   1476   if (layer_info->visible == MagickFalse)
   1477     layer_info->image->compose=NoCompositeOp;
   1478   /*
   1479     Set up some hidden attributes for folks that need them.
   1480   */
   1481   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
   1482     (double) layer_info->page.x);
   1483   (void) SetImageArtifact(layer_info->image,"psd:layer.x",message);
   1484   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
   1485     (double) layer_info->page.y);
   1486   (void) SetImageArtifact(layer_info->image,"psd:layer.y",message);
   1487   (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
   1488     layer_info->opacity);
   1489   (void) SetImageArtifact(layer_info->image,"psd:layer.opacity",message);
   1490   (void) SetImageProperty(layer_info->image,"label",(char *) layer_info->name,
   1491     exception);
   1492 
   1493   status=MagickTrue;
   1494   for (j=0; j < (ssize_t) layer_info->channels; j++)
   1495   {
   1496     if (image->debug != MagickFalse)
   1497       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1498         "    reading data for channel %.20g",(double) j);
   1499 
   1500     compression=(PSDCompressionType) ReadBlobShort(layer_info->image);
   1501 
   1502     /* TODO: Remove this when we figure out how to support this */
   1503     if ((compression == ZipWithPrediction) && (image->depth == 32))
   1504       {
   1505         (void) ThrowMagickException(exception,GetMagickModule(),
   1506           TypeError,"CompressionNotSupported","ZipWithPrediction(32 bit)");
   1507         return(MagickFalse);
   1508       }
   1509 
   1510     layer_info->image->compression=ConvertPSDCompression(compression);
   1511     if (layer_info->channel_info[j].type == -1)
   1512       layer_info->image->alpha_trait=BlendPixelTrait;
   1513 
   1514     status=ReadPSDChannel(layer_info->image,image_info,psd_info,layer_info,
   1515       (size_t) j,compression,exception);
   1516 
   1517     if (status == MagickFalse)
   1518       break;
   1519   }
   1520 
   1521   if (status != MagickFalse)
   1522     status=ApplyPSDLayerOpacity(layer_info->image,layer_info->opacity,
   1523       MagickFalse,exception);
   1524 
   1525   if ((status != MagickFalse) &&
   1526       (layer_info->image->colorspace == CMYKColorspace))
   1527     status=NegateCMYK(layer_info->image,exception);
   1528 
   1529   if ((status != MagickFalse) && (layer_info->mask.image != (Image *) NULL))
   1530     {
   1531       const char
   1532         *option;
   1533 
   1534       layer_info->mask.image->page.x=layer_info->mask.page.x;
   1535       layer_info->mask.image->page.y=layer_info->mask.page.y;
   1536       /* Do not composite the mask when it is disabled */
   1537       if ((layer_info->mask.flags & 0x02) == 0x02)
   1538         layer_info->mask.image->compose=NoCompositeOp;
   1539       else
   1540         status=ApplyPSDOpacityMask(layer_info->image,layer_info->mask.image,
   1541           layer_info->mask.background == 0 ? 0 : QuantumRange,MagickFalse,
   1542           exception);
   1543       option=GetImageOption(image_info,"psd:preserve-opacity-mask");
   1544       if (IsStringTrue(option) != MagickFalse)
   1545         PreservePSDOpacityMask(image,layer_info,exception);
   1546       layer_info->mask.image=DestroyImage(layer_info->mask.image);
   1547     }
   1548 
   1549   return(status);
   1550 }
   1551 
   1552 static MagickBooleanType CheckPSDChannels(const PSDInfo *psd_info,
   1553   LayerInfo *layer_info)
   1554 {
   1555   int
   1556     channel_type;
   1557 
   1558   register ssize_t
   1559     i;
   1560 
   1561   if (layer_info->channels < psd_info->min_channels)
   1562     return(MagickFalse);
   1563   channel_type=RedChannel;
   1564   if (psd_info->min_channels >= 3)
   1565     channel_type|=(GreenChannel | BlueChannel);
   1566   if (psd_info->min_channels >= 4)
   1567     channel_type|=BlackChannel;
   1568   for (i=0; i < (ssize_t) layer_info->channels; i++)
   1569   {
   1570     short
   1571       type;
   1572 
   1573     type=layer_info->channel_info[i].type;
   1574     if (type == -1)
   1575       {
   1576         channel_type|=AlphaChannel;
   1577         continue;
   1578       }
   1579     if (type < -1)
   1580       continue;
   1581     if (type == 0)
   1582       channel_type&=~RedChannel;
   1583     else if (type == 1)
   1584       channel_type&=~GreenChannel;
   1585     else if (type == 2)
   1586       channel_type&=~BlueChannel;
   1587     else if (type == 3)
   1588       channel_type&=~BlackChannel;
   1589   }
   1590   if (channel_type == 0)
   1591     return(MagickTrue);
   1592   if ((channel_type == AlphaChannel) &&
   1593       (layer_info->channels >= psd_info->min_channels + 1))
   1594     return(MagickTrue);
   1595   return(MagickFalse);
   1596 }
   1597 
   1598 static void AttachPSDLayers(Image *image,LayerInfo *layer_info,
   1599   ssize_t number_layers)
   1600 {
   1601   register ssize_t
   1602     i;
   1603 
   1604   ssize_t
   1605     j;
   1606 
   1607   for (i=0; i < number_layers; i++)
   1608   {
   1609     if (layer_info[i].image == (Image *) NULL)
   1610       {
   1611         for (j=i; j < number_layers - 1; j++)
   1612           layer_info[j] = layer_info[j+1];
   1613         number_layers--;
   1614         i--;
   1615       }
   1616   }
   1617   if (number_layers == 0)
   1618     {
   1619       layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
   1620       return;
   1621     }
   1622   for (i=0; i < number_layers; i++)
   1623   {
   1624     if (i > 0)
   1625       layer_info[i].image->previous=layer_info[i-1].image;
   1626     if (i < (number_layers-1))
   1627       layer_info[i].image->next=layer_info[i+1].image;
   1628     layer_info[i].image->page=layer_info[i].page;
   1629   }
   1630   image->next=layer_info[0].image;
   1631   layer_info[0].image->previous=image;
   1632   layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
   1633 }
   1634 
   1635 static inline MagickBooleanType PSDSkipImage(const ImageInfo *image_info,
   1636   const size_t index)
   1637 {
   1638   if (image_info->number_scenes == 0)
   1639     return(MagickFalse);
   1640   if (index < image_info->scene)
   1641     return(MagickTrue);
   1642   if (index > image_info->scene+image_info->number_scenes-1)
   1643     return(MagickTrue);
   1644   return(MagickFalse);
   1645 }
   1646 
   1647 static MagickBooleanType ReadPSDLayersInternal(Image *image,
   1648   const ImageInfo *image_info,const PSDInfo *psd_info,
   1649   const MagickBooleanType skip_layers,ExceptionInfo *exception)
   1650 {
   1651   char
   1652     type[4];
   1653 
   1654   LayerInfo
   1655     *layer_info;
   1656 
   1657   MagickSizeType
   1658     size;
   1659 
   1660   MagickBooleanType
   1661     status;
   1662 
   1663   register ssize_t
   1664     i;
   1665 
   1666   ssize_t
   1667     count,
   1668     j,
   1669     number_layers;
   1670 
   1671   size=GetPSDSize(psd_info,image);
   1672   if (size == 0)
   1673     {
   1674       /*
   1675         Skip layers & masks.
   1676       */
   1677       (void) ReadBlobLong(image);
   1678       count=ReadBlob(image,4,(unsigned char *) type);
   1679       if (count == 4)
   1680         ReversePSDString(image,type,(size_t) count);
   1681       if ((count != 4) || (LocaleNCompare(type,"8BIM",4) != 0))
   1682         return(MagickTrue);
   1683       else
   1684         {
   1685           count=ReadBlob(image,4,(unsigned char *) type);
   1686           if (count == 4)
   1687             ReversePSDString(image,type,4);
   1688           if ((count == 4) && ((LocaleNCompare(type,"Lr16",4) == 0) ||
   1689               (LocaleNCompare(type,"Lr32",4) == 0)))
   1690             size=GetPSDSize(psd_info,image);
   1691           else
   1692             return(MagickTrue);
   1693         }
   1694     }
   1695   if (size == 0)
   1696     return(MagickTrue);
   1697 
   1698   layer_info=(LayerInfo *) NULL;
   1699   number_layers=(ssize_t) ReadBlobSignedShort(image);
   1700 
   1701   if (number_layers < 0)
   1702     {
   1703       /*
   1704         The first alpha channel in the merged result contains the
   1705         transparency data for the merged result.
   1706       */
   1707       number_layers=MagickAbsoluteValue(number_layers);
   1708       if (image->debug != MagickFalse)
   1709         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1710           "  negative layer count corrected for");
   1711       image->alpha_trait=BlendPixelTrait;
   1712     }
   1713 
   1714   /*
   1715     We only need to know if the image has an alpha channel
   1716   */
   1717   if (skip_layers != MagickFalse)
   1718     return(MagickTrue);
   1719 
   1720   if (image->debug != MagickFalse)
   1721     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1722       "  image contains %.20g layers",(double) number_layers);
   1723 
   1724   if (number_layers == 0)
   1725     ThrowBinaryException(CorruptImageError,"InvalidNumberOfLayers",
   1726       image->filename);
   1727 
   1728   layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
   1729     sizeof(*layer_info));
   1730   if (layer_info == (LayerInfo *) NULL)
   1731     {
   1732       if (image->debug != MagickFalse)
   1733         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1734           "  allocation of LayerInfo failed");
   1735       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1736         image->filename);
   1737     }
   1738   (void) memset(layer_info,0,(size_t) number_layers*sizeof(*layer_info));
   1739 
   1740   for (i=0; i < number_layers; i++)
   1741   {
   1742     ssize_t
   1743       top,
   1744       left,
   1745       bottom,
   1746       right;
   1747 
   1748     if (image->debug != MagickFalse)
   1749       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1750         "  reading layer #%.20g",(double) i+1);
   1751     top=(ssize_t) ReadBlobSignedLong(image);
   1752     left=(ssize_t) ReadBlobSignedLong(image);
   1753     bottom=(ssize_t) ReadBlobSignedLong(image);
   1754     right=(ssize_t) ReadBlobSignedLong(image);
   1755     if ((right < left) || (bottom < top))
   1756       {
   1757         layer_info=DestroyLayerInfo(layer_info,number_layers);
   1758         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
   1759           image->filename);
   1760       }
   1761     layer_info[i].page.y=top;
   1762     layer_info[i].page.x=left;
   1763     layer_info[i].page.width=(size_t) (right-left);
   1764     layer_info[i].page.height=(size_t) (bottom-top);
   1765     layer_info[i].channels=ReadBlobShort(image);
   1766     if (layer_info[i].channels > MaxPSDChannels)
   1767       {
   1768         layer_info=DestroyLayerInfo(layer_info,number_layers);
   1769         ThrowBinaryException(CorruptImageError,"MaximumChannelsExceeded",
   1770           image->filename);
   1771       }
   1772     if (image->debug != MagickFalse)
   1773       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1774         "    offset(%.20g,%.20g), size(%.20g,%.20g), channels=%.20g",
   1775         (double) layer_info[i].page.x,(double) layer_info[i].page.y,
   1776         (double) layer_info[i].page.height,(double)
   1777         layer_info[i].page.width,(double) layer_info[i].channels);
   1778     for (j=0; j < (ssize_t) layer_info[i].channels; j++)
   1779     {
   1780       layer_info[i].channel_info[j].type=(short) ReadBlobShort(image);
   1781       if ((layer_info[i].channel_info[j].type < -4) ||
   1782           (layer_info[i].channel_info[j].type > 4))
   1783         {
   1784           layer_info=DestroyLayerInfo(layer_info,number_layers);
   1785           ThrowBinaryException(CorruptImageError,"NoSuchImageChannel",
   1786             image->filename);
   1787         }
   1788       layer_info[i].channel_info[j].size=(size_t) GetPSDSize(psd_info,
   1789         image);
   1790       if (image->debug != MagickFalse)
   1791         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1792           "    channel[%.20g]: type=%.20g, size=%.20g",(double) j,
   1793           (double) layer_info[i].channel_info[j].type,
   1794           (double) layer_info[i].channel_info[j].size);
   1795     }
   1796     if (CheckPSDChannels(psd_info,&layer_info[i]) == MagickFalse)
   1797       {
   1798         layer_info=DestroyLayerInfo(layer_info,number_layers);
   1799         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
   1800           image->filename);
   1801       }
   1802     count=ReadBlob(image,4,(unsigned char *) type);
   1803     if (count == 4)
   1804       ReversePSDString(image,type,4);
   1805     if ((count != 4) || (LocaleNCompare(type,"8BIM",4) != 0))
   1806       {
   1807         if (image->debug != MagickFalse)
   1808           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1809             "  layer type was %.4s instead of 8BIM", type);
   1810         layer_info=DestroyLayerInfo(layer_info,number_layers);
   1811         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
   1812           image->filename);
   1813       }
   1814     count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
   1815     if (count != 4)
   1816       {
   1817         layer_info=DestroyLayerInfo(layer_info,number_layers);
   1818         ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
   1819           image->filename);
   1820       }
   1821     ReversePSDString(image,layer_info[i].blendkey,4);
   1822     layer_info[i].opacity=(Quantum) ScaleCharToQuantum((unsigned char)
   1823       ReadBlobByte(image));
   1824     layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
   1825     layer_info[i].flags=(unsigned char) ReadBlobByte(image);
   1826     layer_info[i].visible=!(layer_info[i].flags & 0x02);
   1827     if (image->debug != MagickFalse)
   1828       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1829         "   blend=%.4s, opacity=%.20g, clipping=%s, flags=%d, visible=%s",
   1830         layer_info[i].blendkey,(double) layer_info[i].opacity,
   1831         layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
   1832         layer_info[i].visible ? "true" : "false");
   1833     (void) ReadBlobByte(image);  /* filler */
   1834 
   1835     size=ReadBlobLong(image);
   1836     if (size != 0)
   1837       {
   1838         MagickSizeType
   1839           combined_length,
   1840           length;
   1841 
   1842         if (image->debug != MagickFalse)
   1843           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1844             "    layer contains additional info");
   1845         length=ReadBlobLong(image);
   1846         combined_length=length+4;
   1847         if (length != 0)
   1848           {
   1849             /*
   1850               Layer mask info.
   1851             */
   1852             layer_info[i].mask.page.y=(ssize_t) ReadBlobSignedLong(image);
   1853             layer_info[i].mask.page.x=(ssize_t) ReadBlobSignedLong(image);
   1854             layer_info[i].mask.page.height=(size_t)
   1855               (ReadBlobSignedLong(image)-layer_info[i].mask.page.y);
   1856             layer_info[i].mask.page.width=(size_t) (
   1857               ReadBlobSignedLong(image)-layer_info[i].mask.page.x);
   1858             layer_info[i].mask.background=(unsigned char) ReadBlobByte(
   1859               image);
   1860             layer_info[i].mask.flags=(unsigned char) ReadBlobByte(image);
   1861             if (!(layer_info[i].mask.flags & 0x01))
   1862               {
   1863                 layer_info[i].mask.page.y=layer_info[i].mask.page.y-
   1864                   layer_info[i].page.y;
   1865                 layer_info[i].mask.page.x=layer_info[i].mask.page.x-
   1866                   layer_info[i].page.x;
   1867               }
   1868             if (image->debug != MagickFalse)
   1869               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1870                 "      layer mask: offset(%.20g,%.20g), size(%.20g,%.20g), length=%.20g",
   1871                 (double) layer_info[i].mask.page.x,(double)
   1872                 layer_info[i].mask.page.y,(double)
   1873                 layer_info[i].mask.page.width,(double)
   1874                 layer_info[i].mask.page.height,(double) ((MagickOffsetType)
   1875                 length)-18);
   1876             /*
   1877               Skip over the rest of the layer mask information.
   1878             */
   1879             if (DiscardBlobBytes(image,(MagickSizeType) (length-18)) == MagickFalse)
   1880               {
   1881                 layer_info=DestroyLayerInfo(layer_info,number_layers);
   1882                 ThrowBinaryException(CorruptImageError,
   1883                   "UnexpectedEndOfFile",image->filename);
   1884               }
   1885           }
   1886         length=ReadBlobLong(image);
   1887         combined_length+=length+4;
   1888         if (length != 0)
   1889           {
   1890             /*
   1891               Layer blending ranges info.
   1892             */
   1893             if (image->debug != MagickFalse)
   1894               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1895                 "      layer blending ranges: length=%.20g",(double)
   1896                 ((MagickOffsetType) length));
   1897             if (DiscardBlobBytes(image,length) == MagickFalse)
   1898               {
   1899                 layer_info=DestroyLayerInfo(layer_info,number_layers);
   1900                 ThrowBinaryException(CorruptImageError,
   1901                   "UnexpectedEndOfFile",image->filename);
   1902               }
   1903           }
   1904         /*
   1905           Layer name.
   1906         */
   1907         length=(MagickSizeType) (unsigned char) ReadBlobByte(image);
   1908         combined_length+=length+1;
   1909         if (length > 0)
   1910           (void) ReadBlob(image,(size_t) length++,layer_info[i].name);
   1911         layer_info[i].name[length]='\0';
   1912         if (image->debug != MagickFalse)
   1913           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1914             "      layer name: %s",layer_info[i].name);
   1915         if ((length % 4) != 0)
   1916           {
   1917             length=4-(length % 4);
   1918             combined_length+=length;
   1919             /* Skip over the padding of the layer name */
   1920             if (DiscardBlobBytes(image,length) == MagickFalse)
   1921               {
   1922                 layer_info=DestroyLayerInfo(layer_info,number_layers);
   1923                 ThrowBinaryException(CorruptImageError,
   1924                   "UnexpectedEndOfFile",image->filename);
   1925               }
   1926           }
   1927         length=(MagickSizeType) size-combined_length;
   1928         if (length > 0)
   1929           {
   1930             unsigned char
   1931               *info;
   1932 
   1933             if (length > GetBlobSize(image))
   1934               {
   1935                 layer_info=DestroyLayerInfo(layer_info,number_layers);
   1936                 ThrowBinaryException(CorruptImageError,
   1937                   "InsufficientImageDataInFile",image->filename);
   1938               }
   1939             layer_info[i].info=AcquireStringInfo((const size_t) length);
   1940             info=GetStringInfoDatum(layer_info[i].info);
   1941             (void) ReadBlob(image,(const size_t) length,info);
   1942           }
   1943       }
   1944   }
   1945 
   1946   for (i=0; i < number_layers; i++)
   1947   {
   1948     if ((layer_info[i].page.width == 0) || (layer_info[i].page.height == 0))
   1949       {
   1950         if (image->debug != MagickFalse)
   1951           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1952             "      layer data is empty");
   1953         if (layer_info[i].info != (StringInfo *) NULL)
   1954           layer_info[i].info=DestroyStringInfo(layer_info[i].info);
   1955         continue;
   1956       }
   1957 
   1958     /*
   1959       Allocate layered image.
   1960     */
   1961     layer_info[i].image=CloneImage(image,layer_info[i].page.width,
   1962       layer_info[i].page.height,MagickFalse,exception);
   1963     if (layer_info[i].image == (Image *) NULL)
   1964       {
   1965         layer_info=DestroyLayerInfo(layer_info,number_layers);
   1966         if (image->debug != MagickFalse)
   1967           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1968             "  allocation of image for layer %.20g failed",(double) i);
   1969         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   1970           image->filename);
   1971       }
   1972     if (layer_info[i].info != (StringInfo *) NULL)
   1973       {
   1974         (void) SetImageProfile(layer_info[i].image,"psd:additional-info",
   1975           layer_info[i].info,exception);
   1976         layer_info[i].info=DestroyStringInfo(layer_info[i].info);
   1977       }
   1978   }
   1979   if (image_info->ping != MagickFalse)
   1980     {
   1981       AttachPSDLayers(image,layer_info,number_layers);
   1982       return(MagickTrue);
   1983     }
   1984   status=MagickTrue;
   1985   for (i=0; i < number_layers; i++)
   1986   {
   1987     if ((layer_info[i].image == (Image *) NULL) ||
   1988         (PSDSkipImage(image_info,i) != MagickFalse))
   1989       {
   1990         for (j=0; j < (ssize_t) layer_info[i].channels; j++)
   1991         {
   1992           if (DiscardBlobBytes(image,(MagickSizeType)
   1993               layer_info[i].channel_info[j].size) == MagickFalse)
   1994             {
   1995               layer_info=DestroyLayerInfo(layer_info,number_layers);
   1996               ThrowBinaryException(CorruptImageError,
   1997                 "UnexpectedEndOfFile",image->filename);
   1998             }
   1999         }
   2000         continue;
   2001       }
   2002 
   2003     if (image->debug != MagickFalse)
   2004       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2005         "  reading data for layer %.20g",(double) i);
   2006 
   2007     status=ReadPSDLayer(image,image_info,psd_info,&layer_info[i],
   2008       exception);
   2009     if (status == MagickFalse)
   2010       break;
   2011 
   2012     status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType) i,
   2013       (MagickSizeType) number_layers);
   2014     if (status == MagickFalse)
   2015       break;
   2016   }
   2017 
   2018   if (status != MagickFalse)
   2019     AttachPSDLayers(image,layer_info,number_layers);
   2020   else
   2021     layer_info=DestroyLayerInfo(layer_info,number_layers);
   2022 
   2023   return(status);
   2024 }
   2025 
   2026 ModuleExport MagickBooleanType ReadPSDLayers(Image *image,
   2027   const ImageInfo *image_info,const PSDInfo *psd_info,ExceptionInfo *exception)
   2028 {
   2029   PolicyDomain
   2030     domain;
   2031 
   2032   PolicyRights
   2033     rights;
   2034 
   2035   domain=CoderPolicyDomain;
   2036   rights=ReadPolicyRights;
   2037   if (IsRightsAuthorized(domain,rights,"PSD") == MagickFalse)
   2038     return(MagickTrue);
   2039   return(ReadPSDLayersInternal(image,image_info,psd_info,MagickFalse,
   2040     exception));
   2041 }
   2042 
   2043 static MagickBooleanType ReadPSDMergedImage(const ImageInfo *image_info,
   2044   Image *image,const PSDInfo *psd_info,ExceptionInfo *exception)
   2045 {
   2046   MagickOffsetType
   2047     *sizes;
   2048 
   2049   MagickBooleanType
   2050     status;
   2051 
   2052   PSDCompressionType
   2053     compression;
   2054 
   2055   register ssize_t
   2056     i;
   2057 
   2058   if ((image_info->number_scenes != 0) && (image_info->scene != 0))
   2059     return(MagickTrue);
   2060   compression=(PSDCompressionType) ReadBlobMSBShort(image);
   2061   image->compression=ConvertPSDCompression(compression);
   2062 
   2063   if (compression != Raw && compression != RLE)
   2064     {
   2065       (void) ThrowMagickException(exception,GetMagickModule(),
   2066         TypeWarning,"CompressionNotSupported","'%.20g'",(double) compression);
   2067       return(MagickFalse);
   2068     }
   2069 
   2070   sizes=(MagickOffsetType *) NULL;
   2071   if (compression == RLE)
   2072     {
   2073       sizes=ReadPSDRLESizes(image,psd_info,image->rows*psd_info->channels);
   2074       if (sizes == (MagickOffsetType *) NULL)
   2075         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   2076           image->filename);
   2077     }
   2078 
   2079   status=MagickTrue;
   2080   for (i=0; i < (ssize_t) psd_info->channels; i++)
   2081   {
   2082     ssize_t
   2083       type;
   2084 
   2085     type=i;
   2086     if ((type == 1) && (psd_info->channels == 2))
   2087       type=-1;
   2088 
   2089     if (compression == RLE)
   2090       status=ReadPSDChannelRLE(image,psd_info,type,sizes+(i*image->rows),
   2091         exception);
   2092     else
   2093       status=ReadPSDChannelRaw(image,psd_info->channels,type,exception);
   2094 
   2095     if (status != MagickFalse)
   2096       status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType) i,
   2097         psd_info->channels);
   2098 
   2099     if (status == MagickFalse)
   2100       break;
   2101   }
   2102 
   2103   if ((status != MagickFalse) && (image->colorspace == CMYKColorspace))
   2104     status=NegateCMYK(image,exception);
   2105 
   2106   if (status != MagickFalse)
   2107     status=CorrectPSDAlphaBlend(image_info,image,exception);
   2108 
   2109   sizes=(MagickOffsetType *) RelinquishMagickMemory(sizes);
   2110 
   2111   return(status);
   2112 }
   2113 
   2114 static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
   2115 {
   2116   Image
   2117     *image;
   2118 
   2119   MagickBooleanType
   2120     has_merged_image,
   2121     skip_layers;
   2122 
   2123   MagickOffsetType
   2124     offset;
   2125 
   2126   MagickSizeType
   2127     length;
   2128 
   2129   MagickBooleanType
   2130     status;
   2131 
   2132   PSDInfo
   2133     psd_info;
   2134 
   2135   register ssize_t
   2136     i;
   2137 
   2138   size_t
   2139     imageListLength;
   2140 
   2141   ssize_t
   2142     count;
   2143 
   2144   StringInfo
   2145     *profile;
   2146 
   2147   /*
   2148     Open image file.
   2149   */
   2150   assert(image_info != (const ImageInfo *) NULL);
   2151   assert(image_info->signature == MagickCoreSignature);
   2152   if (image_info->debug != MagickFalse)
   2153     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   2154       image_info->filename);
   2155   assert(exception != (ExceptionInfo *) NULL);
   2156   assert(exception->signature == MagickCoreSignature);
   2157 
   2158   image=AcquireImage(image_info,exception);
   2159   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   2160   if (status == MagickFalse)
   2161     {
   2162       image=DestroyImageList(image);
   2163       return((Image *) NULL);
   2164     }
   2165   /*
   2166     Read image header.
   2167   */
   2168   image->endian=MSBEndian;
   2169   count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
   2170   psd_info.version=ReadBlobMSBShort(image);
   2171   if ((count != 4) || (LocaleNCompare(psd_info.signature,"8BPS",4) != 0) ||
   2172       ((psd_info.version != 1) && (psd_info.version != 2)))
   2173     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2174   (void) ReadBlob(image,6,psd_info.reserved);
   2175   psd_info.channels=ReadBlobMSBShort(image);
   2176   if (psd_info.channels < 1)
   2177     ThrowReaderException(CorruptImageError,"MissingImageChannel");
   2178   if (psd_info.channels > MaxPSDChannels)
   2179     ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
   2180   psd_info.rows=ReadBlobMSBLong(image);
   2181   psd_info.columns=ReadBlobMSBLong(image);
   2182   if ((psd_info.version == 1) && ((psd_info.rows > 30000) ||
   2183       (psd_info.columns > 30000)))
   2184     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2185   psd_info.depth=ReadBlobMSBShort(image);
   2186   if ((psd_info.depth != 1) && (psd_info.depth != 8) &&
   2187       (psd_info.depth != 16) && (psd_info.depth != 32))
   2188     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2189   psd_info.mode=ReadBlobMSBShort(image);
   2190   if ((psd_info.mode == IndexedMode) && (psd_info.channels > 3))
   2191     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2192   if (image->debug != MagickFalse)
   2193     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2194       "  Image is %.20g x %.20g with channels=%.20g, depth=%.20g, mode=%s",
   2195       (double) psd_info.columns,(double) psd_info.rows,(double)
   2196       psd_info.channels,(double) psd_info.depth,ModeToString((PSDImageType)
   2197       psd_info.mode));
   2198   if (EOFBlob(image) != MagickFalse)
   2199     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2200   /*
   2201     Initialize image.
   2202   */
   2203   image->depth=psd_info.depth;
   2204   image->columns=psd_info.columns;
   2205   image->rows=psd_info.rows;
   2206   status=SetImageExtent(image,image->columns,image->rows,exception);
   2207   if (status == MagickFalse)
   2208     return(DestroyImageList(image));
   2209   status=ResetImagePixels(image,exception);
   2210   if (status == MagickFalse)
   2211     return(DestroyImageList(image));
   2212   psd_info.min_channels=3;
   2213   if (psd_info.mode == LabMode)
   2214     (void) SetImageColorspace(image,LabColorspace,exception);
   2215   if (psd_info.mode == CMYKMode)
   2216     {
   2217       psd_info.min_channels=4;
   2218       (void) SetImageColorspace(image,CMYKColorspace,exception);
   2219     }
   2220   else if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
   2221            (psd_info.mode == DuotoneMode))
   2222     {
   2223       if (psd_info.depth != 32)
   2224         {
   2225           status=AcquireImageColormap(image,(size_t) (psd_info.depth < 16 ?
   2226             256 : 65536),exception);
   2227           if (status == MagickFalse)
   2228             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   2229           if (image->debug != MagickFalse)
   2230             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2231               "  Image colormap allocated");
   2232         }
   2233       psd_info.min_channels=1;
   2234       (void) SetImageColorspace(image,GRAYColorspace,exception);
   2235     }
   2236   if (psd_info.channels < psd_info.min_channels)
   2237     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2238   /*
   2239     Read PSD raster colormap only present for indexed and duotone images.
   2240   */
   2241   length=ReadBlobMSBLong(image);
   2242   if ((psd_info.mode == IndexedMode) && (length < 3))
   2243     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2244   if (length != 0)
   2245     {
   2246       if (image->debug != MagickFalse)
   2247         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2248           "  reading colormap");
   2249       if ((psd_info.mode == DuotoneMode) || (psd_info.depth == 32))
   2250         {
   2251           /*
   2252             Duotone image data;  the format of this data is undocumented.
   2253             32 bits per pixel;  the colormap is ignored.
   2254           */
   2255           (void) SeekBlob(image,(const MagickOffsetType) length,SEEK_CUR);
   2256         }
   2257       else
   2258         {
   2259           size_t
   2260             number_colors;
   2261 
   2262           /*
   2263             Read PSD raster colormap.
   2264           */
   2265           number_colors=(size_t) length/3;
   2266           if (number_colors > 65536)
   2267             ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2268           if (AcquireImageColormap(image,number_colors,exception) == MagickFalse)
   2269             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   2270           for (i=0; i < (ssize_t) image->colors; i++)
   2271             image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(
   2272               (unsigned char) ReadBlobByte(image));
   2273           for (i=0; i < (ssize_t) image->colors; i++)
   2274             image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(
   2275               (unsigned char) ReadBlobByte(image));
   2276           for (i=0; i < (ssize_t) image->colors; i++)
   2277             image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(
   2278               (unsigned char) ReadBlobByte(image));
   2279           image->alpha_trait=UndefinedPixelTrait;
   2280         }
   2281     }
   2282   if ((image->depth == 1) && (image->storage_class != PseudoClass))
   2283     ThrowReaderException(CorruptImageError, "ImproperImageHeader");
   2284   has_merged_image=MagickTrue;
   2285   profile=(StringInfo *) NULL;
   2286   length=ReadBlobMSBLong(image);
   2287   if (length != 0)
   2288     {
   2289       unsigned char
   2290         *blocks;
   2291 
   2292       /*
   2293         Image resources block.
   2294       */
   2295       if (image->debug != MagickFalse)
   2296         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2297           "  reading image resource blocks - %.20g bytes",(double)
   2298           ((MagickOffsetType) length));
   2299       if (length > GetBlobSize(image))
   2300         ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
   2301       blocks=(unsigned char *) AcquireQuantumMemory((size_t) length,
   2302         sizeof(*blocks));
   2303       if (blocks == (unsigned char *) NULL)
   2304         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   2305       count=ReadBlob(image,(size_t) length,blocks);
   2306       if ((count != (ssize_t) length) || (length < 4) ||
   2307           (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
   2308         {
   2309           blocks=(unsigned char *) RelinquishMagickMemory(blocks);
   2310           ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   2311         }
   2312       profile=ParseImageResourceBlocks(image,blocks,(size_t) length,
   2313         &has_merged_image,exception);
   2314       blocks=(unsigned char *) RelinquishMagickMemory(blocks);
   2315     }
   2316   /*
   2317     Layer and mask block.
   2318   */
   2319   length=GetPSDSize(&psd_info,image);
   2320   if (length == 8)
   2321     {
   2322       length=ReadBlobMSBLong(image);
   2323       length=ReadBlobMSBLong(image);
   2324     }
   2325   offset=TellBlob(image);
   2326   skip_layers=MagickFalse;
   2327   if ((image_info->number_scenes == 1) && (image_info->scene == 0) &&
   2328       (has_merged_image != MagickFalse))
   2329     {
   2330       if (image->debug != MagickFalse)
   2331         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2332           "  read composite only");
   2333       skip_layers=MagickTrue;
   2334     }
   2335   if (length == 0)
   2336     {
   2337       if (image->debug != MagickFalse)
   2338         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2339           "  image has no layers");
   2340     }
   2341   else
   2342     {
   2343       if (ReadPSDLayersInternal(image,image_info,&psd_info,skip_layers,
   2344             exception) != MagickTrue)
   2345         {
   2346           if (profile != (StringInfo *) NULL)
   2347             profile=DestroyStringInfo(profile);
   2348           (void) CloseBlob(image);
   2349           image=DestroyImageList(image);
   2350           return((Image *) NULL);
   2351         }
   2352 
   2353       /*
   2354          Skip the rest of the layer and mask information.
   2355       */
   2356       (void) SeekBlob(image,offset+length,SEEK_SET);
   2357     }
   2358   /*
   2359     If we are only "pinging" the image, then we're done - so return.
   2360   */
   2361   if (EOFBlob(image) != MagickFalse)
   2362     {
   2363       if (profile != (StringInfo *) NULL)
   2364         profile=DestroyStringInfo(profile);
   2365       ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
   2366     }
   2367   if (image_info->ping != MagickFalse)
   2368     {
   2369       if (profile != (StringInfo *) NULL)
   2370         profile=DestroyStringInfo(profile);
   2371       (void) CloseBlob(image);
   2372       return(GetFirstImageInList(image));
   2373     }
   2374   /*
   2375     Read the precombined layer, present for PSD < 4 compatibility.
   2376   */
   2377   if (image->debug != MagickFalse)
   2378     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   2379       "  reading the precombined layer");
   2380   imageListLength=GetImageListLength(image);
   2381   if ((has_merged_image != MagickFalse) || (imageListLength == 1))
   2382     has_merged_image=(MagickBooleanType) ReadPSDMergedImage(image_info,image,
   2383       &psd_info,exception);
   2384   if ((has_merged_image == MagickFalse) && (imageListLength == 1) &&
   2385       (length != 0))
   2386     {
   2387       (void) SeekBlob(image,offset,SEEK_SET);
   2388       status=ReadPSDLayersInternal(image,image_info,&psd_info,MagickFalse,
   2389         exception);
   2390       if (status != MagickTrue)
   2391         {
   2392           if (profile != (StringInfo *) NULL)
   2393             profile=DestroyStringInfo(profile);
   2394           (void) CloseBlob(image);
   2395           image=DestroyImageList(image);
   2396           return((Image *) NULL);
   2397         }
   2398     }
   2399   if (has_merged_image == MagickFalse)
   2400     {
   2401       Image
   2402         *merged;
   2403 
   2404       if (imageListLength == 1)
   2405         {
   2406           if (profile != (StringInfo *) NULL)
   2407             profile=DestroyStringInfo(profile);
   2408           ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
   2409         }
   2410       image->background_color.alpha=(MagickRealType) TransparentAlpha;
   2411       image->background_color.alpha_trait=BlendPixelTrait;
   2412       (void) SetImageBackgroundColor(image,exception);
   2413       merged=MergeImageLayers(image,FlattenLayer,exception);
   2414       ReplaceImageInList(&image,merged);
   2415     }
   2416   if (profile != (StringInfo *) NULL)
   2417     {
   2418       Image
   2419         *next;
   2420 
   2421       i=0;
   2422       next=image;
   2423       while (next != (Image *) NULL)
   2424       {
   2425         if (PSDSkipImage(image_info,i++) == MagickFalse)
   2426           (void) SetImageProfile(next,GetStringInfoName(profile),profile,
   2427             exception);
   2428         next=next->next;
   2429       }
   2430       profile=DestroyStringInfo(profile);
   2431     }
   2432   (void) CloseBlob(image);
   2433   return(GetFirstImageInList(image));
   2434 }
   2435 
   2436 /*
   2438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2439 %                                                                             %
   2440 %                                                                             %
   2441 %                                                                             %
   2442 %   R e g i s t e r P S D I m a g e                                           %
   2443 %                                                                             %
   2444 %                                                                             %
   2445 %                                                                             %
   2446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2447 %
   2448 %  RegisterPSDImage() adds properties for the PSD image format to
   2449 %  the list of supported formats.  The properties include the image format
   2450 %  tag, a method to read and/or write the format, whether the format
   2451 %  supports the saving of more than one frame to the same file or blob,
   2452 %  whether the format supports native in-memory I/O, and a brief
   2453 %  description of the format.
   2454 %
   2455 %  The format of the RegisterPSDImage method is:
   2456 %
   2457 %      size_t RegisterPSDImage(void)
   2458 %
   2459 */
   2460 ModuleExport size_t RegisterPSDImage(void)
   2461 {
   2462   MagickInfo
   2463     *entry;
   2464 
   2465   entry=AcquireMagickInfo("PSD","PSB","Adobe Large Document Format");
   2466   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
   2467   entry->encoder=(EncodeImageHandler *) WritePSDImage;
   2468   entry->magick=(IsImageFormatHandler *) IsPSD;
   2469   entry->flags|=CoderDecoderSeekableStreamFlag;
   2470   entry->flags|=CoderEncoderSeekableStreamFlag;
   2471   (void) RegisterMagickInfo(entry);
   2472   entry=AcquireMagickInfo("PSD","PSD","Adobe Photoshop bitmap");
   2473   entry->decoder=(DecodeImageHandler *) ReadPSDImage;
   2474   entry->encoder=(EncodeImageHandler *) WritePSDImage;
   2475   entry->magick=(IsImageFormatHandler *) IsPSD;
   2476   entry->flags|=CoderDecoderSeekableStreamFlag;
   2477   entry->flags|=CoderEncoderSeekableStreamFlag;
   2478   (void) RegisterMagickInfo(entry);
   2479   return(MagickImageCoderSignature);
   2480 }
   2481 
   2482 /*
   2484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2485 %                                                                             %
   2486 %                                                                             %
   2487 %                                                                             %
   2488 %   U n r e g i s t e r P S D I m a g e                                       %
   2489 %                                                                             %
   2490 %                                                                             %
   2491 %                                                                             %
   2492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2493 %
   2494 %  UnregisterPSDImage() removes format registrations made by the
   2495 %  PSD module from the list of supported formats.
   2496 %
   2497 %  The format of the UnregisterPSDImage method is:
   2498 %
   2499 %      UnregisterPSDImage(void)
   2500 %
   2501 */
   2502 ModuleExport void UnregisterPSDImage(void)
   2503 {
   2504   (void) UnregisterMagickInfo("PSB");
   2505   (void) UnregisterMagickInfo("PSD");
   2506 }
   2507 
   2508 /*
   2510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2511 %                                                                             %
   2512 %                                                                             %
   2513 %                                                                             %
   2514 %   W r i t e P S D I m a g e                                                 %
   2515 %                                                                             %
   2516 %                                                                             %
   2517 %                                                                             %
   2518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2519 %
   2520 %  WritePSDImage() writes an image in the Adobe Photoshop encoded image format.
   2521 %
   2522 %  The format of the WritePSDImage method is:
   2523 %
   2524 %      MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image,
   2525 %        ExceptionInfo *exception)
   2526 %
   2527 %  A description of each parameter follows.
   2528 %
   2529 %    o image_info: the image info.
   2530 %
   2531 %    o image:  The image.
   2532 %
   2533 %    o exception: return any errors or warnings in this structure.
   2534 %
   2535 */
   2536 
   2537 static inline ssize_t SetPSDOffset(const PSDInfo *psd_info,Image *image,
   2538   const size_t offset)
   2539 {
   2540   if (psd_info->version == 1)
   2541     return(WriteBlobMSBShort(image,(unsigned short) offset));
   2542   return(WriteBlobMSBLong(image,(unsigned int) offset));
   2543 }
   2544 
   2545 static inline ssize_t WritePSDOffset(const PSDInfo *psd_info,Image *image,
   2546   const MagickSizeType size,const MagickOffsetType offset)
   2547 {
   2548   MagickOffsetType
   2549     current_offset;
   2550 
   2551   ssize_t
   2552     result;
   2553 
   2554   current_offset=TellBlob(image);
   2555   (void) SeekBlob(image,offset,SEEK_SET);
   2556   if (psd_info->version == 1)
   2557     result=WriteBlobMSBShort(image,(unsigned short) size);
   2558   else
   2559     result=WriteBlobMSBLong(image,(unsigned int) size);
   2560   (void) SeekBlob(image,current_offset,SEEK_SET);
   2561   return(result);
   2562 }
   2563 
   2564 static inline ssize_t SetPSDSize(const PSDInfo *psd_info,Image *image,
   2565   const MagickSizeType size)
   2566 {
   2567   if (psd_info->version == 1)
   2568     return(WriteBlobLong(image,(unsigned int) size));
   2569   return(WriteBlobLongLong(image,size));
   2570 }
   2571 
   2572 static inline ssize_t WritePSDSize(const PSDInfo *psd_info,Image *image,
   2573   const MagickSizeType size,const MagickOffsetType offset)
   2574 {
   2575   MagickOffsetType
   2576     current_offset;
   2577 
   2578   ssize_t
   2579     result;
   2580 
   2581   current_offset=TellBlob(image);
   2582   (void) SeekBlob(image,offset,SEEK_SET);
   2583   result=SetPSDSize(psd_info,image,size);
   2584   (void) SeekBlob(image,current_offset,SEEK_SET);
   2585   return(result);
   2586 }
   2587 
   2588 static size_t PSDPackbitsEncodeImage(Image *image,const size_t length,
   2589   const unsigned char *pixels,unsigned char *compact_pixels,
   2590   ExceptionInfo *exception)
   2591 {
   2592   int
   2593     count;
   2594 
   2595   register ssize_t
   2596     i,
   2597     j;
   2598 
   2599   register unsigned char
   2600     *q;
   2601 
   2602   unsigned char
   2603     *packbits;
   2604 
   2605   /*
   2606     Compress pixels with Packbits encoding.
   2607   */
   2608   assert(image != (Image *) NULL);
   2609   assert(image->signature == MagickCoreSignature);
   2610   if (image->debug != MagickFalse)
   2611     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2612   assert(pixels != (unsigned char *) NULL);
   2613   assert(compact_pixels != (unsigned char *) NULL);
   2614   packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
   2615   if (packbits == (unsigned char *) NULL)
   2616     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   2617       image->filename);
   2618   q=compact_pixels;
   2619   for (i=(ssize_t) length; i != 0; )
   2620   {
   2621     switch (i)
   2622     {
   2623       case 1:
   2624       {
   2625         i--;
   2626         *q++=(unsigned char) 0;
   2627         *q++=(*pixels);
   2628         break;
   2629       }
   2630       case 2:
   2631       {
   2632         i-=2;
   2633         *q++=(unsigned char) 1;
   2634         *q++=(*pixels);
   2635         *q++=pixels[1];
   2636         break;
   2637       }
   2638       case 3:
   2639       {
   2640         i-=3;
   2641         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
   2642           {
   2643             *q++=(unsigned char) ((256-3)+1);
   2644             *q++=(*pixels);
   2645             break;
   2646           }
   2647         *q++=(unsigned char) 2;
   2648         *q++=(*pixels);
   2649         *q++=pixels[1];
   2650         *q++=pixels[2];
   2651         break;
   2652       }
   2653       default:
   2654       {
   2655         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
   2656           {
   2657             /*
   2658               Packed run.
   2659             */
   2660             count=3;
   2661             while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
   2662             {
   2663               count++;
   2664               if (count >= 127)
   2665                 break;
   2666             }
   2667             i-=count;
   2668             *q++=(unsigned char) ((256-count)+1);
   2669             *q++=(*pixels);
   2670             pixels+=count;
   2671             break;
   2672           }
   2673         /*
   2674           Literal run.
   2675         */
   2676         count=0;
   2677         while ((*(pixels+count) != *(pixels+count+1)) ||
   2678                (*(pixels+count+1) != *(pixels+count+2)))
   2679         {
   2680           packbits[count+1]=pixels[count];
   2681           count++;
   2682           if (((ssize_t) count >= (i-3)) || (count >= 127))
   2683             break;
   2684         }
   2685         i-=count;
   2686         *packbits=(unsigned char) (count-1);
   2687         for (j=0; j <= (ssize_t) count; j++)
   2688           *q++=packbits[j];
   2689         pixels+=count;
   2690         break;
   2691       }
   2692     }
   2693   }
   2694   *q++=(unsigned char) 128;  /* EOD marker */
   2695   packbits=(unsigned char *) RelinquishMagickMemory(packbits);
   2696   return((size_t) (q-compact_pixels));
   2697 }
   2698 
   2699 static size_t WriteCompressionStart(const PSDInfo *psd_info,Image *image,
   2700   const Image *next_image,const CompressionType compression,
   2701   const ssize_t channels)
   2702 {
   2703   size_t
   2704     length;
   2705 
   2706   ssize_t
   2707     i,
   2708     y;
   2709 
   2710   if (compression == RLECompression)
   2711     {
   2712       length=(size_t) WriteBlobShort(image,RLE);
   2713       for (i=0; i < channels; i++)
   2714         for (y=0; y < (ssize_t) next_image->rows; y++)
   2715           length+=SetPSDOffset(psd_info,image,0);
   2716     }
   2717 #ifdef MAGICKCORE_ZLIB_DELEGATE
   2718   else if (compression == ZipCompression)
   2719     length=(size_t) WriteBlobShort(image,ZipWithoutPrediction);
   2720 #endif
   2721   else
   2722     length=(size_t) WriteBlobShort(image,Raw);
   2723   return(length);
   2724 }
   2725 
   2726 static size_t WritePSDChannel(const PSDInfo *psd_info,
   2727   const ImageInfo *image_info,Image *image,Image *next_image,
   2728   const QuantumType quantum_type, unsigned char *compact_pixels,
   2729   MagickOffsetType size_offset,const MagickBooleanType separate,
   2730   const CompressionType compression,ExceptionInfo *exception)
   2731 {
   2732   MagickBooleanType
   2733     monochrome;
   2734 
   2735   QuantumInfo
   2736     *quantum_info;
   2737 
   2738   register const Quantum
   2739     *p;
   2740 
   2741   register ssize_t
   2742     i;
   2743 
   2744   size_t
   2745     count,
   2746     length;
   2747 
   2748   ssize_t
   2749     y;
   2750 
   2751   unsigned char
   2752     *pixels;
   2753 
   2754 #ifdef MAGICKCORE_ZLIB_DELEGATE
   2755 
   2756 #define CHUNK 16384
   2757 
   2758   int
   2759     flush,
   2760     level;
   2761 
   2762   unsigned char
   2763     *compressed_pixels;
   2764 
   2765   z_stream
   2766     stream;
   2767 
   2768   compressed_pixels=(unsigned char *) NULL;
   2769   flush=Z_NO_FLUSH;
   2770 #endif
   2771   count=0;
   2772   if (separate != MagickFalse)
   2773     {
   2774       size_offset=TellBlob(image)+2;
   2775       count+=WriteCompressionStart(psd_info,image,next_image,compression,1);
   2776     }
   2777   if (next_image->depth > 8)
   2778     next_image->depth=16;
   2779   monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
   2780     MagickTrue : MagickFalse;
   2781   quantum_info=AcquireQuantumInfo(image_info,next_image);
   2782   if (quantum_info == (QuantumInfo *) NULL)
   2783     return(0);
   2784   pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   2785 #ifdef MAGICKCORE_ZLIB_DELEGATE
   2786   if (compression == ZipCompression)
   2787     {
   2788       compressed_pixels=(unsigned char *) AcquireQuantumMemory(CHUNK,
   2789         sizeof(*compressed_pixels));
   2790       if (compressed_pixels == (unsigned char *) NULL)
   2791         {
   2792           quantum_info=DestroyQuantumInfo(quantum_info);
   2793           return(0);
   2794         }
   2795       memset(&stream,0,sizeof(stream));
   2796       stream.data_type=Z_BINARY;
   2797       level=Z_DEFAULT_COMPRESSION;
   2798       if ((image_info->quality > 0 && image_info->quality < 10))
   2799         level=(int) image_info->quality;
   2800       if (deflateInit(&stream,level) != Z_OK)
   2801         {
   2802           quantum_info=DestroyQuantumInfo(quantum_info);
   2803           compressed_pixels=(unsigned char *) RelinquishMagickMemory(
   2804             compressed_pixels);
   2805           return(0);
   2806         }
   2807     }
   2808 #endif
   2809   for (y=0; y < (ssize_t) next_image->rows; y++)
   2810   {
   2811     p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception);
   2812     if (p == (const Quantum *) NULL)
   2813       break;
   2814     length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info,
   2815       quantum_type,pixels,exception);
   2816     if (monochrome != MagickFalse)
   2817       for (i=0; i < (ssize_t) length; i++)
   2818         pixels[i]=(~pixels[i]);
   2819     if (compression == RLECompression)
   2820       {
   2821         length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels,
   2822           exception);
   2823         count+=WriteBlob(image,length,compact_pixels);
   2824         size_offset+=WritePSDOffset(psd_info,image,length,size_offset);
   2825       }
   2826 #ifdef MAGICKCORE_ZLIB_DELEGATE
   2827     else if (compression == ZipCompression)
   2828       {
   2829         stream.avail_in=(uInt) length;
   2830         stream.next_in=(Bytef *) pixels;
   2831         if (y == (ssize_t) next_image->rows-1)
   2832           flush=Z_FINISH;
   2833         do {
   2834             stream.avail_out=(uInt) CHUNK;
   2835             stream.next_out=(Bytef *) compressed_pixels;
   2836             if (deflate(&stream,flush) == Z_STREAM_ERROR)
   2837               break;
   2838             length=(size_t) CHUNK-stream.avail_out;
   2839             if (length > 0)
   2840               count+=WriteBlob(image,length,compressed_pixels);
   2841         } while (stream.avail_out == 0);
   2842       }
   2843 #endif
   2844     else
   2845       count+=WriteBlob(image,length,pixels);
   2846   }
   2847 #ifdef MAGICKCORE_ZLIB_DELEGATE
   2848   if (compression == ZipCompression)
   2849     {
   2850       (void) deflateEnd(&stream);
   2851       compressed_pixels=(unsigned char *) RelinquishMagickMemory(
   2852         compressed_pixels);
   2853     }
   2854 #endif
   2855   quantum_info=DestroyQuantumInfo(quantum_info);
   2856   return(count);
   2857 }
   2858 
   2859 static unsigned char *AcquireCompactPixels(const Image *image,
   2860   ExceptionInfo *exception)
   2861 {
   2862   size_t
   2863     packet_size;
   2864 
   2865   unsigned char
   2866     *compact_pixels;
   2867 
   2868   packet_size=image->depth > 8UL ? 2UL : 1UL;
   2869   compact_pixels=(unsigned char *) AcquireQuantumMemory((9*
   2870     image->columns)+1,packet_size*sizeof(*compact_pixels));
   2871   if (compact_pixels == (unsigned char *) NULL)
   2872     {
   2873       (void) ThrowMagickException(exception,GetMagickModule(),
   2874         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
   2875     }
   2876   return(compact_pixels);
   2877 }
   2878 
   2879 static size_t WritePSDChannels(const PSDInfo *psd_info,
   2880   const ImageInfo *image_info,Image *image,Image *next_image,
   2881   MagickOffsetType size_offset,const MagickBooleanType separate,
   2882   ExceptionInfo *exception)
   2883 {
   2884   CompressionType
   2885     compression;
   2886 
   2887   Image
   2888     *mask;
   2889 
   2890   MagickOffsetType
   2891     rows_offset;
   2892 
   2893   size_t
   2894     channels,
   2895     count,
   2896     length,
   2897     offset_length;
   2898 
   2899   unsigned char
   2900     *compact_pixels;
   2901 
   2902   count=0;
   2903   offset_length=0;
   2904   rows_offset=0;
   2905   compact_pixels=(unsigned char *) NULL;
   2906   compression=next_image->compression;
   2907   if (image_info->compression != UndefinedCompression)
   2908     compression=image_info->compression;
   2909   if (compression == RLECompression)
   2910     {
   2911       compact_pixels=AcquireCompactPixels(next_image,exception);
   2912       if (compact_pixels == (unsigned char *) NULL)
   2913         return(0);
   2914     }
   2915   channels=1;
   2916   if (separate == MagickFalse)
   2917     {
   2918       if (next_image->storage_class != PseudoClass)
   2919         {
   2920           if (IsImageGray(next_image) == MagickFalse)
   2921             channels=(size_t) (next_image->colorspace == CMYKColorspace ? 4 :
   2922               3);
   2923           if (next_image->alpha_trait != UndefinedPixelTrait)
   2924             channels++;
   2925         }
   2926       rows_offset=TellBlob(image)+2;
   2927       count+=WriteCompressionStart(psd_info,image,next_image,compression,
   2928         (ssize_t) channels);
   2929       offset_length=(next_image->rows*(psd_info->version == 1 ? 2 : 4));
   2930     }
   2931   size_offset+=2;
   2932   if (next_image->storage_class == PseudoClass)
   2933     {
   2934       length=WritePSDChannel(psd_info,image_info,image,next_image,
   2935         IndexQuantum,compact_pixels,rows_offset,separate,compression,
   2936         exception);
   2937       if (separate != MagickFalse)
   2938         size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
   2939       else
   2940         rows_offset+=offset_length;
   2941       count+=length;
   2942     }
   2943   else
   2944     {
   2945       if (IsImageGray(next_image) != MagickFalse)
   2946         {
   2947           length=WritePSDChannel(psd_info,image_info,image,next_image,
   2948             GrayQuantum,compact_pixels,rows_offset,separate,compression,
   2949             exception);
   2950           if (separate != MagickFalse)
   2951             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
   2952           else
   2953             rows_offset+=offset_length;
   2954           count+=length;
   2955         }
   2956       else
   2957         {
   2958           if (next_image->colorspace == CMYKColorspace)
   2959             (void) NegateCMYK(next_image,exception);
   2960 
   2961           length=WritePSDChannel(psd_info,image_info,image,next_image,
   2962             RedQuantum,compact_pixels,rows_offset,separate,compression,
   2963             exception);
   2964           if (separate != MagickFalse)
   2965             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
   2966           else
   2967             rows_offset+=offset_length;
   2968           count+=length;
   2969 
   2970           length=WritePSDChannel(psd_info,image_info,image,next_image,
   2971             GreenQuantum,compact_pixels,rows_offset,separate,compression,
   2972             exception);
   2973           if (separate != MagickFalse)
   2974             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
   2975           else
   2976             rows_offset+=offset_length;
   2977           count+=length;
   2978 
   2979           length=WritePSDChannel(psd_info,image_info,image,next_image,
   2980             BlueQuantum,compact_pixels,rows_offset,separate,compression,
   2981             exception);
   2982           if (separate != MagickFalse)
   2983             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
   2984           else
   2985             rows_offset+=offset_length;
   2986           count+=length;
   2987 
   2988           if (next_image->colorspace == CMYKColorspace)
   2989             {
   2990               length=WritePSDChannel(psd_info,image_info,image,next_image,
   2991                 BlackQuantum,compact_pixels,rows_offset,separate,compression,
   2992                 exception);
   2993               if (separate != MagickFalse)
   2994                 size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
   2995               else
   2996                 rows_offset+=offset_length;
   2997               count+=length;
   2998             }
   2999         }
   3000       if (next_image->alpha_trait != UndefinedPixelTrait)
   3001         {
   3002           length=WritePSDChannel(psd_info,image_info,image,next_image,
   3003             AlphaQuantum,compact_pixels,rows_offset,separate,compression,
   3004             exception);
   3005           if (separate != MagickFalse)
   3006             size_offset+=WritePSDSize(psd_info,image,length,size_offset)+2;
   3007           else
   3008             rows_offset+=offset_length;
   3009           count+=length;
   3010         }
   3011     }
   3012   compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels);
   3013   if (next_image->colorspace == CMYKColorspace)
   3014     (void) NegateCMYK(next_image,exception);
   3015   if (separate != MagickFalse)
   3016     {
   3017       const char
   3018         *property;
   3019 
   3020       property=GetImageArtifact(next_image,"psd:opacity-mask");
   3021       if (property != (const char *) NULL)
   3022         {
   3023           mask=(Image *) GetImageRegistry(ImageRegistryType,property,
   3024             exception);
   3025           if (mask != (Image *) NULL)
   3026             {
   3027               if (compression == RLECompression)
   3028                 {
   3029                   compact_pixels=AcquireCompactPixels(mask,exception);
   3030                   if (compact_pixels == (unsigned char *) NULL)
   3031                     return(0);
   3032                 }
   3033               length=WritePSDChannel(psd_info,image_info,image,mask,
   3034                 RedQuantum,compact_pixels,rows_offset,MagickTrue,compression,
   3035                 exception);
   3036               (void) WritePSDSize(psd_info,image,length,size_offset);
   3037               count+=length;
   3038               compact_pixels=(unsigned char *) RelinquishMagickMemory(
   3039                 compact_pixels);
   3040             }
   3041         }
   3042     }
   3043   return(count);
   3044 }
   3045 
   3046 static size_t WritePascalString(Image *image,const char *value,size_t padding)
   3047 {
   3048   size_t
   3049     count,
   3050     length;
   3051 
   3052   register ssize_t
   3053     i;
   3054 
   3055   /*
   3056     Max length is 255.
   3057   */
   3058   count=0;
   3059   length=(strlen(value) > 255UL ) ? 255UL : strlen(value);
   3060   if (length ==  0)
   3061     count+=WriteBlobByte(image,0);
   3062   else
   3063     {
   3064       count+=WriteBlobByte(image,(unsigned char) length);
   3065       count+=WriteBlob(image,length,(const unsigned char *) value);
   3066     }
   3067   length++;
   3068   if ((length % padding) == 0)
   3069     return(count);
   3070   for (i=0; i < (ssize_t) (padding-(length % padding)); i++)
   3071     count+=WriteBlobByte(image,0);
   3072   return(count);
   3073 }
   3074 
   3075 static void WriteResolutionResourceBlock(Image *image)
   3076 {
   3077   double
   3078     x_resolution,
   3079     y_resolution;
   3080 
   3081   unsigned short
   3082     units;
   3083 
   3084   if (image->units == PixelsPerCentimeterResolution)
   3085     {
   3086       x_resolution=2.54*65536.0*image->resolution.x+0.5;
   3087       y_resolution=2.54*65536.0*image->resolution.y+0.5;
   3088       units=2;
   3089     }
   3090   else
   3091     {
   3092       x_resolution=65536.0*image->resolution.x+0.5;
   3093       y_resolution=65536.0*image->resolution.y+0.5;
   3094       units=1;
   3095     }
   3096   (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
   3097   (void) WriteBlobMSBShort(image,0x03ED);
   3098   (void) WriteBlobMSBShort(image,0);
   3099   (void) WriteBlobMSBLong(image,16); /* resource size */
   3100   (void) WriteBlobMSBLong(image,(unsigned int) (x_resolution+0.5));
   3101   (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
   3102   (void) WriteBlobMSBShort(image,units); /* width unit */
   3103   (void) WriteBlobMSBLong(image,(unsigned int) (y_resolution+0.5));
   3104   (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
   3105   (void) WriteBlobMSBShort(image,units); /* height unit */
   3106 }
   3107 
   3108 static inline size_t WriteChannelSize(const PSDInfo *psd_info,Image *image,
   3109   const signed short channel)
   3110 {
   3111   size_t
   3112     count;
   3113 
   3114   count=(size_t) WriteBlobShort(image,(const unsigned short) channel);
   3115   count+=SetPSDSize(psd_info,image,0);
   3116   return(count);
   3117 }
   3118 
   3119 static void RemoveICCProfileFromResourceBlock(StringInfo *bim_profile)
   3120 {
   3121   register const unsigned char
   3122     *p;
   3123 
   3124   size_t
   3125     length;
   3126 
   3127   unsigned char
   3128     *datum;
   3129 
   3130   unsigned int
   3131     count,
   3132     long_sans;
   3133 
   3134   unsigned short
   3135     id,
   3136     short_sans;
   3137 
   3138   length=GetStringInfoLength(bim_profile);
   3139   if (length < 16)
   3140     return;
   3141   datum=GetStringInfoDatum(bim_profile);
   3142   for (p=datum; (p >= datum) && (p < (datum+length-16)); )
   3143   {
   3144     register unsigned char
   3145       *q;
   3146 
   3147     q=(unsigned char *) p;
   3148     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
   3149       break;
   3150     p=PushLongPixel(MSBEndian,p,&long_sans);
   3151     p=PushShortPixel(MSBEndian,p,&id);
   3152     p=PushShortPixel(MSBEndian,p,&short_sans);
   3153     p=PushLongPixel(MSBEndian,p,&count);
   3154     if (id == 0x0000040f)
   3155       {
   3156         ssize_t
   3157           quantum;
   3158 
   3159         quantum=PSDQuantum(count)+12;
   3160         if ((quantum >= 12) && (quantum < (ssize_t) length))
   3161           {
   3162             if ((q+quantum < (datum+length-16)))
   3163               (void) memmove(q,q+quantum,length-quantum-(q-datum));
   3164             SetStringInfoLength(bim_profile,length-quantum);
   3165           }
   3166         break;
   3167       }
   3168     p+=count;
   3169     if ((count & 0x01) != 0)
   3170       p++;
   3171   }
   3172 }
   3173 
   3174 static void RemoveResolutionFromResourceBlock(StringInfo *bim_profile)
   3175 {
   3176   register const unsigned char
   3177     *p;
   3178 
   3179   size_t
   3180     length;
   3181 
   3182   unsigned char
   3183     *datum;
   3184 
   3185   unsigned int
   3186     count,
   3187     long_sans;
   3188 
   3189   unsigned short
   3190     id,
   3191     short_sans;
   3192 
   3193   length=GetStringInfoLength(bim_profile);
   3194   if (length < 16)
   3195     return;
   3196   datum=GetStringInfoDatum(bim_profile);
   3197   for (p=datum; (p >= datum) && (p < (datum+length-16)); )
   3198   {
   3199     register unsigned char
   3200       *q;
   3201 
   3202     ssize_t
   3203       cnt;
   3204 
   3205     q=(unsigned char *) p;
   3206     if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
   3207       return;
   3208     p=PushLongPixel(MSBEndian,p,&long_sans);
   3209     p=PushShortPixel(MSBEndian,p,&id);
   3210     p=PushShortPixel(MSBEndian,p,&short_sans);
   3211     p=PushLongPixel(MSBEndian,p,&count);
   3212     cnt=PSDQuantum(count);
   3213     if (cnt < 0)
   3214       return;
   3215     if ((id == 0x000003ed) && (cnt < (ssize_t) (length-12)) &&
   3216         ((ssize_t) length-(cnt+12)-(q-datum)) > 0)
   3217       {
   3218         (void) memmove(q,q+cnt+12,length-(cnt+12)-(q-datum));
   3219         SetStringInfoLength(bim_profile,length-(cnt+12));
   3220         break;
   3221       }
   3222     p+=count;
   3223     if ((count & 0x01) != 0)
   3224       p++;
   3225   }
   3226 }
   3227 
   3228 static const StringInfo *GetAdditionalInformation(const ImageInfo *image_info,
   3229   Image *image,ExceptionInfo *exception)
   3230 {
   3231 #define PSDKeySize 5
   3232 #define PSDAllowedLength 36
   3233 
   3234   char
   3235     key[PSDKeySize];
   3236 
   3237   /* Whitelist of keys from: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ */
   3238   const char
   3239     allowed[PSDAllowedLength][PSDKeySize] = {
   3240       "blnc", "blwh", "brit", "brst", "clbl", "clrL", "curv", "expA", "FMsk",
   3241       "GdFl", "grdm", "hue ", "hue2", "infx", "knko", "lclr", "levl", "lnsr",
   3242       "lfx2", "luni", "lrFX", "lspf", "lyid", "lyvr", "mixr", "nvrt", "phfl",
   3243       "post", "PtFl", "selc", "shpa", "sn2P", "SoCo", "thrs", "tsly", "vibA"
   3244     },
   3245     *option;
   3246 
   3247   const StringInfo
   3248     *info;
   3249 
   3250   MagickBooleanType
   3251     found;
   3252 
   3253   register size_t
   3254     i;
   3255 
   3256   size_t
   3257     remaining_length,
   3258     length;
   3259 
   3260   StringInfo
   3261     *profile;
   3262 
   3263   unsigned char
   3264     *p;
   3265 
   3266   unsigned int
   3267     size;
   3268 
   3269   info=GetImageProfile(image,"psd:additional-info");
   3270   if (info == (const StringInfo *) NULL)
   3271     return((const StringInfo *) NULL);
   3272   option=GetImageOption(image_info,"psd:additional-info");
   3273   if (LocaleCompare(option,"all") == 0)
   3274     return(info);
   3275   if (LocaleCompare(option,"selective") != 0)
   3276     {
   3277       profile=RemoveImageProfile(image,"psd:additional-info");
   3278       return(DestroyStringInfo(profile));
   3279     }
   3280   length=GetStringInfoLength(info);
   3281   p=GetStringInfoDatum(info);
   3282   remaining_length=length;
   3283   length=0;
   3284   while (remaining_length >= 12)
   3285   {
   3286     /* skip over signature */
   3287     p+=4;
   3288     key[0]=(char) (*p++);
   3289     key[1]=(char) (*p++);
   3290     key[2]=(char) (*p++);
   3291     key[3]=(char) (*p++);
   3292     key[4]='\0';
   3293     size=(unsigned int) (*p++) << 24;
   3294     size|=(unsigned int) (*p++) << 16;
   3295     size|=(unsigned int) (*p++) << 8;
   3296     size|=(unsigned int) (*p++);
   3297     size=size & 0xffffffff;
   3298     remaining_length-=12;
   3299     if ((size_t) size > remaining_length)
   3300       return((const StringInfo *) NULL);
   3301     found=MagickFalse;
   3302     for (i=0; i < PSDAllowedLength; i++)
   3303     {
   3304       if (LocaleNCompare(key,allowed[i],PSDKeySize) != 0)
   3305         continue;
   3306 
   3307       found=MagickTrue;
   3308       break;
   3309     }
   3310     remaining_length-=(size_t) size;
   3311     if (found == MagickFalse)
   3312       {
   3313         if (remaining_length > 0)
   3314           p=(unsigned char *) memmove(p-12,p+size,remaining_length);
   3315         continue;
   3316       }
   3317     length+=(size_t) size+12;
   3318     p+=size;
   3319   }
   3320   profile=RemoveImageProfile(image,"psd:additional-info");
   3321   if (length == 0)
   3322     return(DestroyStringInfo(profile));
   3323   SetStringInfoLength(profile,(const size_t) length);
   3324   (void) SetImageProfile(image,"psd:additional-info",info,exception);
   3325   return(profile);
   3326 }
   3327 
   3328 static MagickBooleanType WritePSDLayersInternal(Image *image,
   3329   const ImageInfo *image_info,const PSDInfo *psd_info,size_t *layers_size,
   3330   ExceptionInfo *exception)
   3331 {
   3332   char
   3333     layer_name[MagickPathExtent];
   3334 
   3335   const char
   3336     *property;
   3337 
   3338   const StringInfo
   3339     *info;
   3340 
   3341   Image
   3342     *base_image,
   3343     *next_image;
   3344 
   3345   MagickBooleanType
   3346     status;
   3347 
   3348   MagickOffsetType
   3349     *layer_size_offsets,
   3350     size_offset;
   3351 
   3352   register ssize_t
   3353     i;
   3354 
   3355   size_t
   3356     layer_count,
   3357     layer_index,
   3358     length,
   3359     name_length,
   3360     rounded_size,
   3361     size;
   3362 
   3363   status=MagickTrue;
   3364   base_image=GetNextImageInList(image);
   3365   if (base_image == (Image *) NULL)
   3366     base_image=image;
   3367   size=0;
   3368   size_offset=TellBlob(image);
   3369   (void) SetPSDSize(psd_info,image,0);
   3370   layer_count=0;
   3371   for (next_image=base_image; next_image != NULL; )
   3372   {
   3373     layer_count++;
   3374     next_image=GetNextImageInList(next_image);
   3375   }
   3376   if (image->alpha_trait != UndefinedPixelTrait)
   3377     size+=WriteBlobShort(image,-(unsigned short) layer_count);
   3378   else
   3379     size+=WriteBlobShort(image,(unsigned short) layer_count);
   3380   layer_size_offsets=(MagickOffsetType *) AcquireQuantumMemory(
   3381     (size_t) layer_count,sizeof(MagickOffsetType));
   3382   if (layer_size_offsets == (MagickOffsetType *) NULL)
   3383     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   3384   layer_index=0;
   3385   for (next_image=base_image; next_image != NULL; )
   3386   {
   3387     Image
   3388       *mask;
   3389 
   3390     unsigned char
   3391       default_color;
   3392 
   3393     unsigned short
   3394       channels,
   3395       total_channels;
   3396 
   3397     mask=(Image *) NULL;
   3398     property=GetImageArtifact(next_image,"psd:opacity-mask");
   3399     default_color=0;
   3400     if (property != (const char *) NULL)
   3401       {
   3402         mask=(Image *) GetImageRegistry(ImageRegistryType,property,exception);
   3403         default_color=(unsigned char) (strlen(property) == 9 ? 255 : 0);
   3404       }
   3405     size+=WriteBlobSignedLong(image,(signed int) next_image->page.y);
   3406     size+=WriteBlobSignedLong(image,(signed int) next_image->page.x);
   3407     size+=WriteBlobSignedLong(image,(signed int) (next_image->page.y+
   3408       next_image->rows));
   3409     size+=WriteBlobSignedLong(image,(signed int) (next_image->page.x+
   3410       next_image->columns));
   3411     channels=1;
   3412     if ((next_image->storage_class != PseudoClass) &&
   3413         (IsImageGray(next_image) == MagickFalse))
   3414       channels=(unsigned short) (next_image->colorspace == CMYKColorspace ? 4 :
   3415         3);
   3416     total_channels=channels;
   3417     if (next_image->alpha_trait != UndefinedPixelTrait)
   3418       total_channels++;
   3419     if (mask != (Image *) NULL)
   3420       total_channels++;
   3421     size+=WriteBlobShort(image,total_channels);
   3422     layer_size_offsets[layer_index++]=TellBlob(image);
   3423     for (i=0; i < (ssize_t) channels; i++)
   3424       size+=WriteChannelSize(psd_info,image,(signed short) i);
   3425     if (next_image->alpha_trait != UndefinedPixelTrait)
   3426       size+=WriteChannelSize(psd_info,image,-1);
   3427     if (mask != (Image *) NULL)
   3428       size+=WriteChannelSize(psd_info,image,-2);
   3429     size+=WriteBlobString(image,image->endian == LSBEndian ? "MIB8" :"8BIM");
   3430     size+=WriteBlobString(image,CompositeOperatorToPSDBlendMode(next_image));
   3431     property=GetImageArtifact(next_image,"psd:layer.opacity");
   3432     if (property != (const char *) NULL)
   3433       {
   3434         Quantum
   3435           opacity;
   3436 
   3437         opacity=(Quantum) StringToInteger(property);
   3438         size+=WriteBlobByte(image,ScaleQuantumToChar(opacity));
   3439         (void) ApplyPSDLayerOpacity(next_image,opacity,MagickTrue,exception);
   3440       }
   3441     else
   3442       size+=WriteBlobByte(image,255);
   3443     size+=WriteBlobByte(image,0);
   3444     size+=WriteBlobByte(image,(const unsigned char)
   3445       (next_image->compose == NoCompositeOp ? 1 << 0x02 : 1)); /* layer properties - visible, etc. */
   3446     size+=WriteBlobByte(image,0);
   3447     info=GetAdditionalInformation(image_info,next_image,exception);
   3448     property=(const char *) GetImageProperty(next_image,"label",exception);
   3449     if (property == (const char *) NULL)
   3450       {
   3451         (void) FormatLocaleString(layer_name,MagickPathExtent,"L%.20g",
   3452           (double) layer_index);
   3453         property=layer_name;
   3454       }
   3455     name_length=strlen(property)+1;
   3456     if ((name_length % 4) != 0)
   3457       name_length+=(4-(name_length % 4));
   3458     if (info != (const StringInfo *) NULL)
   3459       name_length+=GetStringInfoLength(info);
   3460     name_length+=8;
   3461     if (mask != (Image *) NULL)
   3462       name_length+=20;
   3463     size+=WriteBlobLong(image,(unsigned int) name_length);
   3464     if (mask == (Image *) NULL)
   3465       size+=WriteBlobLong(image,0);
   3466     else
   3467       {
   3468         if (mask->compose != NoCompositeOp)
   3469           (void) ApplyPSDOpacityMask(next_image,mask,ScaleCharToQuantum(
   3470             default_color),MagickTrue,exception);
   3471         mask->page.y+=image->page.y;
   3472         mask->page.x+=image->page.x;
   3473         size+=WriteBlobLong(image,20);
   3474         size+=WriteBlobSignedLong(image,(const signed int) mask->page.y);
   3475         size+=WriteBlobSignedLong(image,(const signed int) mask->page.x);
   3476         size+=WriteBlobSignedLong(image,(const signed int) (mask->rows+
   3477           mask->page.y));
   3478         size+=WriteBlobSignedLong(image,(const signed int) (mask->columns+
   3479           mask->page.x));
   3480         size+=WriteBlobByte(image,default_color);
   3481         size+=WriteBlobByte(image,(const unsigned char)
   3482           (mask->compose == NoCompositeOp ? 2 : 0));
   3483         size+=WriteBlobMSBShort(image,0);
   3484       }
   3485     size+=WriteBlobLong(image,0);
   3486     size+=WritePascalString(image,property,4);
   3487     if (info != (const StringInfo *) NULL)
   3488       size+=WriteBlob(image,GetStringInfoLength(info),
   3489         GetStringInfoDatum(info));
   3490     next_image=GetNextImageInList(next_image);
   3491   }
   3492   /*
   3493     Now the image data!
   3494   */
   3495   next_image=base_image;
   3496   layer_index=0;
   3497   while (next_image != NULL)
   3498   {
   3499     length=WritePSDChannels(psd_info,image_info,image,next_image,
   3500       layer_size_offsets[layer_index++],MagickTrue,exception);
   3501     if (length == 0)
   3502       {
   3503         status=MagickFalse;
   3504         break;
   3505       }
   3506     size+=length;
   3507     next_image=GetNextImageInList(next_image);
   3508   }
   3509   /*
   3510     Write the total size
   3511   */
   3512   if (layers_size != (size_t*) NULL)
   3513     *layers_size=size;
   3514   if ((size/2) != ((size+1)/2))
   3515     rounded_size=size+1;
   3516   else
   3517     rounded_size=size;
   3518   (void) WritePSDSize(psd_info,image,rounded_size,size_offset);
   3519   layer_size_offsets=(MagickOffsetType *) RelinquishMagickMemory(
   3520     layer_size_offsets);
   3521   /*
   3522     Remove the opacity mask from the registry
   3523   */
   3524   next_image=base_image;
   3525   while (next_image != (Image *) NULL)
   3526   {
   3527     property=GetImageArtifact(next_image,"psd:opacity-mask");
   3528     if (property != (const char *) NULL)
   3529       (void) DeleteImageRegistry(property);
   3530     next_image=GetNextImageInList(next_image);
   3531   }
   3532 
   3533   return(status);
   3534 }
   3535 
   3536 ModuleExport MagickBooleanType WritePSDLayers(Image * image,
   3537   const ImageInfo *image_info,const PSDInfo *psd_info,ExceptionInfo *exception)
   3538 {
   3539   PolicyDomain
   3540     domain;
   3541 
   3542   PolicyRights
   3543     rights;
   3544 
   3545   domain=CoderPolicyDomain;
   3546   rights=WritePolicyRights;
   3547   if (IsRightsAuthorized(domain,rights,"PSD") == MagickFalse)
   3548     return(MagickTrue);
   3549   return WritePSDLayersInternal(image,image_info,psd_info,(size_t*) NULL,
   3550     exception);
   3551 }
   3552 
   3553 static MagickBooleanType WritePSDImage(const ImageInfo *image_info,
   3554   Image *image,ExceptionInfo *exception)
   3555 {
   3556   const StringInfo
   3557     *icc_profile;
   3558 
   3559   MagickBooleanType
   3560     status;
   3561 
   3562   PSDInfo
   3563     psd_info;
   3564 
   3565   register ssize_t
   3566     i;
   3567 
   3568   size_t
   3569     length,
   3570     num_channels,
   3571     packet_size;
   3572 
   3573   StringInfo
   3574     *bim_profile;
   3575 
   3576   /*
   3577     Open image file.
   3578   */
   3579   assert(image_info != (const ImageInfo *) NULL);
   3580   assert(image_info->signature == MagickCoreSignature);
   3581   assert(image != (Image *) NULL);
   3582   assert(image->signature == MagickCoreSignature);
   3583   if (image->debug != MagickFalse)
   3584     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   3585   assert(exception != (ExceptionInfo *) NULL);
   3586   assert(exception->signature == MagickCoreSignature);
   3587   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   3588   if (status == MagickFalse)
   3589     return(status);
   3590   packet_size=(size_t) (image->depth > 8 ? 6 : 3);
   3591   if (image->alpha_trait != UndefinedPixelTrait)
   3592     packet_size+=image->depth > 8 ? 2 : 1;
   3593   psd_info.version=1;
   3594   if ((LocaleCompare(image_info->magick,"PSB") == 0) ||
   3595       (image->columns > 30000) || (image->rows > 30000))
   3596     psd_info.version=2;
   3597   (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
   3598   (void) WriteBlobMSBShort(image,psd_info.version);  /* version */
   3599   for (i=1; i <= 6; i++)
   3600     (void) WriteBlobByte(image, 0);  /* 6 bytes of reserved */
   3601   /* When the image has a color profile it won't be converted to gray scale */
   3602   if ((GetImageProfile(image,"icc") == (StringInfo *) NULL) &&
   3603       (SetImageGray(image,exception) != MagickFalse))
   3604     num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
   3605   else
   3606     if ((image_info->type != TrueColorType) && (image_info->type !=
   3607          TrueColorAlphaType) && (image->storage_class == PseudoClass))
   3608       num_channels=(image->alpha_trait != UndefinedPixelTrait ? 2UL : 1UL);
   3609     else
   3610       {
   3611         if (image->storage_class == PseudoClass)
   3612           (void) SetImageStorageClass(image,DirectClass,exception);
   3613         if (image->colorspace != CMYKColorspace)
   3614           num_channels=(image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL);
   3615         else
   3616           num_channels=(image->alpha_trait != UndefinedPixelTrait ? 5UL : 4UL);
   3617       }
   3618   (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
   3619   (void) WriteBlobMSBLong(image,(unsigned int) image->rows);
   3620   (void) WriteBlobMSBLong(image,(unsigned int) image->columns);
   3621   if (IsImageGray(image) != MagickFalse)
   3622     {
   3623       MagickBooleanType
   3624         monochrome;
   3625 
   3626       /*
   3627         Write depth & mode.
   3628       */
   3629       monochrome=IsImageMonochrome(image) && (image->depth == 1) ?
   3630         MagickTrue : MagickFalse;
   3631       (void) WriteBlobMSBShort(image,(unsigned short)
   3632         (monochrome != MagickFalse ? 1 : image->depth > 8 ? 16 : 8));
   3633       (void) WriteBlobMSBShort(image,(unsigned short)
   3634         (monochrome != MagickFalse ? BitmapMode : GrayscaleMode));
   3635     }
   3636   else
   3637     {
   3638       (void) WriteBlobMSBShort(image,(unsigned short) (image->storage_class ==
   3639         PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
   3640 
   3641       if (((image_info->colorspace != UndefinedColorspace) ||
   3642            (image->colorspace != CMYKColorspace)) &&
   3643           (image_info->colorspace != CMYKColorspace))
   3644         {
   3645           (void) TransformImageColorspace(image,sRGBColorspace,exception);
   3646           (void) WriteBlobMSBShort(image,(unsigned short)
   3647             (image->storage_class == PseudoClass ? IndexedMode : RGBMode));
   3648         }
   3649       else
   3650         {
   3651           if (image->colorspace != CMYKColorspace)
   3652             (void) TransformImageColorspace(image,CMYKColorspace,exception);
   3653           (void) WriteBlobMSBShort(image,CMYKMode);
   3654         }
   3655     }
   3656   if ((IsImageGray(image) != MagickFalse) ||
   3657       (image->storage_class == DirectClass) || (image->colors > 256))
   3658     (void) WriteBlobMSBLong(image,0);
   3659   else
   3660     {
   3661       /*
   3662         Write PSD raster colormap.
   3663       */
   3664       (void) WriteBlobMSBLong(image,768);
   3665       for (i=0; i < (ssize_t) image->colors; i++)
   3666         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
   3667           image->colormap[i].red)));
   3668       for ( ; i < 256; i++)
   3669         (void) WriteBlobByte(image,0);
   3670       for (i=0; i < (ssize_t) image->colors; i++)
   3671         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
   3672           image->colormap[i].green)));
   3673       for ( ; i < 256; i++)
   3674         (void) WriteBlobByte(image,0);
   3675       for (i=0; i < (ssize_t) image->colors; i++)
   3676         (void) WriteBlobByte(image,ScaleQuantumToChar(ClampToQuantum(
   3677           image->colormap[i].blue)));
   3678       for ( ; i < 256; i++)
   3679         (void) WriteBlobByte(image,0);
   3680     }
   3681   /*
   3682     Image resource block.
   3683   */
   3684   length=28; /* 0x03EB */
   3685   bim_profile=(StringInfo *) GetImageProfile(image,"8bim");
   3686   icc_profile=GetImageProfile(image,"icc");
   3687   if (bim_profile != (StringInfo *) NULL)
   3688     {
   3689       bim_profile=CloneStringInfo(bim_profile);
   3690       if (icc_profile != (StringInfo *) NULL)
   3691         RemoveICCProfileFromResourceBlock(bim_profile);
   3692       RemoveResolutionFromResourceBlock(bim_profile);
   3693       length+=PSDQuantum(GetStringInfoLength(bim_profile));
   3694     }
   3695   if (icc_profile != (const StringInfo *) NULL)
   3696     length+=PSDQuantum(GetStringInfoLength(icc_profile))+12;
   3697   (void) WriteBlobMSBLong(image,(unsigned int) length);
   3698   WriteResolutionResourceBlock(image);
   3699   if (bim_profile != (StringInfo *) NULL)
   3700     {
   3701       (void) WriteBlob(image,GetStringInfoLength(bim_profile),
   3702         GetStringInfoDatum(bim_profile));
   3703       bim_profile=DestroyStringInfo(bim_profile);
   3704     }
   3705   if (icc_profile != (StringInfo *) NULL)
   3706     {
   3707       (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
   3708       (void) WriteBlobMSBShort(image,0x0000040F);
   3709       (void) WriteBlobMSBShort(image,0);
   3710       (void) WriteBlobMSBLong(image,(unsigned int) GetStringInfoLength(
   3711         icc_profile));
   3712       (void) WriteBlob(image,GetStringInfoLength(icc_profile),
   3713         GetStringInfoDatum(icc_profile));
   3714       if ((ssize_t) GetStringInfoLength(icc_profile) != PSDQuantum(GetStringInfoLength(icc_profile)))
   3715         (void) WriteBlobByte(image,0);
   3716     }
   3717   if (status != MagickFalse)
   3718     {
   3719       MagickOffsetType
   3720         size_offset;
   3721 
   3722       size_t
   3723         size;
   3724 
   3725       size_offset=TellBlob(image);
   3726       (void) SetPSDSize(&psd_info,image,0);
   3727       status=WritePSDLayersInternal(image,image_info,&psd_info,&size,
   3728         exception);
   3729       size_offset+=WritePSDSize(&psd_info,image,size+
   3730         (psd_info.version == 1 ? 8 : 12),size_offset);
   3731     }
   3732   (void) WriteBlobMSBLong(image,0);  /* user mask data */
   3733   /*
   3734     Write composite image.
   3735   */
   3736   if (status != MagickFalse)
   3737     {
   3738       CompressionType
   3739         compression;
   3740 
   3741       compression=image->compression;
   3742       if (image->compression == ZipCompression)
   3743         image->compression=RLECompression;
   3744       if (image_info->compression != UndefinedCompression)
   3745         image->compression=image_info->compression;
   3746       if (WritePSDChannels(&psd_info,image_info,image,image,0,MagickFalse,
   3747           exception) == 0)
   3748         status=MagickFalse;
   3749       image->compression=compression;
   3750     }
   3751   (void) CloseBlob(image);
   3752   return(status);
   3753 }
   3754