]> granicus.if.org Git - imagemagick/blobdiff - coders/miff.c
(no commit message)
[imagemagick] / coders / miff.c
index 3d1f8590c32a48d14b7c849de2928bdf1aa4fca0..9dba61ad096237c678c1095101fbdce0b3d8abc2 100644 (file)
 %                      Read/Write MIFF Image Format                           %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2015 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  %
@@ -49,6 +49,7 @@
 #include "MagickCore/colormap.h"
 #include "MagickCore/colormap-private.h"
 #include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
 #include "MagickCore/constitute.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
@@ -184,20 +185,6 @@ static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
 }
 #endif
 
-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)
-{
-  if (x < y)
-    return(x);
-  return(y);
-}
-
 static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
   size_t *length,PixelInfo *pixel,ExceptionInfo *exception)
 {
@@ -212,8 +199,9 @@ static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
       {
         case 32:
         {
-          pixel->index=ConstrainColormapIndex(image,
-            (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3),exception);
+          pixel->index=ConstrainColormapIndex(image,((size_t) *p << 24) |
+            ((size_t) *(p+1) << 16) | ((size_t) *(p+2) << 8) | (size_t) *(p+3),
+            exception);
           p+=4;
           break;
         }
@@ -241,7 +229,7 @@ static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
           unsigned char
             quantum;
 
-          if (image->matte != MagickFalse)
+          if (image->alpha_trait != UndefinedPixelTrait)
             {
               p=PushCharPixel(p,&quantum);
               pixel->alpha=ScaleCharToQuantum(quantum);
@@ -253,7 +241,7 @@ static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
           unsigned short
             quantum;
 
-          if (image->matte != MagickFalse)
+          if (image->alpha_trait != UndefinedPixelTrait)
             {
               p=PushShortPixel(MSBEndian,p,&quantum);
               pixel->alpha=(Quantum) (quantum >> (image->depth-
@@ -266,7 +254,7 @@ static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
           unsigned int
             quantum;
 
-          if (image->matte != MagickFalse)
+          if (image->alpha_trait != UndefinedPixelTrait)
             {
               p=PushLongPixel(MSBEndian,p,&quantum);
               pixel->alpha=(Quantum) (quantum >> (image->depth-
@@ -290,16 +278,21 @@ static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
 
       p=PushCharPixel(p,&quantum);
       pixel->red=ScaleCharToQuantum(quantum);
-      p=PushCharPixel(p,&quantum);
-      pixel->green=ScaleCharToQuantum(quantum);
-      p=PushCharPixel(p,&quantum);
-      pixel->blue=ScaleCharToQuantum(quantum);
+      pixel->green=pixel->red;
+      pixel->blue=pixel->red;
+      if (IsGrayColorspace(image->colorspace) == MagickFalse)
+        {
+          p=PushCharPixel(p,&quantum);
+          pixel->green=ScaleCharToQuantum(quantum);
+          p=PushCharPixel(p,&quantum);
+          pixel->blue=ScaleCharToQuantum(quantum);
+        }
       if (image->colorspace == CMYKColorspace)
         {
           p=PushCharPixel(p,&quantum);
           pixel->black=ScaleCharToQuantum(quantum);
         }
-      if (image->matte != MagickFalse)
+      if (image->alpha_trait != UndefinedPixelTrait)
         {
           p=PushCharPixel(p,&quantum);
           pixel->alpha=ScaleCharToQuantum(quantum);
@@ -313,16 +306,21 @@ static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
 
       p=PushShortPixel(MSBEndian,p,&quantum);
       pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
-      p=PushShortPixel(MSBEndian,p,&quantum);
-      pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
-      p=PushShortPixel(MSBEndian,p,&quantum);
-      pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
+      pixel->green=pixel->red;
+      pixel->blue=pixel->red;
+      if (IsGrayColorspace(image->colorspace) == MagickFalse)
+        {
+          p=PushShortPixel(MSBEndian,p,&quantum);
+          pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
+          p=PushShortPixel(MSBEndian,p,&quantum);
+          pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
+        }
       if (image->colorspace == CMYKColorspace)
         {
           p=PushShortPixel(MSBEndian,p,&quantum);
           pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
         }
-      if (image->matte != MagickFalse)
+      if (image->alpha_trait != UndefinedPixelTrait)
         {
           p=PushShortPixel(MSBEndian,p,&quantum);
           pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
@@ -336,16 +334,21 @@ static void PushRunlengthPacket(Image *image,const unsigned char *pixels,
 
       p=PushLongPixel(MSBEndian,p,&quantum);
       pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
-      p=PushLongPixel(MSBEndian,p,&quantum);
-      pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
-      p=PushLongPixel(MSBEndian,p,&quantum);
-      pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
+      pixel->green=pixel->red;
+      pixel->blue=pixel->red;
+      if (IsGrayColorspace(image->colorspace) == MagickFalse)
+        {
+          p=PushLongPixel(MSBEndian,p,&quantum);
+          pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
+          p=PushLongPixel(MSBEndian,p,&quantum);
+          pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
+        }
       if (image->colorspace == CMYKColorspace)
         {
           p=PushLongPixel(MSBEndian,p,&quantum);
           pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
         }
-      if (image->matte != MagickFalse)
+      if (image->alpha_trait != UndefinedPixelTrait)
         {
           p=PushLongPixel(MSBEndian,p,&quantum);
           pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH);
@@ -415,6 +418,9 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
   int
     c;
 
+  LinkedListInfo
+    *profiles;
+
 #if defined(MAGICKCORE_LZMA_DELEGATE)
   lzma_stream
     initialize_lzma = LZMA_STREAM_INIT,
@@ -424,9 +430,6 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
     allocator;
 #endif
 
-  LinkedListInfo
-    *profiles;
-
   MagickBooleanType
     status;
 
@@ -449,6 +452,7 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
     i;
 
   size_t
+    compress_extent,
     length,
     packet_size;
 
@@ -527,8 +531,11 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
           for (p=comment; comment != (char *) NULL; p++)
           {
             c=ReadBlobByte(image);
-            if ((c == EOF) || (c == (int) '}'))
-              break;
+            if (c == (int) '\\')
+              c=ReadBlobByte(image);
+            else
+              if ((c == EOF) || (c == (int) '}'))
+                break;
             if ((size_t) (p-comment+1) >= length)
               {
                 *p='\0';
@@ -554,6 +561,7 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
             /*
               Get the keyword.
             */
+            length=MaxTextExtent;
             p=keyword;
             do
             {
@@ -585,24 +593,51 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
                         break;
                       p=options+strlen(options);
                     }
-                  if (options == (char *) NULL)
-                    ThrowReaderException(ResourceLimitError,
-                      "MemoryAllocationFailed");
                   *p++=(char) c;
                   c=ReadBlobByte(image);
+                  if (c == '\\')
+                    {
+                      c=ReadBlobByte(image);
+                      if (c == (int) '}')
+                        {
+                          *p++=(char) c;
+                          c=ReadBlobByte(image);
+                        }
+                    }
                   if (*options != '{')
                     if (isspace((int) ((unsigned char) c)) != 0)
                       break;
                 }
+                if (options == (char *) NULL)
+                  ThrowReaderException(ResourceLimitError,
+                    "MemoryAllocationFailed");
               }
             *p='\0';
             if (*options == '{')
-              (void) CopyMagickString(options,options+1,MaxTextExtent);
+              (void) CopyMagickString(options,options+1,strlen(options));
             /*
               Assign a value to the specified keyword.
             */
             switch (*keyword)
             {
+              case 'a':
+              case 'A':
+              {
+                if (LocaleCompare(keyword,"alpha-trait") == 0)
+                  {
+                    ssize_t
+                      alpha_trait;
+
+                    alpha_trait=ParseCommandOption(MagickPixelTraitOptions,
+                      MagickFalse,options);
+                    if (alpha_trait < 0)
+                      break;
+                    image->alpha_trait=(PixelTrait) alpha_trait;
+                    break;
+                  }
+                (void) SetImageProperty(image,keyword,options,exception);
+                break;
+              }
               case 'b':
               case 'B':
               {
@@ -790,7 +825,8 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
                       options);
                     if (matte < 0)
                       break;
-                    image->matte=(MagickBooleanType) matte;
+                    image->alpha_trait=matte == 0 ? UndefinedPixelTrait :
+                      BlendPixelTrait;
                     break;
                   }
                 if (LocaleCompare(keyword,"matte-color") == 0)
@@ -810,18 +846,6 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
               case 'o':
               case 'O':
               {
-                if (LocaleCompare(keyword,"opaque") == 0)
-                  {
-                    ssize_t
-                      matte;
-
-                    matte=ParseCommandOption(MagickBooleanOptions,MagickFalse,
-                      options);
-                    if (matte < 0)
-                      break;
-                    image->matte=(MagickBooleanType) matte;
-                    break;
-                  }
                 if (LocaleCompare(keyword,"orientation") == 0)
                   {
                     ssize_t
@@ -850,6 +874,18 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
                     geometry=DestroyString(geometry);
                     break;
                   }
+                if (LocaleCompare(keyword,"pixel-intensity") == 0)
+                  {
+                    ssize_t
+                      intensity;
+
+                    intensity=ParseCommandOption(MagickPixelIntensityOptions,
+                      MagickFalse,options);
+                    if (intensity < 0)
+                      break;
+                    image->intensity=(PixelIntensityMethod) intensity;
+                    break;
+                  }
                 if ((LocaleNCompare(keyword,"profile:",8) == 0) ||
                     (LocaleNCompare(keyword,"profile-",8) == 0))
                   {
@@ -1018,8 +1054,8 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
                   {
                     flags=ParseGeometry(options,&geometry_info);
                     image->chromaticity.white_point.x=geometry_info.rho;
-                    image->chromaticity.white_point.y=geometry_info.rho;
-                    if ((flags & SigmaValue) != 0)
+                    image->chromaticity.white_point.y=geometry_info.sigma;
+                    if ((flags & SigmaValue) == 0)
                       image->chromaticity.white_point.y=
                         image->chromaticity.white_point.x;
                     break;
@@ -1194,6 +1230,9 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
     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)
+      return(DestroyImageList(image));
     /*
       Allocate image pixels.
     */
@@ -1209,20 +1248,18 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
     packet_size=(size_t) (quantum_info->depth/8);
     if (image->storage_class == DirectClass)
       packet_size=(size_t) (3*quantum_info->depth/8);
-    if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
-        (image->type == GrayscaleMatteType))
+    if (IsGrayColorspace(image->colorspace) != MagickFalse)
       packet_size=quantum_info->depth/8;
-    if (image->matte != MagickFalse)
+    if (image->alpha_trait != UndefinedPixelTrait)
       packet_size+=quantum_info->depth/8;
     if (image->colorspace == CMYKColorspace)
       packet_size+=quantum_info->depth/8;
     if (image->compression == RLECompression)
       packet_size++;
-    length=image->columns;
-    length=MagickMax(MagickMax(BZipMaxExtent(packet_size*image->columns),
-      LZMAMaxExtent(packet_size*image->columns)),ZipMaxExtent(packet_size*
-      image->columns));
-    compress_pixels=(unsigned char *) AcquireQuantumMemory(length,
+    compress_extent=MagickMax(MagickMax(BZipMaxExtent(packet_size*
+      image->columns),LZMAMaxExtent(packet_size*image->columns)),
+      ZipMaxExtent(packet_size*image->columns));
+    compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_extent,
       sizeof(*compress_pixels));
     if (compress_pixels == (unsigned char *) NULL)
       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
@@ -1230,28 +1267,37 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
       Read image pixels.
     */
     quantum_type=RGBQuantum;
-    if (image->matte != MagickFalse)
+    if (image->alpha_trait != UndefinedPixelTrait)
       quantum_type=RGBAQuantum;
     if (image->colorspace == CMYKColorspace)
       {
         quantum_type=CMYKQuantum;
-        if (image->matte != MagickFalse)
+        if (image->alpha_trait != UndefinedPixelTrait)
           quantum_type=CMYKAQuantum;
       }
+    if (IsGrayColorspace(image->colorspace) != MagickFalse)
+      {
+        quantum_type=GrayQuantum;
+        if (image->alpha_trait != UndefinedPixelTrait)
+          quantum_type=GrayAlphaQuantum;
+      }
     if (image->storage_class == PseudoClass)
       {
         quantum_type=IndexQuantum;
-        if (image->matte != MagickFalse)
+        if (image->alpha_trait != UndefinedPixelTrait)
           quantum_type=IndexAlphaQuantum;
       }
-    if ((image->type == BilevelType) || (image->type == GrayscaleType) ||
-        (image->type == GrayscaleMatteType))
-      {
-        quantum_type=GrayQuantum;
-        if (image->matte != MagickFalse)
-          quantum_type=GrayAlphaQuantum;
-      }
     status=MagickTrue;
+    GetPixelInfo(image,&pixel);
+#if defined(MAGICKCORE_BZLIB_DELEGATE)
+   (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
+#endif
+#if defined(MAGICKCORE_LZMA_DELEGATE)
+    (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
+#endif
+#if defined(MAGICKCORE_ZLIB_DELEGATE)
+    (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
+#endif
     switch (image->compression)
     {
 #if defined(MAGICKCORE_BZLIB_DELEGATE)
@@ -1260,7 +1306,6 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
         int
           code;
 
-        (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info));
         bzip_info.bzalloc=AcquireBZIPMemory;
         bzip_info.bzfree=RelinquishBZIPMemory;
         bzip_info.opaque=(void *) NULL;
@@ -1277,7 +1322,6 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
         int
           code;
 
-        (void) ResetMagickMemory(&allocator,0,sizeof(allocator));
         allocator.alloc=AcquireLZMAMemory;
         allocator.free=RelinquishLZMAMemory;
         lzma_info=initialize_lzma;
@@ -1295,7 +1339,6 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
         int
           code;
 
-        (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info));
         zip_info.zalloc=AcquireZIPMemory;
         zip_info.zfree=RelinquishZIPMemory;
         zip_info.opaque=(voidpf) NULL;
@@ -1306,10 +1349,7 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
       }
 #endif
       case RLECompression:
-      {
-        GetPixelInfo(image,&pixel);
         break;
-      }
       default:
         break;
     }
@@ -1337,16 +1377,28 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
           bzip_info.avail_out=(unsigned int) (packet_size*image->columns);
           do
           {
+            int
+              code;
+
             if (bzip_info.avail_in == 0)
               {
                 bzip_info.next_in=(char *) compress_pixels;
                 length=(size_t) BZipMaxExtent(packet_size*image->columns);
                 if (version != 0.0)
                   length=(size_t) ReadBlobMSBLong(image);
+                if (length > compress_extent)
+                  ThrowReaderException(CorruptImageError,
+                    "UnableToReadImageData");
                 bzip_info.avail_in=(unsigned int) ReadBlob(image,length,
                   (unsigned char *) bzip_info.next_in);
               }
-            if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END)
+            code=BZ2_bzDecompress(&bzip_info);
+            if (code < 0)
+              {
+                status=MagickFalse;
+                break;
+              }
+            if (code == BZ_STREAM_END)
               break;
           } while (bzip_info.avail_out != 0);
           (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
@@ -1368,6 +1420,9 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
               {
                 lzma_info.next_in=compress_pixels;
                 length=(size_t) ReadBlobMSBLong(image);
+                if (length > compress_extent)
+                  ThrowReaderException(CorruptImageError,
+                    "UnableToReadImageData");
                 lzma_info.avail_in=(unsigned int) ReadBlob(image,length,
                   (unsigned char *) lzma_info.next_in);
               }
@@ -1393,16 +1448,28 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
           zip_info.avail_out=(uInt) (packet_size*image->columns);
           do
           {
+            int
+              code;
+
             if (zip_info.avail_in == 0)
               {
                 zip_info.next_in=compress_pixels;
                 length=(size_t) ZipMaxExtent(packet_size*image->columns);
                 if (version != 0.0)
                   length=(size_t) ReadBlobMSBLong(image);
+                if (length > compress_extent)
+                  ThrowReaderException(CorruptImageError,
+                    "UnableToReadImageData");
                 zip_info.avail_in=(unsigned int) ReadBlob(image,length,
                   zip_info.next_in);
               }
-            if (inflate(&zip_info,Z_SYNC_FLUSH) == Z_STREAM_END)
+            code=inflate(&zip_info,Z_SYNC_FLUSH);
+            if (code < 0)
+              {
+                status=MagickFalse;
+                break;
+              }
+            if (code == Z_STREAM_END)
               break;
           } while (zip_info.avail_out != 0);
           (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
@@ -1430,7 +1497,7 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
                 if (image->colorspace == CMYKColorspace)
                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
               }
-            if (image->matte != MagickFalse)
+            if (image->alpha_trait != UndefinedPixelTrait)
               SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
             q+=GetPixelChannels(image);
           }
@@ -1464,8 +1531,7 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
             offset=SeekBlob(image,-((MagickOffsetType)
               bzip_info.avail_in),SEEK_CUR);
             if (offset < 0)
-              ThrowReaderException(CorruptImageError,
-                "ImproperImageHeader");
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
           }
         code=BZ2_bzDecompressEnd(&bzip_info);
         if (code != BZ_OK)
@@ -1501,8 +1567,7 @@ static Image *ReadMIFFImage(const ImageInfo *image_info,
             offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in),
               SEEK_CUR);
             if (offset < 0)
-              ThrowReaderException(CorruptImageError,
-                "ImproperImageHeader");
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
           }
         code=inflateEnd(&zip_info);
         if (code != LZMA_OK)
@@ -1603,7 +1668,7 @@ ModuleExport size_t RegisterMIFFImage(void)
   entry->decoder=(DecodeImageHandler *) ReadMIFFImage;
   entry->encoder=(EncodeImageHandler *) WriteMIFFImage;
   entry->magick=(IsImageFormatHandler *) IsMIFF;
-  entry->seekable_stream=MagickTrue;
+  entry->flags|=CoderSeekableStreamFlag;
   entry->description=ConstantString("Magick Image File Format");
   if (*version != '\0')
     entry->version=ConstantString(version);
@@ -1671,18 +1736,22 @@ static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
 {
   if (image->storage_class != DirectClass)
     {
+      unsigned int
+        value;
+
+      value=(unsigned int) ClampToQuantum(pixel->index);
       switch (image->depth)
       {
         case 32:
         {
-          *pixels++=(unsigned char) ((size_t) pixel->index >> 24);
-          *pixels++=(unsigned char) ((size_t) pixel->index >> 16);
+          *pixels++=(unsigned char) (value >> 24);
+          *pixels++=(unsigned char) (value >> 16);
         }
         case 16:
-          *pixels++=(unsigned char) ((size_t) pixel->index >> 8);
+          *pixels++=(unsigned char) (value >> 8);
         case 8:
         {
-          *pixels++=(unsigned char) pixel->index;
+          *pixels++=(unsigned char) value;
           break;
         }
         default:
@@ -1696,7 +1765,7 @@ static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
           unsigned int
             value;
 
-          if (image->matte != MagickFalse)
+          if (image->alpha_trait != UndefinedPixelTrait)
             {
               value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
               pixels=PopLongPixel(MSBEndian,value,pixels);
@@ -1708,7 +1777,7 @@ static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
           unsigned short
             value;
 
-          if (image->matte != MagickFalse)
+          if (image->alpha_trait != UndefinedPixelTrait)
             {
               value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
               pixels=PopShortPixel(MSBEndian,value,pixels);
@@ -1720,7 +1789,7 @@ static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
           unsigned char
             value;
 
-          if (image->matte != MagickFalse)
+          if (image->alpha_trait != UndefinedPixelTrait)
             {
               value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
                 pixel->alpha));
@@ -1744,16 +1813,19 @@ static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
 
       value=ScaleQuantumToLong(ClampToQuantum(pixel->red));
       pixels=PopLongPixel(MSBEndian,value,pixels);
-      value=ScaleQuantumToLong(ClampToQuantum(pixel->green));
-      pixels=PopLongPixel(MSBEndian,value,pixels);
-      value=ScaleQuantumToLong(ClampToQuantum(pixel->blue));
-      pixels=PopLongPixel(MSBEndian,value,pixels);
+      if (IsGrayColorspace(image->colorspace) == MagickFalse)
+        {
+          value=ScaleQuantumToLong(ClampToQuantum(pixel->green));
+          pixels=PopLongPixel(MSBEndian,value,pixels);
+          value=ScaleQuantumToLong(ClampToQuantum(pixel->blue));
+          pixels=PopLongPixel(MSBEndian,value,pixels);
+        }
       if (image->colorspace == CMYKColorspace)
         {
           value=ScaleQuantumToLong(ClampToQuantum(pixel->black));
           pixels=PopLongPixel(MSBEndian,value,pixels);
         }
-      if (image->matte != MagickFalse)
+      if (image->alpha_trait != UndefinedPixelTrait)
         {
           value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha));
           pixels=PopLongPixel(MSBEndian,value,pixels);
@@ -1767,16 +1839,19 @@ static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
 
       value=ScaleQuantumToShort(ClampToQuantum(pixel->red));
       pixels=PopShortPixel(MSBEndian,value,pixels);
-      value=ScaleQuantumToShort(ClampToQuantum(pixel->green));
-      pixels=PopShortPixel(MSBEndian,value,pixels);
-      value=ScaleQuantumToShort(ClampToQuantum(pixel->blue));
-      pixels=PopShortPixel(MSBEndian,value,pixels);
+      if (IsGrayColorspace(image->colorspace) == MagickFalse)
+        {
+          value=ScaleQuantumToShort(ClampToQuantum(pixel->green));
+          pixels=PopShortPixel(MSBEndian,value,pixels);
+          value=ScaleQuantumToShort(ClampToQuantum(pixel->blue));
+          pixels=PopShortPixel(MSBEndian,value,pixels);
+        }
       if (image->colorspace == CMYKColorspace)
         {
           value=ScaleQuantumToShort(ClampToQuantum(pixel->black));
           pixels=PopShortPixel(MSBEndian,value,pixels);
         }
-      if (image->matte != MagickFalse)
+      if (image->alpha_trait != UndefinedPixelTrait)
         {
           value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha));
           pixels=PopShortPixel(MSBEndian,value,pixels);
@@ -1790,17 +1865,21 @@ static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels,
 
       value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->red));
       pixels=PopCharPixel(value,pixels);
-      value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->green));
-      pixels=PopCharPixel(value,pixels);
-      value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue));
-      pixels=PopCharPixel(value,pixels);
+      if (IsGrayColorspace(image->colorspace) == MagickFalse)
+        {
+          value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
+            pixel->green));
+          pixels=PopCharPixel(value,pixels);
+          value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue));
+          pixels=PopCharPixel(value,pixels);
+        }
       if (image->colorspace == CMYKColorspace)
         {
           value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
             pixel->black));
           pixels=PopCharPixel(value,pixels);
         }
-      if (image->matte != MagickFalse)
+      if (image->alpha_trait != UndefinedPixelTrait)
         {
           value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(
             pixel->alpha));
@@ -1899,8 +1978,22 @@ static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
     /*
       Allocate image pixels.
     */
+    if ((image->storage_class == PseudoClass) &&
+        (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
+      (void) SetImageStorageClass(image,DirectClass,exception);
     image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL :
       image->depth <= 32 ? 32UL : 64UL;
+    if (IsImageGray(image,exception) == MagickFalse)
+      {
+        /*
+          sRGB masquerading as a grayscale image?
+        */
+        if (IsGrayColorspace(image->colorspace) != MagickFalse)
+          (void) SetImageColorspace(image,sRGBColorspace,exception);
+      }
+    else
+      if (IsGrayColorspace(image->colorspace) == MagickFalse)
+        (void) SetImageColorspace(image,GRAYColorspace,exception);
     quantum_info=AcquireQuantumInfo(image_info,image);
     if (quantum_info == (QuantumInfo *) NULL)
       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
@@ -1912,20 +2005,12 @@ static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
         if (status == MagickFalse)
           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
       }
-    if ((image->storage_class == PseudoClass) &&
-        (image->colors > (size_t) (GetQuantumRange(image->depth)+1)))
-      (void) SetImageStorageClass(image,DirectClass,exception);
-    if (IsImageGray(image,exception) != MagickFalse)
-      {
-        (void) SetImageStorageClass(image,DirectClass,exception);
-        (void) SetImageColorspace(image,GRAYColorspace,exception);
-      }
-    compression=image->compression;
+    compression=UndefinedCompression;
     if (image_info->compression != UndefinedCompression)
       compression=image_info->compression;
     switch (compression)
     {
-#if !defined(MAGICKCORE_ZLIB_DELEGATE)
+#if !defined(MAGICKCORE_LZMA_DELEGATE)
       case LZMACompression: compression=NoCompression; break;
 #endif
 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
@@ -1948,15 +2033,14 @@ static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
     packet_size=(size_t) (quantum_info->depth/8);
     if (image->storage_class == DirectClass)
       packet_size=(size_t) (3*quantum_info->depth/8);
-    if (IsImageGray(image,exception) != MagickFalse)
+    if (IsGrayColorspace(image->colorspace) != MagickFalse)
       packet_size=(size_t) (quantum_info->depth/8);
-    if (image->matte != MagickFalse)
+    if (image->alpha_trait != UndefinedPixelTrait)
       packet_size+=quantum_info->depth/8;
     if (image->colorspace == CMYKColorspace)
       packet_size+=quantum_info->depth/8;
     if (compression == RLECompression)
       packet_size++;
-    length=image->columns;
     length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent(
       packet_size*image->columns));
     if ((compression == BZipCompression) || (compression == ZipCompression))
@@ -1971,9 +2055,10 @@ static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
     */
     (void) WriteBlobString(image,"id=ImageMagick  version=1.0\n");
     (void) FormatLocaleString(buffer,MaxTextExtent,
-      "class=%s  colors=%.20g  matte=%s\n",CommandOptionToMnemonic(
+      "class=%s  colors=%.20g  alpha-trait=%s\n",CommandOptionToMnemonic(
       MagickClassOptions,image->storage_class),(double) image->colors,
-      CommandOptionToMnemonic(MagickBooleanOptions,(ssize_t) image->matte));
+      CommandOptionToMnemonic(MagickPixelTraitOptions,(ssize_t)
+      image->alpha_trait));
     (void) WriteBlobString(image,buffer);
     (void) FormatLocaleString(buffer,MaxTextExtent,"columns=%.20g  rows=%.20g  "
       "depth=%.20g\n",(double) image->columns,(double) image->rows,(double)
@@ -1991,6 +2076,19 @@ static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
           CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace));
         (void) WriteBlobString(image,buffer);
       }
+    if (image->intensity != UndefinedPixelIntensityMethod)
+      {
+        (void) FormatLocaleString(buffer,MaxTextExtent,"pixel-intensity=%s\n",
+          CommandOptionToMnemonic(MagickPixelIntensityOptions,
+          image->intensity));
+        (void) WriteBlobString(image,buffer);
+      }
+    if (image->endian != UndefinedEndian)
+      {
+        (void) FormatLocaleString(buffer,MaxTextExtent,"endian=%s\n",
+          CommandOptionToMnemonic(MagickEndianOptions,image->endian));
+        (void) WriteBlobString(image,buffer);
+      }
     if (compression != UndefinedCompression)
       {
         (void) FormatLocaleString(buffer,MaxTextExtent,"compression=%s  "
@@ -2163,14 +2261,29 @@ static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,
       value=GetImageProperty(image,property,exception);
       if (value != (const char *) NULL)
         {
-          for (i=0; i < (ssize_t) strlen(value); i++)
+          size_t
+            length;
+
+          length=strlen(value);
+          for (i=0; i < (ssize_t) length; i++)
             if (isspace((int) ((unsigned char) value[i])) != 0)
               break;
-          if (i <= (ssize_t) strlen(value))
-            (void) WriteBlobByte(image,'{');
-          (void) WriteBlob(image,strlen(value),(const unsigned char *) value);
-          if (i <= (ssize_t) strlen(value))
-            (void) WriteBlobByte(image,'}');
+          if ((i == (ssize_t) length) && (i != 0))
+            (void) WriteBlob(image,length,(const unsigned char *) value);
+          else
+            {
+              (void) WriteBlobByte(image,'{');
+              if (strchr(value,'}') == (char *) NULL)
+                (void) WriteBlob(image,length,(const unsigned char *) value);
+              else
+                for (i=0; i < (ssize_t) length; i++)
+                {
+                  if (value[i] == (int) '}')
+                    (void) WriteBlobByte(image,'\\');
+                  (void) WriteBlobByte(image,value[i]);
+                }
+              (void) WriteBlobByte(image,'}');
+            }
         }
       (void) WriteBlobByte(image,'\n');
       property=GetNextImageProperty(image);