]> granicus.if.org Git - imagemagick/blobdiff - coders/pcx.c
Use memset() rather than ResetMagickMemory()
[imagemagick] / coders / pcx.c
index 91e0ab0a14be284896a86a0f73c8cfd42c59c48e..a8bce12458d9bd14b0912e4542ae92696662ff86 100644 (file)
 %                Read/Write ZSoft IBM PC Paintbrush Image Format              %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2018 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,          %
@@ -56,6 +56,7 @@
 #include "MagickCore/list.h"
 #include "MagickCore/magick.h"
 #include "MagickCore/memory_.h"
+#include "MagickCore/memory-private.h"
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/pixel-accessor.h"
@@ -89,7 +90,9 @@ typedef struct _PCXInfo
 
   unsigned short
     bytes_per_line,
-    palette_info;
+    palette_info,
+    horizontal_screensize,
+    vertical_screensize;
 
   unsigned char
     colormap_signature;
@@ -99,7 +102,7 @@ typedef struct _PCXInfo
   Forward declarations.
 */
 static MagickBooleanType
-  WritePCXImage(const ImageInfo *,Image *);
+  WritePCXImage(const ImageInfo *,Image *,ExceptionInfo *);
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -125,7 +128,6 @@ static MagickBooleanType
 %
 %    o length: Specifies the length of the magick string.
 %
-%
 */
 static MagickBooleanType IsDCX(const unsigned char *magick,const size_t length)
 {
@@ -160,7 +162,6 @@ static MagickBooleanType IsDCX(const unsigned char *magick,const size_t length)
 %
 %    o length: Specifies the length of the magick string.
 %
-%
 */
 static MagickBooleanType IsPCX(const unsigned char *magick,const size_t length)
 {
@@ -199,30 +200,19 @@ static MagickBooleanType IsPCX(const unsigned char *magick,const size_t length)
 %    o exception: return any errors or warnings in this structure.
 %
 */
-
-static inline ssize_t MagickAbsoluteValue(const ssize_t x)
-{
-  if (x < 0)
-    return(-x);
-  return(x);
-}
-
-static inline size_t MagickMax(const size_t x,const size_t y)
-{
-  if (x > y)
-    return(x);
-  return(y);
-}
-
-static inline size_t MagickMin(const size_t x,const size_t y)
+static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
-  if (x < y)
-    return(x);
-  return(y);
+#define ThrowPCXException(severity,tag) \
+{ \
+  if (scanline != (unsigned char *) NULL) \
+    scanline=(unsigned char *) RelinquishMagickMemory(scanline); \
+  if (pixel_info != (MemoryInfo *) NULL) \
+    pixel_info=RelinquishVirtualMemory(pixel_info); \
+  if (page_table != (MagickOffsetType *) NULL) \
+    page_table=(MagickOffsetType *) RelinquishMagickMemory(page_table); \
+  ThrowReaderException(severity,tag); \
 }
 
-static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
-{
   Image
     *image;
 
@@ -238,6 +228,9 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     offset,
     *page_table;
 
+  MemoryInfo
+    *pixel_info;
+
   PCXInfo
     pcx_info;
 
@@ -264,21 +257,21 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
   unsigned char
     packet,
-    *pcx_colormap,
-    *pcx_pixels,
+    pcx_colormap[768],
+    *pixels,
     *scanline;
 
   /*
     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);
-  image=AcquireImage(image_info);
+  assert(exception->signature == MagickCoreSignature);
+  image=AcquireImage(image_info,exception);
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
     {
@@ -289,6 +282,8 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     Determine if this a PCX file.
   */
   page_table=(MagickOffsetType *) NULL;
+  scanline=(unsigned char *) NULL;
+  pixel_info=(MemoryInfo *) NULL;
   if (LocaleCompare(image_info->magick,"DCX") == 0)
     {
       size_t
@@ -299,11 +294,11 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
       */
       magic=ReadBlobLSBLong(image);
       if (magic != 987654321)
-        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+        ThrowPCXException(CorruptImageError,"ImproperImageHeader");
       page_table=(MagickOffsetType *) AcquireQuantumMemory(1024UL,
         sizeof(*page_table));
       if (page_table == (MagickOffsetType *) NULL)
-        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        ThrowPCXException(ResourceLimitError,"MemoryAllocationFailed");
       for (id=0; id < 1024; id++)
       {
         page_table[id]=(MagickOffsetType) ReadBlobLSBLong(image);
@@ -315,20 +310,25 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     {
       offset=SeekBlob(image,(MagickOffsetType) page_table[0],SEEK_SET);
       if (offset < 0)
-        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+        ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     }
-  pcx_colormap=(unsigned char *) NULL;
   count=ReadBlob(image,1,&pcx_info.identifier);
   for (id=1; id < 1024; id++)
   {
+    int
+      bits_per_pixel;
+
     /*
       Verify PCX identifier.
     */
     pcx_info.version=(unsigned char) ReadBlobByte(image);
-    if ((count == 0) || (pcx_info.identifier != 0x0a))
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+    if ((count != 1) || (pcx_info.identifier != 0x0a))
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     pcx_info.encoding=(unsigned char) ReadBlobByte(image);
-    pcx_info.bits_per_pixel=(unsigned char) ReadBlobByte(image);
+    bits_per_pixel=ReadBlobByte(image);
+    if (bits_per_pixel == -1)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    pcx_info.bits_per_pixel=(unsigned char) bits_per_pixel;
     pcx_info.left=ReadBlobLSBShort(image);
     pcx_info.top=ReadBlobLSBShort(image);
     pcx_info.right=ReadBlobLSBShort(image);
@@ -343,28 +343,41 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     image->rows=(size_t) MagickAbsoluteValue((ssize_t) pcx_info.bottom-
       pcx_info.top)+1UL;
     if ((image->columns == 0) || (image->rows == 0) ||
-        (pcx_info.bits_per_pixel == 0))
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
-    image->depth=pcx_info.bits_per_pixel <= 8 ? 8U : MAGICKCORE_QUANTUM_DEPTH;
+        ((pcx_info.bits_per_pixel != 1) && (pcx_info.bits_per_pixel != 2) &&
+         (pcx_info.bits_per_pixel != 4) && (pcx_info.bits_per_pixel != 8)))
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    image->depth=pcx_info.bits_per_pixel;
     image->units=PixelsPerInchResolution;
-    image->x_resolution=(double) pcx_info.horizontal_resolution;
-    image->y_resolution=(double) pcx_info.vertical_resolution;
+    image->resolution.x=(double) pcx_info.horizontal_resolution;
+    image->resolution.y=(double) pcx_info.vertical_resolution;
     image->colors=16;
-    pcx_colormap=(unsigned char *) AcquireQuantumMemory(256UL,
-      3*sizeof(*pcx_colormap));
-    if (pcx_colormap == (unsigned char *) NULL)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
+      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
+        break;
+    status=SetImageExtent(image,image->columns,image->rows,exception);
+    if (status == MagickFalse)
+      ThrowPCXException(exception->severity,exception->reason);
+    (void) SetImageBackgroundColor(image,exception);
+    (void) memset(pcx_colormap,0,sizeof(pcx_colormap));
     count=ReadBlob(image,3*image->colors,pcx_colormap);
+    if (count != (ssize_t) (3*image->colors))
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     pcx_info.reserved=(unsigned char) ReadBlobByte(image);
     pcx_info.planes=(unsigned char) ReadBlobByte(image);
+    if (pcx_info.planes == 0)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    if (pcx_info.planes > 6)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    if ((pcx_info.bits_per_pixel*pcx_info.planes) >= 64)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     one=1;
     if ((pcx_info.bits_per_pixel != 8) || (pcx_info.planes == 1))
       if ((pcx_info.version == 3) || (pcx_info.version == 5) ||
           ((pcx_info.bits_per_pixel*pcx_info.planes) == 1))
         image->colors=(size_t) MagickMin(one << (1UL*
           (pcx_info.bits_per_pixel*pcx_info.planes)),256UL);
-    if (AcquireImageColormap(image,image->colors) == MagickFalse)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+    if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
+      ThrowPCXException(ResourceLimitError,"MemoryAllocationFailed");
     if ((pcx_info.bits_per_pixel >= 8) && (pcx_info.planes != 1))
       image->storage_class=DirectClass;
     p=pcx_colormap;
@@ -376,33 +389,48 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
     }
     pcx_info.bytes_per_line=ReadBlobLSBShort(image);
     pcx_info.palette_info=ReadBlobLSBShort(image);
-    for (i=0; i < 58; i++)
+    pcx_info.horizontal_screensize=ReadBlobLSBShort(image);
+    pcx_info.vertical_screensize=ReadBlobLSBShort(image);
+    for (i=0; i < 54; i++)
       (void) ReadBlobByte(image);
-    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
-      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
-        break;
     /*
       Read image data.
     */
-    pcx_packets=(size_t) image->rows*pcx_info.bytes_per_line*
-      pcx_info.planes;
-    pcx_pixels=(unsigned char *) AcquireQuantumMemory(pcx_packets,
-      sizeof(*pcx_pixels));
+    if (HeapOverflowSanityCheck(image->rows, (size_t) pcx_info.bytes_per_line) != MagickFalse)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    pcx_packets=(size_t) image->rows*pcx_info.bytes_per_line;
+    if (HeapOverflowSanityCheck(pcx_packets, (size_t) pcx_info.planes) != MagickFalse)
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
+    pcx_packets=(size_t) pcx_packets*pcx_info.planes;
+    if ((size_t) (pcx_info.bits_per_pixel*pcx_info.planes*image->columns) >
+        (pcx_packets*8U))
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     scanline=(unsigned char *) AcquireQuantumMemory(MagickMax(image->columns,
       pcx_info.bytes_per_line),MagickMax(8,pcx_info.planes)*sizeof(*scanline));
-    if ((pcx_pixels == (unsigned char *) NULL) ||
-        (scanline == (unsigned char *) NULL))
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+    pixel_info=AcquireVirtualMemory(pcx_packets,2*sizeof(*pixels));
+    if ((scanline == (unsigned char *) NULL) ||
+        (pixel_info == (MemoryInfo *) NULL))
+      {
+        if (scanline != (unsigned char *) NULL)
+          scanline=(unsigned char *) RelinquishMagickMemory(scanline);
+        if (pixel_info != (MemoryInfo *) NULL)
+          pixel_info=RelinquishVirtualMemory(pixel_info);
+        ThrowPCXException(ResourceLimitError,"MemoryAllocationFailed");
+      }
+    (void) memset(scanline,0,(size_t) MagickMax(image->columns,
+      pcx_info.bytes_per_line)*MagickMax(8,pcx_info.planes)*sizeof(*scanline));
+    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
+    (void) memset(pixels,0,(size_t) pcx_packets*(2*sizeof(*pixels)));
     /*
       Uncompress image data.
     */
-    p=pcx_pixels;
+    p=pixels;
     if (pcx_info.encoding == 0)
       while (pcx_packets != 0)
       {
         packet=(unsigned char) ReadBlobByte(image);
         if (EOFBlob(image) != MagickFalse)
-          break;
+          ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile");
         *p++=packet;
         pcx_packets--;
       }
@@ -411,7 +439,7 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
       {
         packet=(unsigned char) ReadBlobByte(image);
         if (EOFBlob(image) != MagickFalse)
-          break;
+          ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile");
         if ((packet & 0xc0) != 0xc0)
           {
             *p++=packet;
@@ -421,7 +449,7 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
         count=(ssize_t) (packet & 0x3f);
         packet=(unsigned char) ReadBlobByte(image);
         if (EOFBlob(image) != MagickFalse)
-          break;
+          ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile");
         for ( ; count != 0; count--)
         {
           *p++=packet;
@@ -431,7 +459,8 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
         }
       }
     if (image->storage_class == DirectClass)
-      image->matte=pcx_info.planes > 3 ? MagickTrue : MagickFalse;
+      image->alpha_trait=pcx_info.planes > 3 ? BlendPixelTrait :
+        UndefinedPixelTrait;
     else
       if ((pcx_info.version == 5) ||
           ((pcx_info.bits_per_pixel*pcx_info.planes) == 1))
@@ -440,7 +469,7 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
             Initialize image colormap.
           */
           if (image->colors > 256)
-            ThrowReaderException(CorruptImageError,"ColormapExceeds256Colors");
+            ThrowPCXException(CorruptImageError,"ColormapExceeds256Colors");
           if ((pcx_info.bits_per_pixel*pcx_info.planes) == 1)
             {
               /*
@@ -449,9 +478,9 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
               image->colormap[0].red=(Quantum) 0;
               image->colormap[0].green=(Quantum) 0;
               image->colormap[0].blue=(Quantum) 0;
-              image->colormap[1].red=(Quantum) QuantumRange;
-              image->colormap[1].green=(Quantum) QuantumRange;
-              image->colormap[1].blue=(Quantum) QuantumRange;
+              image->colormap[1].red=QuantumRange;
+              image->colormap[1].green=QuantumRange;
+              image->colormap[1].blue=QuantumRange;
             }
           else
             if (image->colors > 16)
@@ -469,16 +498,15 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
                   image->colormap[i].blue=ScaleCharToQuantum(*p++);
                 }
             }
-          pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
         }
     /*
       Convert PCX raster image to pixel packets.
     */
     for (y=0; y < (ssize_t) image->rows; y++)
     {
-      p=pcx_pixels+(y*pcx_info.bytes_per_line*pcx_info.planes);
+      p=pixels+(y*pcx_info.bytes_per_line*pcx_info.planes);
       q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-      if (q == (const Quantum *) NULL)
+      if (q == (Quantum *) NULL)
         break;
       r=scanline;
       if (image->storage_class == DirectClass)
@@ -607,7 +635,7 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
             SetPixelRed(image,ScaleCharToQuantum(*r++),q);
             SetPixelGreen(image,ScaleCharToQuantum(*r++),q);
             SetPixelBlue(image,ScaleCharToQuantum(*r++),q);
-            if (image->matte != MagickFalse)
+            if (image->alpha_trait != UndefinedPixelTrait)
               SetPixelAlpha(image,ScaleCharToQuantum(*r++),q);
           }
         q+=GetPixelChannels(image);
@@ -623,11 +651,9 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
         }
     }
     if (image->storage_class == PseudoClass)
-      (void) SyncImage(image);
+      (void) SyncImage(image,exception);
     scanline=(unsigned char *) RelinquishMagickMemory(scanline);
-    if (pcx_colormap != (unsigned char *) NULL)
-      pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
-    pcx_pixels=(unsigned char *) RelinquishMagickMemory(pcx_pixels);
+    pixel_info=RelinquishVirtualMemory(pixel_info);
     if (EOFBlob(image) != MagickFalse)
       {
         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
@@ -646,14 +672,14 @@ static Image *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception)
       break;
     offset=SeekBlob(image,(MagickOffsetType) page_table[id],SEEK_SET);
     if (offset < 0)
-      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+      ThrowPCXException(CorruptImageError,"ImproperImageHeader");
     count=ReadBlob(image,1,&pcx_info.identifier);
     if ((count != 0) && (pcx_info.identifier == 0x0a))
       {
         /*
           Allocate next image structure.
         */
-        AcquireNextImage(image_info,image);
+        AcquireNextImage(image_info,image,exception);
         if (GetNextImageInList(image) == (Image *) NULL)
           {
             image=DestroyImageList(image);
@@ -700,22 +726,20 @@ ModuleExport size_t RegisterPCXImage(void)
   MagickInfo
     *entry;
 
-  entry=SetMagickInfo("DCX");
+  entry=AcquireMagickInfo("PCX","DCX","ZSoft IBM PC multi-page Paintbrush");
   entry->decoder=(DecodeImageHandler *) ReadPCXImage;
   entry->encoder=(EncodeImageHandler *) WritePCXImage;
-  entry->seekable_stream=MagickTrue;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
+  entry->flags|=CoderEncoderSeekableStreamFlag;
   entry->magick=(IsImageFormatHandler *) IsDCX;
-  entry->description=ConstantString("ZSoft IBM PC multi-page Paintbrush");
-  entry->module=ConstantString("PCX");
   (void) RegisterMagickInfo(entry);
-  entry=SetMagickInfo("PCX");
+  entry=AcquireMagickInfo("PCX","PCX","ZSoft IBM PC Paintbrush");
   entry->decoder=(DecodeImageHandler *) ReadPCXImage;
   entry->encoder=(EncodeImageHandler *) WritePCXImage;
   entry->magick=(IsImageFormatHandler *) IsPCX;
-  entry->adjoin=MagickFalse;
-  entry->seekable_stream=MagickTrue;
-  entry->description=ConstantString("ZSoft IBM PC Paintbrush");
-  entry->module=ConstantString("PCX");
+  entry->flags^=CoderAdjoinFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
+  entry->flags|=CoderEncoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);
 }
@@ -761,7 +785,8 @@ ModuleExport void UnregisterPCXImage(void)
 %
 %  The format of the WritePCXImage method is:
 %
-%      MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
+%      MagickBooleanType WritePCXImage(const ImageInfo *image_info,
+%        Image *image,ExceptionInfo *exception)
 %
 %  A description of each parameter follows.
 %
@@ -769,8 +794,10 @@ ModuleExport void UnregisterPCXImage(void)
 %
 %    o image:  The image.
 %
+%    o exception: return any errors or warnings in this structure.
 %
 */
+
 static MagickBooleanType PCXWritePixels(PCXInfo *pcx_info,
   const unsigned char *pixels,Image *image)
 {
@@ -828,7 +855,8 @@ static MagickBooleanType PCXWritePixels(PCXInfo *pcx_info,
   return (MagickTrue);
 }
 
-static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
+static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image,
+  ExceptionInfo *exception)
 {
   MagickBooleanType
     status;
@@ -838,6 +866,9 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
     *page_table,
     scene;
 
+  MemoryInfo
+    *pixel_info;
+
   PCXInfo
     pcx_info;
 
@@ -859,22 +890,25 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
 
   unsigned char
     *pcx_colormap,
-    *pcx_pixels;
+    *pixels;
 
   /*
     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);
-  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+  assert(exception != (ExceptionInfo *) NULL);
+  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);
+  if ((image->columns > 65535UL) || (image->rows > 65535UL))
+    ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
+  (void) TransformImageColorspace(image,sRGBColorspace,exception);
   page_table=(MagickOffsetType *) NULL;
   if ((LocaleCompare(image_info->magick,"DCX") == 0) ||
       ((GetNextImageInList(image) != (Image *) NULL) &&
@@ -904,7 +938,7 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
     pcx_info.encoding=image_info->compression == NoCompression ? 0 : 1;
     pcx_info.bits_per_pixel=8;
     if ((image->storage_class == PseudoClass) &&
-        (IsImageMonochrome(image,&image->exception) != MagickFalse))
+        (SetImageMonochrome(image,exception) != MagickFalse))
       pcx_info.bits_per_pixel=1;
     pcx_info.left=0;
     pcx_info.top=0;
@@ -916,16 +950,16 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
       case PixelsPerInchResolution:
       default:
       {
-        pcx_info.horizontal_resolution=(unsigned short) image->x_resolution;
-        pcx_info.vertical_resolution=(unsigned short) image->y_resolution;
+        pcx_info.horizontal_resolution=(unsigned short) image->resolution.x;
+        pcx_info.vertical_resolution=(unsigned short) image->resolution.y;
         break;
       }
       case PixelsPerCentimeterResolution:
       {
         pcx_info.horizontal_resolution=(unsigned short)
-          (2.54*image->x_resolution+0.5);
+          (2.54*image->resolution.x+0.5);
         pcx_info.vertical_resolution=(unsigned short)
-          (2.54*image->y_resolution+0.5);
+          (2.54*image->resolution.y+0.5);
         break;
       }
     }
@@ -934,11 +968,13 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
     if ((image->storage_class == DirectClass) || (image->colors > 256))
       {
         pcx_info.planes=3;
-        if (image->matte != MagickFalse)
+        if (image->alpha_trait != UndefinedPixelTrait)
           pcx_info.planes++;
       }
-    pcx_info.bytes_per_line=(unsigned short) (((size_t) image->columns*
-      pcx_info.bits_per_pixel+7)/8);
+    length=(((size_t) image->columns*pcx_info.bits_per_pixel+7)/8);
+    if (length > 65535UL)
+      ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
+    pcx_info.bytes_per_line=(unsigned short) length;
     pcx_info.palette_info=1;
     pcx_info.colormap_signature=0x0c;
     /*
@@ -978,29 +1014,29 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
     for (i=0; i < 58; i++)
       (void) WriteBlobByte(image,'\0');
     length=(size_t) pcx_info.bytes_per_line;
-    pcx_pixels=(unsigned char *) AcquireQuantumMemory(length,pcx_info.planes*
-      sizeof(*pcx_pixels));
-    if (pcx_pixels == (unsigned char *) NULL)
-      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
-    q=pcx_pixels;
+    pixel_info=AcquireVirtualMemory(length,pcx_info.planes*sizeof(*pixels));
+    if (pixel_info == (MemoryInfo *) NULL)
+      {
+        pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
+        if (page_table != (MagickOffsetType *) NULL)
+          page_table=(MagickOffsetType *) RelinquishMagickMemory(page_table);
+        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+      }
+    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
+    q=pixels;
     if ((image->storage_class == DirectClass) || (image->colors > 256))
       {
-        const Quantum
-          *pixels;
-
         /*
           Convert DirectClass image to PCX raster pixels.
         */
         for (y=0; y < (ssize_t) image->rows; y++)
         {
-          pixels=GetVirtualPixels(image,0,y,image->columns,1,
-            &image->exception);
-          if (pixels == (const Quantum *) NULL)
-            break;
-          q=pcx_pixels;
+          q=pixels;
           for (i=0; i < pcx_info.planes; i++)
           {
-            p=pixels;
+            p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+            if (p == (const Quantum *) NULL)
+              break;
             switch ((int) i)
             {
               case 0:
@@ -1042,7 +1078,7 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
               }
             }
           }
-          if (PCXWritePixels(&pcx_info,pcx_pixels,image) == MagickFalse)
+          if (PCXWritePixels(&pcx_info,pixels,image) == MagickFalse)
             break;
           if (image->previous == (Image *) NULL)
             {
@@ -1058,30 +1094,27 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
         if (pcx_info.bits_per_pixel > 1)
           for (y=0; y < (ssize_t) image->rows; y++)
           {
-            p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+            p=GetVirtualPixels(image,0,y,image->columns,1,exception);
             if (p == (const Quantum *) NULL)
               break;
-            q=pcx_pixels;
+            q=pixels;
             for (x=0; x < (ssize_t) image->columns; x++)
             {
               *q++=(unsigned char) GetPixelIndex(image,p);
               p+=GetPixelChannels(image);
             }
-            if (PCXWritePixels(&pcx_info,pcx_pixels,image) == MagickFalse)
+            if (PCXWritePixels(&pcx_info,pixels,image) == MagickFalse)
               break;
             if (image->previous == (Image *) NULL)
               {
-                status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
-                image->rows);
+                status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
+                  y,image->rows);
                 if (status == MagickFalse)
                   break;
               }
           }
         else
           {
-            Quantum
-              polarity;
-
             register unsigned char
               bit,
               byte;
@@ -1089,24 +1122,18 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
             /*
               Convert PseudoClass image to a PCX monochrome image.
             */
-            polarity=(Quantum) (GetPixelPacketIntensity(
-              &image->colormap[0]) < ((Quantum) QuantumRange/2) ? 1 : 0);
-            if (image->colors == 2)
-              polarity=(Quantum) (GetPixelPacketIntensity(&image->colormap[0]) <
-                GetPixelPacketIntensity(&image->colormap[1]) ? 1 : 0);
             for (y=0; y < (ssize_t) image->rows; y++)
             {
-              p=GetVirtualPixels(image,0,y,image->columns,1,
-                &image->exception);
+              p=GetVirtualPixels(image,0,y,image->columns,1,exception);
               if (p == (const Quantum *) NULL)
                 break;
               bit=0;
               byte=0;
-              q=pcx_pixels;
+              q=pixels;
               for (x=0; x < (ssize_t) image->columns; x++)
               {
                 byte<<=1;
-                if (GetPixelIndex(image,p) == polarity)
+                if (GetPixelLuma(image,p) >= (QuantumRange/2.0))
                   byte|=0x01;
                 bit++;
                 if (bit == 8)
@@ -1119,7 +1146,7 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
               }
               if (bit != 0)
                 *q++=byte << (8-bit);
-              if (PCXWritePixels(&pcx_info,pcx_pixels,image) == MagickFalse)
+              if (PCXWritePixels(&pcx_info,pixels,image) == MagickFalse)
                 break;
               if (image->previous == (Image *) NULL)
                 {
@@ -1133,7 +1160,7 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
         (void) WriteBlobByte(image,pcx_info.colormap_signature);
         (void) WriteBlob(image,3*256,pcx_colormap);
       }
-    pcx_pixels=(unsigned char *) RelinquishMagickMemory(pcx_pixels);
+    pixel_info=RelinquishVirtualMemory(pixel_info);
     pcx_colormap=(unsigned char *) RelinquishMagickMemory(pcx_colormap);
     if (page_table == (MagickOffsetType *) NULL)
       break;
@@ -1155,7 +1182,10 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
       page_table[scene+1]=0;
       offset=SeekBlob(image,0L,SEEK_SET);
       if (offset < 0)
-        ThrowWriterException(CorruptImageError,"ImproperImageHeader");
+        {
+          page_table=(MagickOffsetType *) RelinquishMagickMemory(page_table);
+          ThrowWriterException(CorruptImageError,"ImproperImageHeader");
+        }
       (void) WriteBlobLSBLong(image,0x3ADE68B1L);
       for (i=0; i <= (ssize_t) scene; i++)
         (void) WriteBlobLSBLong(image,(unsigned int) page_table[i]);
@@ -1167,8 +1197,8 @@ static MagickBooleanType WritePCXImage(const ImageInfo *image_info,Image *image)
         *message;
 
       message=GetExceptionMessage(errno);
-      (void) ThrowMagickException(&image->exception,GetMagickModule(),
-        FileOpenError,"UnableToWriteFile","`%s': %s",image->filename,message);
+      (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
+        "UnableToWriteFile","`%s': %s",image->filename,message);
       message=DestroyString(message);
     }
   (void) CloseBlob(image);