]> granicus.if.org Git - imagemagick/blobdiff - coders/pict.c
(no commit message)
[imagemagick] / coders / pict.c
index 0a6deeac0d39abca90f96eb6e1194bde1045a3d1..d8b953648612c611bb94f39d8a2b7e863831cdbb 100644 (file)
 %               Read/Write Apple Macintosh QuickDraw/PICT Format              %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
     ThrowReaderException(CorruptImageError,"ImproperImageHeader"); \
 }
 
-#define ReadRectangle(image,rectangle) \
-{ \
-  rectangle.top=(short) ReadBlobMSBShort(image); \
-  rectangle.left=(short) ReadBlobMSBShort(image); \
-  rectangle.bottom=(short) ReadBlobMSBShort(image); \
-  rectangle.right=(short) ReadBlobMSBShort(image); \
-  if ((rectangle.left > rectangle.right) || \
-      (rectangle.top > rectangle.bottom)) \
-    ThrowReaderException(CorruptImageError,"ImproperImageHeader"); \
-}
-
 typedef struct _PICTCode
 {
   const char
@@ -427,7 +416,8 @@ static unsigned char *ExpandBuffer(unsigned char *pixels,
 }
 
 static unsigned char *DecodeImage(Image *blob,Image *image,
-  size_t bytes_per_line,const unsigned int bits_per_pixel,size_t *extent)
+  size_t bytes_per_line,const unsigned int bits_per_pixel,size_t *extent,
+  ExceptionInfo *exception)
 {
   MagickSizeType
     number_pixels;
@@ -469,7 +459,7 @@ static unsigned char *DecodeImage(Image *blob,Image *image,
     }
   else
     if (bits_per_pixel == 32)
-      width*=image->matte ? 4 : 3;
+      width*=image->alpha_trait ? 4 : 3;
   if (bytes_per_line == 0)
     bytes_per_line=width;
   row_bytes=(size_t) (image->columns | 0x8000);
@@ -501,7 +491,7 @@ static unsigned char *DecodeImage(Image *blob,Image *image,
         p=ExpandBuffer(scanline,&number_pixels,bits_per_pixel);
         if ((q+number_pixels) > (pixels+(*extent)))
           {
-            (void) ThrowMagickException(&image->exception,GetMagickModule(),
+            (void) ThrowMagickException(exception,GetMagickModule(),
               CorruptImageError,"UnableToUncompressImage","`%s'",
               image->filename);
             break;
@@ -523,7 +513,7 @@ static unsigned char *DecodeImage(Image *blob,Image *image,
       scanline_length=1UL*ReadBlobByte(blob);
     if (scanline_length >= row_bytes)
       {
-        (void) ThrowMagickException(&image->exception,GetMagickModule(),
+        (void) ThrowMagickException(exception,GetMagickModule(),
           CorruptImageError,"UnableToUncompressImage","`%s'",image->filename);
         break;
       }
@@ -744,6 +734,13 @@ static size_t EncodeImage(Image *image,const unsigned char *scanline,
 */
 static MagickBooleanType IsPICT(const unsigned char *magick,const size_t length)
 {
+  if (length < 12)
+    return(MagickFalse);
+  /*
+    Embedded OLE2 macintosh have "PICT" instead of 512 platform header.
+  */
+  if (memcmp(magick,"PICT",4) == 0)
+    return(MagickTrue);
   if (length < 528)
     return(MagickFalse);
   if (memcmp(magick+522,"\000\021\002\377\014\000",6) == 0)
@@ -788,11 +785,24 @@ static inline size_t MagickMax(const size_t x,
   return(y);
 }
 
+static MagickBooleanType ReadRectangle(Image *image,PICTRectangle *rectangle)
+{
+  rectangle->top=(short) ReadBlobMSBShort(image);
+  rectangle->left=(short) ReadBlobMSBShort(image);
+  rectangle->bottom=(short) ReadBlobMSBShort(image);
+  rectangle->right=(short) ReadBlobMSBShort(image);
+  if ((rectangle->left > rectangle->right) ||
+      (rectangle->top > rectangle->bottom))
+    return(MagickFalse);
+  return(MagickTrue);
+}
+
 static Image *ReadPICTImage(const ImageInfo *image_info,
   ExceptionInfo *exception)
 {
   char
-    geometry[MaxTextExtent];
+    geometry[MaxTextExtent],
+    header_ole[4];
 
   Image
     *image;
@@ -845,8 +855,7 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
       image_info->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
-  image=AcquireImage(image_info);
-  image->depth=8;
+  image=AcquireImage(image_info,exception);
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
     {
@@ -858,10 +867,20 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
   */
   pixmap.bits_per_pixel=0;
   pixmap.component_count=0;
-  for (i=0; i < 512; i++)
-    (void) ReadBlobByte(image);  /* skip header */
+  /*
+    Skip header : 512 for standard PICT and 4, ie "PICT" for OLE2.
+  */
+  header_ole[0]=ReadBlobByte(image);
+  header_ole[1]=ReadBlobByte(image);
+  header_ole[2]=ReadBlobByte(image);
+  header_ole[3]=ReadBlobByte(image);
+  if (!((header_ole[0] == 0x50) && (header_ole[1] == 0x49) &&
+      (header_ole[2] == 0x43) && (header_ole[3] == 0x54 )))
+    for (i=0; i < 508; i++)
+      (void) ReadBlobByte(image);
   (void) ReadBlobMSBShort(image);  /* skip picture size */
-  ReadRectangle(image,frame);
+  if (ReadRectangle(image,&frame) == MagickFalse)
+    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   while ((c=ReadBlobByte(image)) == 0) ;
   if (c != 0x11)
     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
@@ -883,10 +902,11 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
     Create black canvas.
   */
   flags=0;
+  image->depth=8;
   image->columns=1UL*(frame.right-frame.left);
   image->rows=1UL*(frame.bottom-frame.top);
-  image->x_resolution=DefaultResolution;
-  image->y_resolution=DefaultResolution;
+  image->resolution.x=DefaultResolution;
+  image->resolution.y=DefaultResolution;
   image->units=UndefinedResolution;
   /*
     Interpret PICT opcodes.
@@ -901,6 +921,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
       code=ReadBlobByte(image);
     if (version == 2)
       code=(int) ReadBlobMSBShort(image);
+    if (code < 0)
+      break;
     if (code > 0xa1)
       {
         if (image->debug != MagickFalse)
@@ -925,12 +947,13 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                   (void) ReadBlobByte(image);
                 break;
               }
-            ReadRectangle(image,frame);
+            if (ReadRectangle(image,&frame) == MagickFalse)
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
             if (((frame.left & 0x8000) != 0) || ((frame.top & 0x8000) != 0))
               break;
             image->columns=1UL*(frame.right-frame.left);
             image->rows=1UL*(frame.bottom-frame.top);
-            (void) SetImageBackgroundColor(image);
+            (void) SetImageBackgroundColor(image,exception);
             break;
           }
           case 0x12:
@@ -959,11 +982,12 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             if (pattern != 1)
               ThrowReaderException(CorruptImageError,"UnknownPatternType");
             length=ReadBlobMSBShort(image);
-            ReadRectangle(image,frame);
+            if (ReadRectangle(image,&frame) == MagickFalse)
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
             ReadPixmap(pixmap);
             image->depth=1UL*pixmap.component_size;
-            image->x_resolution=1.0*pixmap.horizontal_resolution;
-            image->y_resolution=1.0*pixmap.vertical_resolution;
+            image->resolution.x=1.0*pixmap.horizontal_resolution;
+            image->resolution.y=1.0*pixmap.vertical_resolution;
             image->units=PixelsPerInchResolution;
             (void) ReadBlobMSBLong(image);
             flags=1L*ReadBlobMSBShort(image);
@@ -1061,7 +1085,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                 (void) ReadBlobMSBShort(image);
                 (void) ReadBlobMSBShort(image);
               }
-            ReadRectangle(image,frame);
+            if (ReadRectangle(image,&frame) == MagickFalse)
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
             /*
               Initialize tile image.
             */
@@ -1074,13 +1099,13 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
               {
                 ReadPixmap(pixmap);
                 tile_image->depth=1UL*pixmap.component_size;
-                tile_image->matte=pixmap.component_count == 4 ?
-                  MagickTrue : MagickFalse;
-                tile_image->x_resolution=(double) pixmap.horizontal_resolution;
-                tile_image->y_resolution=(double) pixmap.vertical_resolution;
+                tile_image->alpha_trait=pixmap.component_count == 4 ?
+                  BlendPixelTrait : UndefinedPixelTrait;
+                tile_image->resolution.x=(double) pixmap.horizontal_resolution;
+                tile_image->resolution.y=(double) pixmap.vertical_resolution;
                 tile_image->units=PixelsPerInchResolution;
-                if (tile_image->matte != MagickFalse)
-                  image->matte=tile_image->matte;
+                if (tile_image->alpha_trait == BlendPixelTrait)
+                  image->alpha_trait=tile_image->alpha_trait;
               }
             if ((code != 0x9a) && (code != 0x9b))
               {
@@ -1094,7 +1119,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                     flags=1L*ReadBlobMSBShort(image);
                     tile_image->colors=1UL*ReadBlobMSBShort(image)+1;
                   }
-                status=AcquireImageColormap(tile_image,tile_image->colors);
+                status=AcquireImageColormap(tile_image,tile_image->colors,
+                  exception);
                 if (status == MagickFalse)
                   {
                     tile_image=DestroyImage(tile_image);
@@ -1129,8 +1155,10 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                     }
                   }
               }
-            ReadRectangle(image,source);
-            ReadRectangle(image,destination);
+            if (ReadRectangle(image,&source) == MagickFalse)
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+            if (ReadRectangle(image,&destination) == MagickFalse)
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
             (void) ReadBlobMSBShort(image);
             if ((code == 0x91) || (code == 0x99) || (code == 0x9b))
               {
@@ -1143,10 +1171,11 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
               }
             if ((code != 0x9a) && (code != 0x9b) &&
                 (bytes_per_line & 0x8000) == 0)
-              pixels=DecodeImage(image,tile_image,1UL*bytes_per_line,1,&extent);
+              pixels=DecodeImage(image,tile_image,1UL*bytes_per_line,1,&extent,
+                exception);
             else
               pixels=DecodeImage(image,tile_image,1UL*bytes_per_line,1U*
-                pixmap.bits_per_pixel,&extent);
+                pixmap.bits_per_pixel,&extent,exception);
             if (pixels == (unsigned char *) NULL)
               {
                 tile_image=DestroyImage(tile_image);
@@ -1163,13 +1192,13 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                 ThrowReaderException(CorruptImageError,"NotEnoughPixelData");
               q=QueueAuthenticPixels(tile_image,0,y,tile_image->columns,1,
                 exception);
-              if (q == (const Quantum *) NULL)
+              if (q == (Quantum *) NULL)
                 break;
               for (x=0; x < (ssize_t) tile_image->columns; x++)
               {
                 if (tile_image->storage_class == PseudoClass)
                   {
-                    index=ConstrainColormapIndex(tile_image,*p);
+                    index=ConstrainColormapIndex(tile_image,*p,exception);
                     SetPixelIndex(tile_image,index,q);
                     SetPixelRed(tile_image,
                       tile_image->colormap[(ssize_t) index].red,q);
@@ -1193,7 +1222,7 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                           (unsigned char) ((j & 0x1f) << 3)),q);
                       }
                     else
-                      if (tile_image->matte == MagickFalse)
+                      if (tile_image->alpha_trait != BlendPixelTrait)
                         {
                           if (p > (pixels+extent+2*image->columns))
                             ThrowReaderException(CorruptImageError,
@@ -1238,8 +1267,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             if (jpeg == MagickFalse)
               if ((code == 0x9a) || (code == 0x9b) ||
                   ((bytes_per_line & 0x8000) != 0))
-                (void) CompositeImage(image,CopyCompositeOp,tile_image,
-                  destination.left,destination.top);
+                (void) CompositeImage(image,tile_image,CopyCompositeOp,
+                  MagickTrue,destination.left,destination.top,exception);
             tile_image=DestroyImage(tile_image);
             break;
           }
@@ -1273,9 +1302,9 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
               {
                 if (length == 0)
                   break;
-                profile=AcquireStringInfo(length);
+                profile=BlobToStringInfo((const void *) NULL,length);
                 SetStringInfoDatum(profile,info);
-                status=SetImageProfile(image,"icc",profile);
+                status=SetImageProfile(image,"icc",profile,exception);
                 profile=DestroyStringInfo(profile);
                 if (status == MagickFalse)
                   ThrowReaderException(ResourceLimitError,
@@ -1286,9 +1315,9 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
               {
                 if (length == 0)
                   break;
-                profile=AcquireStringInfo(length);
+                profile=BlobToStringInfo((const void *) NULL,length);
                 SetStringInfoDatum(profile,info);
-                status=SetImageProfile(image,"iptc",profile);
+                status=SetImageProfile(image,"iptc",profile,exception);
                 if (status == MagickFalse)
                   ThrowReaderException(ResourceLimitError,
                     "MemoryAllocationFailed");
@@ -1306,6 +1335,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             /*
               Skip to next op code.
             */
+            if (code < 0)
+              break;
             if (codes[code].length == -1)
               (void) ReadBlobMSBShort(image);
             else
@@ -1352,6 +1383,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
           file=fdopen(unique_file,"wb");
         if ((unique_file == -1) || (file == (FILE *) NULL))
           {
+            if (file != (FILE *) NULL)
+              (void) fclose(file);
             (void) CopyMagickString(image->filename,read_info->filename,
               MaxTextExtent);
             ThrowFileException(exception,FileOpenError,
@@ -1362,7 +1395,11 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
         length=ReadBlobMSBLong(image);
         for (i=0; i < 6; i++)
           (void) ReadBlobMSBLong(image);
-        ReadRectangle(image,frame);
+        if (ReadRectangle(image,&frame) == MagickFalse)
+          {
+            (void) fclose(file);
+            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+          }
         for (i=0; i < 122; i++)
           (void) ReadBlobByte(image);
         for (i=0; i < (ssize_t) (length-154); i++)
@@ -1371,6 +1408,7 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
           (void) fputc(c,file);
         }
         (void) fclose(file);
+        (void) close(unique_file);
         tile_image=ReadImage(read_info,exception);
         (void) RelinquishUniqueFileResource(read_info->filename);
         read_info=DestroyImageInfo(read_info);
@@ -1382,10 +1420,9 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
         (void) SetImageExtent(image,
           MagickMax(image->columns,tile_image->columns),
           MagickMax(image->rows,tile_image->rows),exception);
-        if (IsRGBColorspace(image->colorspace) == MagickFalse)
-          (void) TransformImageColorspace(image,tile_image->colorspace);
-        (void) CompositeImage(image,CopyCompositeOp,tile_image,frame.left,
-          frame.right);
+        (void) TransformImageColorspace(image,tile_image->colorspace,exception);
+        (void) CompositeImage(image,tile_image,CopyCompositeOp,MagickTrue,
+          frame.left,frame.right,exception);
         image->compression=tile_image->compression;
         tile_image=DestroyImage(tile_image);
         continue;
@@ -1599,8 +1636,7 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   if (status == MagickFalse)
     return(status);
-  if (IsRGBColorspace(image->colorspace) == MagickFalse)
-    (void) TransformImageColorspace(image,RGBColorspace);
+  (void) TransformImageColorspace(image,sRGBColorspace,exception);
   /*
     Initialize image info.
   */
@@ -1629,16 +1665,16 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
   pixmap.table=0;
   pixmap.reserved=0;
   transfer_mode=0;
-  x_resolution=image->x_resolution != 0.0 ? image->x_resolution :
+  x_resolution=image->resolution.x != 0.0 ? image->resolution.x :
     DefaultResolution;
-  y_resolution=image->y_resolution != 0.0 ? image->y_resolution :
+  y_resolution=image->resolution.y != 0.0 ? image->resolution.y :
     DefaultResolution;
   storage_class=image->storage_class;
   if (image_info->compression == JPEGCompression)
     storage_class=DirectClass;
-  if ((storage_class == DirectClass) || (image->matte != MagickFalse))
+  if (storage_class == DirectClass)
     {
-      pixmap.component_count=image->matte ? 4 : 3;
+      pixmap.component_count=image->alpha_trait == BlendPixelTrait ? 4 : 3;
       pixmap.pixel_type=16;
       pixmap.bits_per_pixel=32;
       pixmap.pack_type=0x04;
@@ -1649,8 +1685,8 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
     Allocate memory.
   */
   bytes_per_line=image->columns;
-  if ((storage_class == DirectClass) || (image->matte != MagickFalse))
-    bytes_per_line*=image->matte ? 4 : 3;
+  if (storage_class == DirectClass)
+    bytes_per_line*=image->alpha_trait == BlendPixelTrait ? 4 : 3;
   buffer=(unsigned char *) AcquireQuantumMemory(PictInfoSize,sizeof(*buffer));
   packed_scanline=(unsigned char *) AcquireQuantumMemory((size_t)
    (row_bytes+MaxCount),sizeof(*packed_scanline));
@@ -1873,7 +1909,7 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
     Write picture data.
   */
   count=0;
-  if ((storage_class == PseudoClass) && (image->matte == MagickFalse))
+  if (storage_class == PseudoClass)
     for (y=0; y < (ssize_t) image->rows; y++)
     {
       p=GetVirtualPixels(image,0,y,image->columns,1,exception);
@@ -1922,7 +1958,7 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
           red=scanline;
           green=scanline+image->columns;
           blue=scanline+2*image->columns;
-          if (image->matte != MagickFalse)
+          if (image->alpha_trait == BlendPixelTrait)
             {
               opacity=scanline;
               red=scanline+image->columns;
@@ -1934,7 +1970,7 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
             *red++=ScaleQuantumToChar(GetPixelRed(image,p));
             *green++=ScaleQuantumToChar(GetPixelGreen(image,p));
             *blue++=ScaleQuantumToChar(GetPixelBlue(image,p));
-            if (image->matte != MagickFalse)
+            if (image->alpha_trait == BlendPixelTrait)
               *opacity++=ScaleQuantumToChar((Quantum) (GetPixelAlpha(image,p)));
             p+=GetPixelChannels(image);
           }