]> granicus.if.org Git - imagemagick/blobdiff - coders/pict.c
https://github.com/ImageMagick/ImageMagick/issues/659
[imagemagick] / coders / pict.c
index 8276928462fd6be8b2ac66a4b82c11707b4e8a99..fc2314b1336d4d92f9fd02a15a0c8d5a86266a23 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-2017 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  %
 %  obtain a copy of the License at                                            %
 %                                                                             %
-%    http://www.imagemagick.org/script/license.php                            %
+%    https://www.imagemagick.org/script/license.php                           %
 %                                                                             %
 %  Unless required by applicable law or agreed to in writing, software        %
 %  distributed under the License is distributed on an "AS IS" BASIS,          %
 /*
   ImageMagick Macintosh PICT Methods.
 */
-#define ReadPixmap(pixmap) \
-{ \
-  pixmap.version=(short) ReadBlobMSBShort(image); \
-  pixmap.pack_type=(short) ReadBlobMSBShort(image); \
-  pixmap.pack_size=ReadBlobMSBLong(image); \
-  pixmap.horizontal_resolution=1UL*ReadBlobMSBShort(image); \
-  (void) ReadBlobMSBShort(image); \
-  pixmap.vertical_resolution=1UL*ReadBlobMSBShort(image); \
-  (void) ReadBlobMSBShort(image); \
-  pixmap.pixel_type=(short) ReadBlobMSBShort(image); \
-  pixmap.bits_per_pixel=(short) ReadBlobMSBShort(image); \
-  pixmap.component_count=(short) ReadBlobMSBShort(image); \
-  pixmap.component_size=(short) ReadBlobMSBShort(image); \
-  pixmap.plane_bytes=ReadBlobMSBLong(image); \
-  pixmap.table=ReadBlobMSBLong(image); \
-  pixmap.reserved=ReadBlobMSBLong(image); \
-  if ((pixmap.bits_per_pixel <= 0) || (pixmap.bits_per_pixel > 32) || \
-      (pixmap.component_count <= 0) || (pixmap.component_count > 4) || \
-      (pixmap.component_size <= 0)) \
-    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
@@ -470,7 +437,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);
@@ -485,7 +452,8 @@ static unsigned char *DecodeImage(Image *blob,Image *image,
     return((unsigned char *) NULL);
   *extent=row_bytes*image->rows*sizeof(*pixels);
   (void) ResetMagickMemory(pixels,0,*extent);
-  scanline=(unsigned char *) AcquireQuantumMemory(row_bytes,sizeof(*scanline));
+  scanline=(unsigned char *) AcquireQuantumMemory(row_bytes,2*
+    sizeof(*scanline));
   if (scanline == (unsigned char *) NULL)
     return((unsigned char *) NULL);
   if (bytes_per_line < 8)
@@ -498,7 +466,13 @@ static unsigned char *DecodeImage(Image *blob,Image *image,
         q=pixels+y*width*GetPixelChannels(image);;
         number_pixels=bytes_per_line;
         count=ReadBlob(blob,(size_t) number_pixels,scanline);
-        (void) count;
+        if (count != (ssize_t) number_pixels)
+          {
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              CorruptImageError,"UnableToUncompressImage","`%s'",
+              image->filename);
+            break;
+          }
         p=ExpandBuffer(scanline,&number_pixels,bits_per_pixel);
         if ((q+number_pixels) > (pixels+(*extent)))
           {
@@ -529,6 +503,12 @@ static unsigned char *DecodeImage(Image *blob,Image *image,
         break;
       }
     count=ReadBlob(blob,scanline_length,scanline);
+    if (count != (ssize_t) scanline_length)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          CorruptImageError,"UnableToUncompressImage","`%s'",image->filename);
+        break;
+      }
     for (j=0; j < (ssize_t) scanline_length; )
       if ((scanline[j] & 0x80) == 0)
         {
@@ -619,7 +599,7 @@ static size_t EncodeImage(Image *image,const unsigned char *scanline,
     Pack scanline.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(scanline != (unsigned char *) NULL);
@@ -745,6 +725,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)
@@ -781,19 +768,47 @@ static MagickBooleanType IsPICT(const unsigned char *magick,const size_t length)
 %
 */
 
-static inline size_t MagickMax(const size_t x,
-  const size_t y)
+static MagickBooleanType ReadPixmap(Image *image,PICTPixmap *pixmap)
+{
+  pixmap->version=(short) ReadBlobMSBShort(image);
+  pixmap->pack_type=(short) ReadBlobMSBShort(image);
+  pixmap->pack_size=ReadBlobMSBLong(image);
+  pixmap->horizontal_resolution=1UL*ReadBlobMSBShort(image);
+  (void) ReadBlobMSBShort(image);
+  pixmap->vertical_resolution=1UL*ReadBlobMSBShort(image);
+  (void) ReadBlobMSBShort(image);
+  pixmap->pixel_type=(short) ReadBlobMSBShort(image);
+  pixmap->bits_per_pixel=(short) ReadBlobMSBShort(image);
+  pixmap->component_count=(short) ReadBlobMSBShort(image);
+  pixmap->component_size=(short) ReadBlobMSBShort(image);
+  pixmap->plane_bytes=ReadBlobMSBLong(image);
+  pixmap->table=ReadBlobMSBLong(image);
+  pixmap->reserved=ReadBlobMSBLong(image);
+  if ((EOFBlob(image) != MagickFalse) || (pixmap->bits_per_pixel <= 0) ||
+      (pixmap->bits_per_pixel > 32) || (pixmap->component_count <= 0) ||
+      (pixmap->component_count > 4) || (pixmap->component_size <= 0))
+    return(MagickFalse);
+  return(MagickTrue);
+}
+
+static MagickBooleanType ReadRectangle(Image *image,PICTRectangle *rectangle)
 {
-  if (x > y)
-    return(x);
-  return(y);
+  rectangle->top=(short) ReadBlobMSBShort(image);
+  rectangle->left=(short) ReadBlobMSBShort(image);
+  rectangle->bottom=(short) ReadBlobMSBShort(image);
+  rectangle->right=(short) ReadBlobMSBShort(image);
+  if ((EOFBlob(image) != MagickFalse) || (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[MagickPathExtent],
+    header_ole[4];
 
   Image
     *image;
@@ -840,14 +855,13 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
     Open image file.
   */
   assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
+  assert(image_info->signature == MagickCoreSignature);
   if (image_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       image_info->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   image=AcquireImage(image_info,exception);
-  image->depth=8;
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
     {
@@ -859,10 +873,21 @@ 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++)
+      if (ReadBlobByte(image) == EOF)
+        break;
   (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");
@@ -884,11 +909,21 @@ 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->resolution.x=DefaultResolution;
   image->resolution.y=DefaultResolution;
   image->units=UndefinedResolution;
+  if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
+    if (image->scene >= (image_info->scene+image_info->number_scenes-1))
+      {
+        (void) CloseBlob(image);
+        return(GetFirstImageInList(image));
+      }
+  status=SetImageExtent(image,image->columns,image->rows,exception);
+  if (status == MagickFalse)
+    return(DestroyImageList(image));
   /*
     Interpret PICT opcodes.
   */
@@ -901,7 +936,9 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
     if ((version == 1) || ((TellBlob(image) % 2) != 0))
       code=ReadBlobByte(image);
     if (version == 2)
-      code=(int) ReadBlobMSBShort(image);
+      code=ReadBlobMSBSignedShort(image);
+    if (code < 0)
+      break;
     if (code > 0xa1)
       {
         if (image->debug != MagickFalse)
@@ -923,14 +960,19 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             if (length != 0x000a)
               {
                 for (i=0; i < (ssize_t) (length-2); i++)
-                  (void) ReadBlobByte(image);
+                  if (ReadBlobByte(image) == EOF)
+                    break;
                 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);
+            status=SetImageExtent(image,image->columns,image->rows,exception);
+            if (status == MagickFalse)
+              return(DestroyImageList(image));
             (void) SetImageBackgroundColor(image,exception);
             break;
           }
@@ -950,18 +992,22 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             */
             pattern=1L*ReadBlobMSBShort(image);
             for (i=0; i < 8; i++)
-              (void) ReadBlobByte(image);
+              if (ReadBlobByte(image) == EOF)
+                break;
             if (pattern == 2)
               {
                 for (i=0; i < 5; i++)
-                  (void) ReadBlobByte(image);
+                  if (ReadBlobByte(image) == EOF)
+                    break;
                 break;
               }
             if (pattern != 1)
               ThrowReaderException(CorruptImageError,"UnknownPatternType");
             length=ReadBlobMSBShort(image);
-            ReadRectangle(image,frame);
-            ReadPixmap(pixmap);
+            if (ReadRectangle(image,&frame) == MagickFalse)
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+            if (ReadPixmap(image,&pixmap) == MagickFalse)
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
             image->depth=1UL*pixmap.component_size;
             image->resolution.x=1.0*pixmap.horizontal_resolution;
             image->resolution.y=1.0*pixmap.vertical_resolution;
@@ -982,16 +1028,21 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             if (length < 8)
               {
                 for (i=0; i < (ssize_t) (length*height); i++)
-                  (void) ReadBlobByte(image);
+                  if (ReadBlobByte(image) == EOF)
+                    break;
               }
             else
               for (j=0; j < (int) height; j++)
                 if (length > 200)
-                  for (j=0; j < (ssize_t) ReadBlobMSBShort(image); j++)
-                    (void) ReadBlobByte(image);
+                  {
+                    for (j=0; j < (ssize_t) ReadBlobMSBShort(image); j++)
+                      if (ReadBlobByte(image) == EOF)
+                        break;
+                  }
                 else
                   for (j=0; j < (ssize_t) ReadBlobByte(image); j++)
-                    (void) ReadBlobByte(image);
+                    if (ReadBlobByte(image) == EOF)
+                      break;
             break;
           }
           case 0x1b:
@@ -1021,7 +1072,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             */
             length=ReadBlobMSBShort(image);
             for (i=0; i < (ssize_t) (length-2); i++)
-              (void) ReadBlobByte(image);
+              if (ReadBlobByte(image) == EOF)
+                break;
             break;
           }
           case 0x90:
@@ -1062,7 +1114,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.
             */
@@ -1073,15 +1126,20 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             if ((code == 0x9a) || (code == 0x9b) ||
                 ((bytes_per_line & 0x8000) != 0))
               {
-                ReadPixmap(pixmap);
+                if (ReadPixmap(image,&pixmap) == MagickFalse)
+                  {
+                    tile_image=DestroyImage(tile_image);
+                    ThrowReaderException(CorruptImageError,
+                      "ImproperImageHeader");
+                  }
                 tile_image->depth=1UL*pixmap.component_size;
-                tile_image->matte=pixmap.component_count == 4 ?
-                  MagickTrue : MagickFalse;
+                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 != UndefinedPixelTrait)
+                  image->alpha_trait=tile_image->alpha_trait;
               }
             if ((code != 0x9a) && (code != 0x9b))
               {
@@ -1131,8 +1189,16 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                     }
                   }
               }
-            ReadRectangle(image,source);
-            ReadRectangle(image,destination);
+            if (ReadRectangle(image,&source) == MagickFalse)
+              {
+                tile_image=DestroyImage(tile_image);
+                ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+              }
+            if (ReadRectangle(image,&destination) == MagickFalse)
+              {
+                tile_image=DestroyImage(tile_image);
+                ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+              }
             (void) ReadBlobMSBShort(image);
             if ((code == 0x91) || (code == 0x99) || (code == 0x9b))
               {
@@ -1141,7 +1207,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                 */
                 length=ReadBlobMSBShort(image);
                 for (i=0; i < (ssize_t) (length-2); i++)
-                  (void) ReadBlobByte(image);
+                  if (ReadBlobByte(image) == EOF)
+                    break;
               }
             if ((code != 0x9a) && (code != 0x9b) &&
                 (bytes_per_line & 0x8000) == 0)
@@ -1163,7 +1230,10 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             for (y=0; y < (ssize_t) tile_image->rows; y++)
             {
               if (p > (pixels+extent+image->columns))
-                ThrowReaderException(CorruptImageError,"NotEnoughPixelData");
+                {
+                  tile_image=DestroyImage(tile_image);
+                  ThrowReaderException(CorruptImageError,"NotEnoughPixelData");
+                }
               q=QueueAuthenticPixels(tile_image,0,y,tile_image->columns,1,
                 exception);
               if (q == (Quantum *) NULL)
@@ -1196,11 +1266,14 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                           (unsigned char) ((j & 0x1f) << 3)),q);
                       }
                     else
-                      if (tile_image->matte == MagickFalse)
+                      if (tile_image->alpha_trait == UndefinedPixelTrait)
                         {
                           if (p > (pixels+extent+2*image->columns))
-                            ThrowReaderException(CorruptImageError,
-                              "NotEnoughPixelData");
+                            {
+                              tile_image=DestroyImage(tile_image);
+                              ThrowReaderException(CorruptImageError,
+                                "NotEnoughPixelData");
+                            }
                           SetPixelRed(tile_image,ScaleCharToQuantum(*p),q);
                           SetPixelGreen(tile_image,ScaleCharToQuantum(
                             *(p+tile_image->columns)),q);
@@ -1210,8 +1283,11 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
                       else
                         {
                           if (p > (pixels+extent+3*image->columns))
-                            ThrowReaderException(CorruptImageError,
-                              "NotEnoughPixelData");
+                            {
+                              tile_image=DestroyImage(tile_image);
+                              ThrowReaderException(CorruptImageError,
+                                "NotEnoughPixelData");
+                            }
                           SetPixelAlpha(tile_image,ScaleCharToQuantum(*p),q);
                           SetPixelRed(tile_image,ScaleCharToQuantum(
                             *(p+tile_image->columns)),q);
@@ -1241,8 +1317,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,exception);
+                (void) CompositeImage(image,tile_image,CopyCompositeOp,
+                  MagickTrue,destination.left,destination.top,exception);
             tile_image=DestroyImage(tile_image);
             break;
           }
@@ -1269,32 +1345,35 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
             if (info == (unsigned char *) NULL)
               break;
             count=ReadBlob(image,length,info);
-            (void) count;
+            if (count != (ssize_t) length)
+              ThrowReaderException(ResourceLimitError,"UnableToReadImageData");
             switch (type)
             {
               case 0xe0:
               {
-                if (length == 0)
-                  break;
                 profile=BlobToStringInfo((const void *) NULL,length);
                 SetStringInfoDatum(profile,info);
                 status=SetImageProfile(image,"icc",profile,exception);
                 profile=DestroyStringInfo(profile);
                 if (status == MagickFalse)
-                  ThrowReaderException(ResourceLimitError,
-                    "MemoryAllocationFailed");
+                  {
+                    info=(unsigned char *) RelinquishMagickMemory(info);
+                    ThrowReaderException(ResourceLimitError,
+                      "MemoryAllocationFailed");
+                  }
                 break;
               }
               case 0x1f2:
               {
-                if (length == 0)
-                  break;
                 profile=BlobToStringInfo((const void *) NULL,length);
                 SetStringInfoDatum(profile,info);
                 status=SetImageProfile(image,"iptc",profile,exception);
                 if (status == MagickFalse)
-                  ThrowReaderException(ResourceLimitError,
-                    "MemoryAllocationFailed");
+                  {
+                    info=(unsigned char *) RelinquishMagickMemory(info);
+                    ThrowReaderException(ResourceLimitError,
+                      "MemoryAllocationFailed");
+                  }
                 profile=DestroyStringInfo(profile);
                 break;
               }
@@ -1313,7 +1392,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
               (void) ReadBlobMSBShort(image);
             else
               for (i=0; i < (ssize_t) codes[code].length; i++)
-                (void) ReadBlobByte(image);
+                if (ReadBlobByte(image) == EOF)
+                  break;
           }
         }
       }
@@ -1323,7 +1403,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
           Skip header.
         */
         for (i=0; i < 24; i++)
-          (void) ReadBlobByte(image);
+          if (ReadBlobByte(image) == EOF)
+            break;
         continue;
       }
     if (((code >= 0xb0) && (code <= 0xcf)) ||
@@ -1355,41 +1436,52 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
           file=fdopen(unique_file,"wb");
         if ((unique_file == -1) || (file == (FILE *) NULL))
           {
+            (void) RelinquishUniqueFileResource(read_info->filename);
             (void) CopyMagickString(image->filename,read_info->filename,
-              MaxTextExtent);
+              MagickPathExtent);
             ThrowFileException(exception,FileOpenError,
               "UnableToCreateTemporaryFile",image->filename);
             image=DestroyImageList(image);
             return((Image *) NULL);
           }
         length=ReadBlobMSBLong(image);
-        for (i=0; i < 6; i++)
-          (void) ReadBlobMSBLong(image);
-        ReadRectangle(image,frame);
-        for (i=0; i < 122; i++)
-          (void) ReadBlobByte(image);
-        for (i=0; i < (ssize_t) (length-154); i++)
-        {
-          c=ReadBlobByte(image);
-          (void) fputc(c,file);
-        }
+        if (length > 154)
+          {
+            for (i=0; i < 6; i++)
+              (void) ReadBlobMSBLong(image);
+            if (ReadRectangle(image,&frame) == MagickFalse)
+              {
+                (void) fclose(file);
+                (void) RelinquishUniqueFileResource(read_info->filename);
+                ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+              }
+            for (i=0; i < 122; i++)
+              if (ReadBlobByte(image) == EOF)
+                break;
+            for (i=0; i < (ssize_t) (length-154); i++)
+            {
+              c=ReadBlobByte(image);
+              if (c == EOF)
+                break;
+              (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);
         if (tile_image == (Image *) NULL)
           continue;
-        (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g",
+        (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
           (double) MagickMax(image->columns,tile_image->columns),
           (double) MagickMax(image->rows,tile_image->rows));
         (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,
-            exception);
-        (void) CompositeImage(image,CopyCompositeOp,tile_image,frame.left,
-          frame.right,exception);
+        (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;
@@ -1404,7 +1496,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
         */
         length=ReadBlobMSBShort(image);
         for (i=0; i < (ssize_t) length; i++)
-          (void) ReadBlobByte(image);
+          if (ReadBlobByte(image) == EOF)
+            break;
         continue;
       }
     if ((code >= 0x100) && (code <= 0x7fff))
@@ -1414,7 +1507,8 @@ static Image *ReadPICTImage(const ImageInfo *image_info,
         */
         length=(size_t) ((code >> 7) & 0xff);
         for (i=0; i < (ssize_t) length; i++)
-          (void) ReadBlobByte(image);
+          if (ReadBlobByte(image) == EOF)
+            break;
         continue;
       }
   }
@@ -1451,23 +1545,19 @@ ModuleExport size_t RegisterPICTImage(void)
   MagickInfo
     *entry;
 
-  entry=SetMagickInfo("PCT");
+  entry=AcquireMagickInfo("PICT","PCT","Apple Macintosh QuickDraw/PICT");
   entry->decoder=(DecodeImageHandler *) ReadPICTImage;
   entry->encoder=(EncodeImageHandler *) WritePICTImage;
-  entry->adjoin=MagickFalse;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Apple Macintosh QuickDraw/PICT");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderEncoderSeekableStreamFlag;
   entry->magick=(IsImageFormatHandler *) IsPICT;
-  entry->module=ConstantString("PICT");
   (void) RegisterMagickInfo(entry);
-  entry=SetMagickInfo("PICT");
+  entry=AcquireMagickInfo("PICT","PICT","Apple Macintosh QuickDraw/PICT");
   entry->decoder=(DecodeImageHandler *) ReadPICTImage;
   entry->encoder=(EncodeImageHandler *) WritePICTImage;
-  entry->adjoin=MagickFalse;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("Apple Macintosh QuickDraw/PICT");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderEncoderSeekableStreamFlag;
   entry->magick=(IsImageFormatHandler *) IsPICT;
-  entry->module=ConstantString("PICT");
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);
 }
@@ -1572,6 +1662,7 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
   size_t
     bytes_per_line,
     count,
+    row_bytes,
     storage_class;
 
   ssize_t
@@ -1584,27 +1675,25 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
 
   unsigned short
     base_address,
-    row_bytes,
     transfer_mode;
 
   /*
     Open output image file.
   */
   assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
+  assert(image_info->signature == MagickCoreSignature);
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if ((image->columns > 65535L) || (image->rows > 65535L))
     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   if (status == MagickFalse)
     return(status);
-  if (IsRGBColorspace(image->colorspace) == MagickFalse)
-    (void) TransformImageColorspace(image,RGBColorspace,exception);
+  (void) TransformImageColorspace(image,sRGBColorspace,exception);
   /*
     Initialize image info.
   */
@@ -1617,7 +1706,7 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
   source_rectangle=size_rectangle;
   destination_rectangle=size_rectangle;
   base_address=0xff;
-  row_bytes=(unsigned short) (image->columns | 0x8000);
+  row_bytes=image->columns;
   bounds.top=0;
   bounds.left=0;
   bounds.bottom=(short) image->rows;
@@ -1640,21 +1729,21 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
   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 != UndefinedPixelTrait ? 4 : 3;
       pixmap.pixel_type=16;
       pixmap.bits_per_pixel=32;
       pixmap.pack_type=0x04;
       transfer_mode=0x40;
-      row_bytes=(unsigned short) ((4*image->columns) | 0x8000);
+      row_bytes=4*image->columns;
     }
   /*
     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 != UndefinedPixelTrait ? 4 : 3;
   buffer=(unsigned char *) AcquireQuantumMemory(PictInfoSize,sizeof(*buffer));
   packed_scanline=(unsigned char *) AcquireQuantumMemory((size_t)
    (row_bytes+MaxCount),sizeof(*packed_scanline));
@@ -1662,7 +1751,16 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
   if ((buffer == (unsigned char *) NULL) ||
       (packed_scanline == (unsigned char *) NULL) ||
       (scanline == (unsigned char *) NULL))
-    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+    {
+      if (scanline != (unsigned char *) NULL)
+        scanline=(unsigned char *) RelinquishMagickMemory(scanline);
+      if (packed_scanline != (unsigned char *) NULL)
+        packed_scanline=(unsigned char *) RelinquishMagickMemory(
+          packed_scanline);
+      if (buffer != (unsigned char *) NULL)
+        buffer=(unsigned char *) RelinquishMagickMemory(buffer);
+      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+    }
   (void) ResetMagickMemory(scanline,0,row_bytes);
   (void) ResetMagickMemory(packed_scanline,0,(size_t) (row_bytes+MaxCount));
   /*
@@ -1747,7 +1845,7 @@ static MagickBooleanType WritePICTImage(const ImageInfo *image_info,
           return(MagickFalse);
         }
       jpeg_info=CloneImageInfo(image_info);
-      (void) CopyMagickString(jpeg_info->magick,"JPEG",MaxTextExtent);
+      (void) CopyMagickString(jpeg_info->magick,"JPEG",MagickPathExtent);
       length=0;
       blob=(unsigned char *) ImageToBlob(jpeg_info,jpeg_image,&length,
         exception);
@@ -1877,7 +1975,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);
@@ -1926,7 +2024,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 != UndefinedPixelTrait)
             {
               opacity=scanline;
               red=scanline+image->columns;
@@ -1938,12 +2036,11 @@ 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 != UndefinedPixelTrait)
               *opacity++=ScaleQuantumToChar((Quantum) (GetPixelAlpha(image,p)));
             p+=GetPixelChannels(image);
           }
-          count+=EncodeImage(image,scanline,bytes_per_line & 0x7FFF,
-            packed_scanline);
+          count+=EncodeImage(image,scanline,bytes_per_line,packed_scanline);
           if (image->previous == (Image *) NULL)
             {
               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,