]> granicus.if.org Git - imagemagick/blobdiff - coders/mat.c
...
[imagemagick] / coders / mat.c
index 0d426ec15e6e0998f1d7c6900043e329d6322acb..0f9a5f44843b50b99372eae1ec798b3e703e4d2c 100644 (file)
@@ -66,6 +66,7 @@
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/pixel-accessor.h"
+#include "MagickCore/quantum.h"
 #include "MagickCore/quantum-private.h"
 #include "MagickCore/option.h"
 #include "MagickCore/pixel.h"
@@ -97,20 +98,20 @@ typedef struct
   char identific[124];
   unsigned short Version;
   char EndianIndicator[2];
-  unsigned long DataType;
-  unsigned long ObjectSize;
-  unsigned long unknown1;
-  unsigned long unknown2;
+  unsigned int DataType;
+  unsigned int ObjectSize;
+  unsigned int unknown1;
+  unsigned int unknown2;
 
   unsigned short unknown5;
   unsigned char StructureFlag;
   unsigned char StructureClass;
-  unsigned long unknown3;
-  unsigned long unknown4;
-  unsigned long DimFlag;
+  unsigned int unknown3;
+  unsigned int unknown4;
+  unsigned int DimFlag;
 
-  unsigned long SizeX;
-  unsigned long SizeY;
+  unsigned int SizeX;
+  unsigned int SizeY;
   unsigned short Flag1;
   unsigned short NameFlag;
 }
@@ -119,7 +120,7 @@ MATHeader;
 static const char *MonthsTab[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
 static const char *DayOfWTab[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
 static const char *OsDesc=
-#ifdef __WIN32__
+#if defined(MAGICKCORE_WINDOWS_SUPPORT)
     "PCWIN";
 #else
  #ifdef __APPLE__
@@ -177,18 +178,16 @@ typedef enum
 
 static const QuantumType z2qtype[4] = {GrayQuantum, BlueQuantum, GreenQuantum, RedQuantum};
 
-
 static void InsertComplexDoubleRow(Image *image,double *p,int y,double MinVal,
   double MaxVal,ExceptionInfo *exception)
 {
-
   double f;
   int x;
   register Quantum *q;
 
-  if (MinVal == 0)
+  if (MinVal >= 0)
     MinVal = -1;
-  if (MaxVal == 0)
+  if (MaxVal <= 0)
     MaxVal = 1;
 
   q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
@@ -197,50 +196,51 @@ static void InsertComplexDoubleRow(Image *image,double *p,int y,double MinVal,
   for (x = 0; x < (ssize_t) image->columns; x++)
   {
     if (*p > 0)
-    {
-      f = (*p / MaxVal) * (QuantumRange-GetPixelRed(image,q));
-      if (f + GetPixelRed(image,q) > QuantumRange)
-        SetPixelRed(image,QuantumRange,q);
-      else
-        SetPixelRed(image,GetPixelRed(image,q)+(int) f,q);
-      if ((int) f / 2.0 > GetPixelGreen(image,q))
-        {
-          SetPixelGreen(image,0,q);
-          SetPixelBlue(image,0,q);
-        }
-      else
-        {
-          SetPixelBlue(image,GetPixelBlue(image,q)-(int) (f/2.0),q);
-          SetPixelGreen(image,GetPixelBlue(image,q),q);
-        }
-    }
+      {
+        f=(*p/MaxVal)*(Quantum) (QuantumRange-GetPixelRed(image,q));
+        if ((f+GetPixelRed(image,q)) >= QuantumRange)
+          SetPixelRed(image,QuantumRange,q);
+        else
+          SetPixelRed(image,GetPixelRed(image,q)+ClampToQuantum(f),q);
+        f=GetPixelGreen(image,q)-f/2.0;
+        if (f <= 0.0)
+          {
+            SetPixelGreen(image,0,q);
+            SetPixelBlue(image,0,q);
+          }
+        else
+          {
+            SetPixelBlue(image,ClampToQuantum(f),q);
+            SetPixelGreen(image,ClampToQuantum(f),q);
+          }
+      }
     if (*p < 0)
-    {
-      f = (*p / MaxVal) * (QuantumRange-GetPixelBlue(image,q));
-      if (f+GetPixelBlue(image,q) > QuantumRange)
-        SetPixelBlue(image,QuantumRange,q);
-      else
-        SetPixelBlue(image,GetPixelBlue(image,q)+(int) f,q);
-      if ((int) f / 2.0 > GetPixelGreen(image,q))
-        {
-          SetPixelRed(image,0,q);
-          SetPixelGreen(image,0,q);
-        }
-      else
-        {
-          SetPixelRed(image,GetPixelRed(image,q)-(int) (f/2.0),q);
-          SetPixelGreen(image,GetPixelRed(image,q),q);
-        }
-    }
+      {
+        f=(*p/MinVal)*(Quantum) (QuantumRange-GetPixelBlue(image,q));
+        if ((f+GetPixelBlue(image,q)) >= QuantumRange)
+          SetPixelBlue(image,QuantumRange,q);
+        else
+          SetPixelBlue(image,GetPixelBlue(image,q)+ClampToQuantum(f),q);
+        f=GetPixelGreen(image,q)-f/2.0;
+        if (f <= 0.0)
+          {
+            SetPixelRed(image,0,q);
+            SetPixelGreen(image,0,q);
+          }
+        else
+          {
+            SetPixelRed(image,ClampToQuantum(f),q);
+            SetPixelGreen(image,ClampToQuantum(f),q);
+          }
+      }
     p++;
-    q+=GetPixelChannels(image);
+    q++;
   }
   if (!SyncAuthenticPixels(image,exception))
     return;
   return;
 }
 
-
 static void InsertComplexFloatRow(Image *image,float *p,int y,double MinVal,
   double MaxVal,ExceptionInfo *exception)
 {
@@ -248,9 +248,9 @@ static void InsertComplexFloatRow(Image *image,float *p,int y,double MinVal,
   int x;
   register Quantum *q;
 
-  if (MinVal == 0)
+  if (MinVal >= 0)
     MinVal = -1;
-  if (MaxVal == 0)
+  if (MaxVal <= 0)
     MaxVal = 1;
 
   q = QueueAuthenticPixels(image, 0, y, image->columns, 1,exception);
@@ -259,42 +259,43 @@ static void InsertComplexFloatRow(Image *image,float *p,int y,double MinVal,
   for (x = 0; x < (ssize_t) image->columns; x++)
   {
     if (*p > 0)
-    {
-      f = (*p / MaxVal) * (QuantumRange-GetPixelRed(image,q));
-      if (f+GetPixelRed(image,q) > QuantumRange)
-        SetPixelRed(image,QuantumRange,q);
-      else
-        SetPixelRed(image,GetPixelRed(image,q)+(int) f,q);
-      if ((int) f / 2.0 > GetPixelGreen(image,q))
-        {
-          SetPixelGreen(image,0,q);
-          SetPixelBlue(image,0,q);
-        }
-      else
-        {
-          SetPixelBlue(image,GetPixelBlue(image,q)-(int) (f/2.0),q);
-          SetPixelGreen(image,GetPixelBlue(image,q),q);
-        }
-    }
+      {
+        f=(*p/MaxVal)*(Quantum) (QuantumRange-GetPixelRed(image,q));
+        if ((f+GetPixelRed(image,q)) < QuantumRange)
+          SetPixelRed(image,GetPixelRed(image,q)+ClampToQuantum(f),q);
+        else
+          SetPixelRed(image,QuantumRange,q);
+        f/=2.0;
+        if (f < GetPixelGreen(image,q))
+          {
+            SetPixelBlue(image,GetPixelBlue(image,q)-ClampToQuantum(f),q);
+            SetPixelGreen(image,GetPixelBlue(image,q),q);
+          }
+        else
+          {
+            SetPixelGreen(image,0,q);
+            SetPixelBlue(image,0,q);
+          }
+      }
     if (*p < 0)
-    {
-      f = (*p / MaxVal) * (QuantumRange - GetPixelBlue(image,q));
-      if (f + GetPixelBlue(image,q) > QuantumRange)
-        SetPixelBlue(image,QuantumRange,q);
-      else
-        SetPixelBlue(image,GetPixelBlue(image,q)+
-          (int) f,q);
-      if ((int) f / 2.0 > GetPixelGreen(image,q))
-        {
-          SetPixelGreen(image,0,q);
-          SetPixelRed(image,0,q);
-        }
-      else
-        {
-          SetPixelRed(image,GetPixelRed(image,q)-(int) (f/2.0),q);
-          SetPixelGreen(image,GetPixelRed(image,q),q);
-        }
-    }
+      {
+        f=(*p/MaxVal)*(Quantum) (QuantumRange-GetPixelBlue(image,q));
+        if ((f > 0) && ((f+GetPixelBlue(image,q)) < QuantumRange))
+          SetPixelBlue(image,GetPixelBlue(image,q)+ClampToQuantum(f),q);
+        else
+          SetPixelBlue(image,QuantumRange,q);
+        f/=2.0;
+        if (f < GetPixelGreen(image,q))
+          {
+            SetPixelRed(image,GetPixelRed(image,q)-ClampToQuantum(f),q);
+            SetPixelGreen(image,GetPixelRed(image,q),q);
+          }
+        else
+          {
+            SetPixelGreen(image,0,q);
+            SetPixelRed(image,0,q);
+          }
+      }
     p++;
     q++;
   }
@@ -363,14 +364,14 @@ double *dblrow;
 float *fltrow;
 
   if (endian_indicator == LSBEndian)
-  {    
+  {
     ReadBlobDoublesXXX = ReadBlobDoublesLSB;
-    ReadBlobFloatsXXX = ReadBlobFloatsLSB;   
-  } 
+    ReadBlobFloatsXXX = ReadBlobFloatsLSB;
+  }
   else    /* MI */
-  {    
+  {
     ReadBlobDoublesXXX = ReadBlobDoublesMSB;
-    ReadBlobFloatsXXX = ReadBlobFloatsMSB;   
+    ReadBlobFloatsXXX = ReadBlobFloatsMSB;
   }
 
   filepos = TellBlob(image);     /* Please note that file seeking occurs only in the case of doubles */
@@ -420,7 +421,7 @@ static void FixSignedValues(const Image *image,Quantum *q, int y)
   while(y-->0)
   {
      /* Please note that negative values will overflow
-        Q=8; QuantumRange=255: <0;127> + 127+1 = <128; 255> 
+        Q=8; QuantumRange=255: <0;127> + 127+1 = <128; 255>
            <-1;-128> + 127+1 = <0; 127> */
     SetPixelRed(image,GetPixelRed(image,q)+QuantumRange/2+1,q);
     SetPixelGreen(image,GetPixelGreen(image,q)+QuantumRange/2+1,q);
@@ -440,7 +441,7 @@ unsigned char val = 0;
   while(ldblk-->0)
   {
     if(*Buff++ != 0)
-      val |= mask;    
+      val |= mask;
 
     mask >>= 1;
     if(mask==0)
@@ -448,8 +449,8 @@ unsigned char val = 0;
       *BuffL++ = val;
       val = 0;
       mask = 128;
-    }   
-      
+    }
+
   }
   *BuffL = val;
 }
@@ -471,11 +472,11 @@ static void RelinquishZIPMemory(voidpf context,voidpf memory)
 
 #if defined(MAGICKCORE_ZLIB_DELEGATE)
 /** This procedure decompreses an image block for a new MATLAB format. */
-static Image *DecompressBlock(Image *orig, MagickOffsetType Size, ImageInfo *clone_info, ExceptionInfo *exception)
+static Image *decompress_block(Image *orig, unsigned int *Size, ImageInfo *clone_info, ExceptionInfo *exception)
 {
 
 Image *image2;
-void *CacheBlock, *DecompressBlock;
+void *cache_block, *decompress_block;
 z_stream zip_info;
 FILE *mat_file;
 size_t magick_size;
@@ -483,6 +484,8 @@ size_t extent;
 int file;
 
 int status;
+int zip_status;
+ssize_t TotalSize = 0;
 
   if(clone_info==NULL) return NULL;
   if(clone_info->file)    /* Close file opened from previous transaction. */
@@ -492,12 +495,12 @@ int status;
     (void) remove_utf8(clone_info->filename);
   }
 
-  CacheBlock = AcquireQuantumMemory((size_t)((Size<16384)?Size:16384),sizeof(unsigned char *));
-  if(CacheBlock==NULL) return NULL;
-  DecompressBlock = AcquireQuantumMemory((size_t)(4096),sizeof(unsigned char *));
-  if(DecompressBlock==NULL) 
+  cache_block = AcquireQuantumMemory((size_t)(*Size < 16384) ? *Size: 16384,sizeof(unsigned char *));
+  if(cache_block==NULL) return NULL;
+  decompress_block = AcquireQuantumMemory((size_t)(4096),sizeof(unsigned char *));
+  if(decompress_block==NULL)
   {
-    RelinquishMagickMemory(CacheBlock);    
+    RelinquishMagickMemory(cache_block);
     return NULL;
   }
 
@@ -507,62 +510,325 @@ int status;
     mat_file = fdopen(file,"w");
   if(!mat_file)
   {
-    RelinquishMagickMemory(CacheBlock);
-    RelinquishMagickMemory(DecompressBlock);
-    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Gannot create file stream for PS image");
+    RelinquishMagickMemory(cache_block);
+    RelinquishMagickMemory(decompress_block);
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Cannot create file stream for decompressed image");
     return NULL;
   }
 
   zip_info.zalloc=AcquireZIPMemory;
   zip_info.zfree=RelinquishZIPMemory;
   zip_info.opaque = (voidpf) NULL;
-  inflateInit(&zip_info);
+  zip_status = inflateInit(&zip_info);
+  if (zip_status != Z_OK)
+    {
+      RelinquishMagickMemory(cache_block);
+      RelinquishMagickMemory(decompress_block);
+      (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
+        "UnableToUncompressImage","`%s'",clone_info->filename);
+      (void) fclose(mat_file);
+      RelinquishUniqueFileResource(clone_info->filename);
+      return NULL;
+    }
   /* zip_info.next_out = 8*4;*/
 
   zip_info.avail_in = 0;
   zip_info.total_out = 0;
-  while(Size>0 && !EOFBlob(orig))
-  {    
-    magick_size = ReadBlob(orig, (Size<16384)?Size:16384, (unsigned char *) CacheBlock);
-    zip_info.next_in = (Bytef *) CacheBlock;
-    zip_info.avail_in = (uInt) magick_size;    
+  while(*Size>0 && !EOFBlob(orig))
+  {
+    magick_size = ReadBlob(orig, (*Size < 16384) ? *Size : 16384, (unsigned char *) cache_block);
+    if (magick_size == 0)
+      break;
+    zip_info.next_in = (Bytef *) cache_block;
+    zip_info.avail_in = (uInt) magick_size;
 
     while(zip_info.avail_in>0)
     {
-      zip_info.avail_out = 4096;    
-      zip_info.next_out = (Bytef *) DecompressBlock;
-      status = inflate(&zip_info,Z_NO_FLUSH);      
-      extent=fwrite(DecompressBlock, 4096-zip_info.avail_out, 1, mat_file);
+      zip_info.avail_out = 4096;
+      zip_info.next_out = (Bytef *) decompress_block;
+      zip_status = inflate(&zip_info,Z_NO_FLUSH);
+      if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END))
+        break;
+      extent=fwrite(decompress_block, 4096-zip_info.avail_out, 1, mat_file);
       (void) extent;
+      TotalSize += 4096-zip_info.avail_out;
 
-      if(status == Z_STREAM_END) goto DblBreak;
+      if(zip_status == Z_STREAM_END) goto DblBreak;
     }
+    if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END))
+      break;
 
-    Size -= magick_size;
+    *Size -= (unsigned int) magick_size;
   }
 DblBreak:
+
+  inflateEnd(&zip_info);
   (void)fclose(mat_file);
-  RelinquishMagickMemory(CacheBlock);
-  RelinquishMagickMemory(DecompressBlock);
+  RelinquishMagickMemory(cache_block);
+  RelinquishMagickMemory(decompress_block);
+  *Size = TotalSize;
 
   if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) goto UnlinkFile;
-  if( (image2 = AcquireImage(clone_info,exception))==NULL ) goto EraseFile;  
+  if( (image2 = AcquireImage(clone_info,exception))==NULL ) goto EraseFile;
   status = OpenBlob(clone_info,image2,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
   {
-    DeleteImageFromList(&image2);    
+    DeleteImageFromList(&image2);
 EraseFile:
     fclose(clone_info->file);
     clone_info->file = NULL;
 UnlinkFile:
-    (void) remove_utf8(clone_info->filename);
-    return NULL; 
+    RelinquishUniqueFileResource(clone_info->filename);
+    return NULL;
   }
 
   return image2;
 }
 #endif
+
+static Image *ReadMATImageV4(const ImageInfo *image_info,Image *image,
+  ExceptionInfo *exception)
+{
+  typedef struct {
+    unsigned char Type[4];
+    unsigned int nRows;
+    unsigned int nCols;
+    unsigned int imagf;
+    unsigned int nameLen;
+  } MAT4_HDR;
+
+  long
+    ldblk;
+
+  EndianType
+    endian;
+
+  Image
+    *rotated_image;
+
+  MagickBooleanType
+    status;
+
+  MAT4_HDR
+    HDR;
+
+  QuantumInfo
+    *quantum_info;
+
+  QuantumFormatType
+    format_type;
+
+  register ssize_t
+    i;
+
+  ssize_t
+    count,
+    y;
+
+  unsigned char
+    *pixels;
+
+  unsigned int
+    depth;
+
+  quantum_info=(QuantumInfo *) NULL;
+  (void) SeekBlob(image,0,SEEK_SET);
+  status=MagickTrue;
+  while (EOFBlob(image) == MagickFalse)
+  {
+    /*
+     Object parser loop.
+    */
+    ldblk=ReadBlobLSBLong(image);
+    if ((ldblk > 9999) || (ldblk < 0))
+      break;
+    HDR.Type[3]=ldblk % 10; ldblk /= 10;  /* T digit */
+    HDR.Type[2]=ldblk % 10; ldblk /= 10;  /* P digit */
+    HDR.Type[1]=ldblk % 10; ldblk /= 10;  /* O digit */
+    HDR.Type[0]=ldblk;        /* M digit */
+    if (HDR.Type[3] != 0)
+      break;  /* Data format */
+    if (HDR.Type[2] != 0)
+      break;  /* Always 0 */
+    if (HDR.Type[0] == 0)
+      {
+        HDR.nRows=ReadBlobLSBLong(image);
+        HDR.nCols=ReadBlobLSBLong(image);
+        HDR.imagf=ReadBlobLSBLong(image);
+        HDR.nameLen=ReadBlobLSBLong(image);
+        endian=LSBEndian;
+      }
+    else
+      {
+        HDR.nRows=ReadBlobMSBLong(image);
+        HDR.nCols=ReadBlobMSBLong(image);
+        HDR.imagf=ReadBlobMSBLong(image);
+        HDR.nameLen=ReadBlobMSBLong(image);
+        endian=MSBEndian;
+      }
+    if ((HDR.imagf != 0) && (HDR.imagf != 1))
+      break;
+    if (HDR.nameLen > 0xFFFF)
+      return(DestroyImageList(image));
+    for (i=0; i < (ssize_t) HDR.nameLen; i++)
+    {
+      int
+        byte;
+
+      /*
+        Skip matrix name.
+      */
+      byte=ReadBlobByte(image);
+      if (byte == EOF)
+        {
+          ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
+            image->filename);
+          break;
+        }
+    }
+    image->columns=(size_t) HDR.nRows;
+    image->rows=(size_t) HDR.nCols;
+    if ((image->columns == 0) || (image->rows == 0))
+      return(DestroyImageList(image));
+    if (image_info->ping != MagickFalse)
+      {
+        Swap(image->columns,image->rows);
+        if(HDR.imagf==1) ldblk *= 2;
+        SeekBlob(image, HDR.nCols*ldblk, SEEK_CUR);
+        if ((image->columns == 0) || (image->rows == 0))
+          return(image->previous == (Image *) NULL ? DestroyImageList(image)
+            : image);
+        goto skip_reading_current;
+      }
+    status=SetImageExtent(image,image->columns,image->rows,exception);
+    if (status == MagickFalse)
+      return(DestroyImageList(image));
+    (void) SetImageBackgroundColor(image,exception);
+    (void) SetImageColorspace(image,GRAYColorspace,exception);
+    quantum_info=AcquireQuantumInfo(image_info,image);
+    if (quantum_info == (QuantumInfo *) NULL)
+      return(DestroyImageList(image));
+    switch(HDR.Type[1])
+    {
+      case 0:
+        format_type=FloatingPointQuantumFormat;
+        depth=64;
+        break;
+      case 1:
+        format_type=FloatingPointQuantumFormat;
+        depth=32;
+        break;
+      case 2:
+        format_type=UnsignedQuantumFormat;
+        depth=16;
+        break;
+      case 3:
+        format_type=SignedQuantumFormat;
+        depth=16;
+        break;
+      case 4:
+        format_type=UnsignedQuantumFormat;
+        depth=8;
+        break;
+      default:
+        format_type=UnsignedQuantumFormat;
+        depth=8;
+        break;
+    }
+    image->depth=depth;
+    if (HDR.Type[0] != 0)
+      SetQuantumEndian(image,quantum_info,MSBEndian);
+    status=SetQuantumFormat(image,quantum_info,format_type);
+    status=SetQuantumDepth(image,quantum_info,depth);
+    status=SetQuantumEndian(image,quantum_info,endian);
+    SetQuantumScale(quantum_info,1.0);
+    pixels=(unsigned char *) GetQuantumPixels(quantum_info);
+    for (y=0; y < (ssize_t) image->rows; y++)
+    {
+      register Quantum
+        *magick_restrict q;
+
+      count=ReadBlob(image,depth/8*image->columns,(char *) pixels);
+      if (count == -1)
+        break;
+      q=QueueAuthenticPixels(image,0,image->rows-y-1,image->columns,1,
+        exception);
+      if (q == (Quantum *) NULL)
+        break;
+      (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
+        GrayQuantum,pixels,exception);
+      if ((HDR.Type[1] == 2) || (HDR.Type[1] == 3))
+        FixSignedValues(image,q,(int) image->columns);
+      if (SyncAuthenticPixels(image,exception) == MagickFalse)
+        break;
+      if (image->previous == (Image *) NULL)
+        {
+          status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
+            image->rows);
+          if (status == MagickFalse)
+            break;
+        }
+    }
+    if (HDR.imagf == 1)
+      for (y=0; y < (ssize_t) image->rows; y++)
+      {
+        /*
+          Read complex pixels.
+        */
+        count=ReadBlob(image,depth/8*image->columns,(char *) pixels);
+        if (count == -1)
+          break;
+        if (HDR.Type[1] == 0)
+          InsertComplexDoubleRow(image,(double *) pixels,y,0,0,exception);
+        else
+          InsertComplexFloatRow(image,(float *) pixels,y,0,0,exception);
+      }
+    if (quantum_info != (QuantumInfo *) NULL)
+      quantum_info=DestroyQuantumInfo(quantum_info);
+    if (EOFBlob(image) != MagickFalse)
+      {
+        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
+          image->filename);
+        break;
+      }
+    rotated_image=RotateImage(image,90.0,exception);
+    if (rotated_image != (Image *) NULL)
+      {
+        rotated_image->page.x=0;
+        rotated_image->page.y=0;
+        rotated_image->colors = image->colors;
+        DestroyBlob(rotated_image);
+        rotated_image->blob=ReferenceBlob(image->blob);
+        AppendImageToList(&image,rotated_image);
+        DeleteImageFromList(&image);
+      }
+    /*
+      Proceed to next image.
+    */
+    if (image_info->number_scenes != 0)
+      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
+        break;
+    /*
+      Allocate next image structure.
+    */
+skip_reading_current:
+    AcquireNextImage(image_info,image,exception);
+    if (GetNextImageInList(image) == (Image *) NULL)
+      {
+        status=MagickFalse;
+        break;
+      }
+    image=SyncNextImageInList(image);
+    status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
+      GetBlobSize(image));
+    if (status == MagickFalse)
+      break;
+  }
+  (void) CloseBlob(image);
+  if (status == MagickFalse)
+    return(DestroyImageList(image));
+  return(GetFirstImageInList(image));
+}
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -594,14 +860,6 @@ UnlinkFile:
 %    o exception: return any errors or warnings in this structure.
 %
 */
-
-static inline size_t MagickMin(const size_t x,const size_t y)
-{
-  if (x < y)
-    return(x);
-  return(y);
-}
-
 static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
   Image *image, *image2=NULL,
@@ -610,7 +868,7 @@ static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
   unsigned int status;
   MATHeader MATLAB_HDR;
-  size_t size;  
+  size_t size;
   size_t CellType;
   QuantumInfo *quantum_info;
   ImageInfo *clone_info;
@@ -623,9 +881,7 @@ static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
   int logging;
   int sample_size;
   MagickOffsetType filepos=0x80;
-  BlobInfo *blob;
-  size_t one;
-  
+
   unsigned int (*ReadBlobXXXLong)(Image *image);
   unsigned short (*ReadBlobXXXShort)(Image *image);
   void (*ReadBlobDoublesXXX)(Image * image, size_t len, double *data);
@@ -633,15 +889,16 @@ static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
 
   assert(image_info != (const ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
+  assert(image_info->signature == MagickCoreSignature);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter"); 
+  assert(exception->signature == MagickCoreSignature);
+  logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter");
 
   /*
      Open image file.
    */
   image = AcquireImage(image_info,exception);
+  image2 = (Image *) NULL;
 
   status = OpenBlob(image_info, image, ReadBinaryBlobMode, exception);
   if (status == MagickFalse)
@@ -652,15 +909,30 @@ static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
   /*
      Read MATLAB image.
    */
-  clone_info=CloneImageInfo(image_info);
-  if(ReadBlob(image,124,(unsigned char *) &MATLAB_HDR.identific) != 124)
+  quantum_info=(QuantumInfo *) NULL;
+  clone_info=(ImageInfo *) NULL;
+  if (ReadBlob(image,124,(unsigned char *) &MATLAB_HDR.identific) != 124)
     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+  if (strncmp(MATLAB_HDR.identific,"MATLAB",6) != 0)
+    {
+      image=ReadMATImageV4(image_info,image,exception);
+      if (image == NULL)
+        {
+          if ((image != image2) && (image2 != (Image *) NULL))
+            image2=DestroyImage(image2);
+          if (clone_info != (ImageInfo *) NULL)
+            clone_info=DestroyImageInfo(clone_info);
+          return((Image *) NULL);
+        }
+      goto END_OF_READING;
+    }
   MATLAB_HDR.Version = ReadBlobLSBShort(image);
   if(ReadBlob(image,2,(unsigned char *) &MATLAB_HDR.EndianIndicator) != 2)
     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
 
-  if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"  Endian %c%c",
-        MATLAB_HDR.EndianIndicator[0],MATLAB_HDR.EndianIndicator[1]);
+  if (logging)
+    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Endian %c%c",
+      MATLAB_HDR.EndianIndicator[0],MATLAB_HDR.EndianIndicator[1]);
   if (!strncmp(MATLAB_HDR.EndianIndicator, "IM", 2))
   {
     ReadBlobXXXLong = ReadBlobLSBLong;
@@ -668,7 +940,7 @@ static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
     ReadBlobDoublesXXX = ReadBlobDoublesLSB;
     ReadBlobFloatsXXX = ReadBlobFloatsLSB;
     image->endian = LSBEndian;
-  } 
+  }
   else if (!strncmp(MATLAB_HDR.EndianIndicator, "MI", 2))
   {
     ReadBlobXXXLong = ReadBlobMSBLong;
@@ -677,43 +949,64 @@ static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
     ReadBlobFloatsXXX = ReadBlobFloatsMSB;
     image->endian = MSBEndian;
   }
-  else 
-    goto MATLAB_KO;    /* unsupported endian */
-
-  if (strncmp(MATLAB_HDR.identific, "MATLAB", 6))
-MATLAB_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+  else
+    {
+MATLAB_KO:
+      if ((image != image2) && (image2 != (Image *) NULL))
+        image2=DestroyImage(image2);
+      if (clone_info != (ImageInfo *) NULL)
+        clone_info=DestroyImageInfo(clone_info);
+      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+    }
 
   filepos = TellBlob(image);
   while(!EOFBlob(image)) /* object parser loop */
   {
     Frames = 1;
-    (void) SeekBlob(image,filepos,SEEK_SET);
+    if (filepos != (unsigned int) filepos)
+      break;
+    if(SeekBlob(image,filepos,SEEK_SET) != filepos) break;
     /* printf("pos=%X\n",TellBlob(image)); */
 
     MATLAB_HDR.DataType = ReadBlobXXXLong(image);
     if(EOFBlob(image)) break;
     MATLAB_HDR.ObjectSize = ReadBlobXXXLong(image);
     if(EOFBlob(image)) break;
-    filepos += MATLAB_HDR.ObjectSize + 4 + 4;
+    if((MagickSizeType) (MATLAB_HDR.ObjectSize+filepos) > GetBlobSize(image))
+      goto MATLAB_KO;
+    filepos += (MagickOffsetType) MATLAB_HDR.ObjectSize + 4 + 4;
 
+    if (clone_info != (ImageInfo *) NULL)
+      clone_info=DestroyImageInfo(clone_info);
+    clone_info=CloneImageInfo(image_info);
+    if ((image != image2) && (image2 != (Image *) NULL))
+      image2=DestroyImage(image2);
     image2 = image;
 #if defined(MAGICKCORE_ZLIB_DELEGATE)
     if(MATLAB_HDR.DataType == miCOMPRESSED)
     {
-      image2 = DecompressBlock(image,MATLAB_HDR.ObjectSize,clone_info,exception);
+      image2 = decompress_block(image,&MATLAB_HDR.ObjectSize,clone_info,exception);
       if(image2==NULL) continue;
       MATLAB_HDR.DataType = ReadBlobXXXLong(image2); /* replace compressed object type. */
     }
-#endif    
+#endif
+
+    if (MATLAB_HDR.DataType != miMATRIX)
+      {
+        clone_info=DestroyImageInfo(clone_info);
+#if defined(MAGICKCORE_ZLIB_DELEGATE)
+        if (image2 != image)
+          DeleteImageFromList(&image2);
+#endif
+        continue;  /* skip another objects. */
+      }
 
-    if(MATLAB_HDR.DataType!=miMATRIX) continue;  /* skip another objects. */
     MATLAB_HDR.unknown1 = ReadBlobXXXLong(image2);
-    MATLAB_HDR.unknown2 = ReadBlobXXXLong(image2);  
+    MATLAB_HDR.unknown2 = ReadBlobXXXLong(image2);
 
     MATLAB_HDR.unknown5 = ReadBlobXXXLong(image2);
     MATLAB_HDR.StructureClass = MATLAB_HDR.unknown5 & 0xFF;
-    MATLAB_HDR.StructureFlag = (MATLAB_HDR.unknown5>>8) & 0xFF;  
+    MATLAB_HDR.StructureFlag = (MATLAB_HDR.unknown5>>8) & 0xFF;
 
     MATLAB_HDR.unknown3 = ReadBlobXXXLong(image2);
     if(image!=image2)
@@ -721,30 +1014,66 @@ MATLAB_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
     MATLAB_HDR.unknown4 = ReadBlobXXXLong(image2);
     MATLAB_HDR.DimFlag = ReadBlobXXXLong(image2);
     MATLAB_HDR.SizeX = ReadBlobXXXLong(image2);
-    MATLAB_HDR.SizeY = ReadBlobXXXLong(image2);  
-   
+    MATLAB_HDR.SizeY = ReadBlobXXXLong(image2);
+
 
     switch(MATLAB_HDR.DimFlag)
-    {     
+    {
       case  8: z2=z=1; break;      /* 2D matrix*/
       case 12: z2=z = ReadBlobXXXLong(image2);  /* 3D matrix RGB*/
            (void) ReadBlobXXXLong(image2);
-         if(z!=3) ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported");
+         if(z!=3)
+           {
+             if (clone_info != (ImageInfo *) NULL)
+               clone_info=DestroyImageInfo(clone_info);
+             if ((image != image2) && (image2 != (Image *) NULL))
+               image2=DestroyImage(image2);
+             ThrowReaderException(CoderError,
+               "MultidimensionalMatricesAreNotSupported");
+           }
          break;
       case 16: z2=z = ReadBlobXXXLong(image2);  /* 4D matrix animation */
          if(z!=3 && z!=1)
-            ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported");
-           Frames = ReadBlobXXXLong(image2);
+           {
+             if (clone_info != (ImageInfo *) NULL)
+               clone_info=DestroyImageInfo(clone_info);
+             if ((image != image2) && (image2 != (Image *) NULL))
+               image2=DestroyImage(image2);
+             ThrowReaderException(CoderError,
+               "MultidimensionalMatricesAreNotSupported");
+           }
+          Frames = ReadBlobXXXLong(image2);
+          if (Frames == 0)
+            {
+              if (clone_info != (ImageInfo *) NULL)
+                clone_info=DestroyImageInfo(clone_info);
+              if ((image != image2) && (image2 != (Image *) NULL))
+                image2=DestroyImage(image2);
+              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+            }
+          if (AcquireMagickResource(ListLengthResource,Frames) == MagickFalse)
+            {
+              if (clone_info != (ImageInfo *) NULL)
+                clone_info=DestroyImageInfo(clone_info);
+              if ((image != image2) && (image2 != (Image *) NULL))
+                image2=DestroyImage(image2);
+              ThrowReaderException(ResourceLimitError,"ListLengthExceedsLimit");
+            }
          break;
-      default: ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported");
-    }  
+      default:
+        if (clone_info != (ImageInfo *) NULL)
+          clone_info=DestroyImageInfo(clone_info);
+        if ((image != image2) && (image2 != (Image *) NULL))
+          image2=DestroyImage(image2);
+        ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported");
+    }
 
     MATLAB_HDR.Flag1 = ReadBlobXXXShort(image2);
     MATLAB_HDR.NameFlag = ReadBlobXXXShort(image2);
 
     if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
           "MATLAB_HDR.StructureClass %d",MATLAB_HDR.StructureClass);
-    if (MATLAB_HDR.StructureClass != mxCHAR_CLASS && 
+    if (MATLAB_HDR.StructureClass != mxCHAR_CLASS &&
         MATLAB_HDR.StructureClass != mxSINGLE_CLASS &&    /* float + complex float */
         MATLAB_HDR.StructureClass != mxDOUBLE_CLASS &&    /* double + complex double */
         MATLAB_HDR.StructureClass != mxINT8_CLASS &&
@@ -755,13 +1084,22 @@ MATLAB_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
         MATLAB_HDR.StructureClass != mxUINT32_CLASS &&    /* uint32 + uint32 3D */
         MATLAB_HDR.StructureClass != mxINT64_CLASS &&
         MATLAB_HDR.StructureClass != mxUINT64_CLASS)    /* uint64 + uint64 3D */
-      ThrowReaderException(CoderError,"UnsupportedCellTypeInTheMatrix");
+      {
+        if ((image2 != (Image*) NULL) && (image2 != image))
+          {
+            CloseBlob(image2);
+            DeleteImageFromList(&image2);
+          }
+        if (clone_info != (ImageInfo *) NULL)
+          clone_info=DestroyImageInfo(clone_info);
+        ThrowReaderException(CoderError,"UnsupportedCellTypeInTheMatrix");
+      }
 
     switch (MATLAB_HDR.NameFlag)
     {
       case 0:
         size = ReadBlobXXXLong(image2);  /* Object name string size */
-        size = 4 * (ssize_t) ((size + 3 + 1) / 4);
+        size = 4 * (((size_t) size + 3 + 1) / 4);
         (void) SeekBlob(image2, size, SEEK_CUR);
         break;
       case 1:
@@ -778,8 +1116,10 @@ MATLAB_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
     if (logging)
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
         "MATLAB_HDR.CellType: %.20g",(double) CellType);
-  
-    (void) ReadBlob(image2, 4, (unsigned char *) &size);     /* data size */
+
+    /* data size */
+    if (ReadBlob(image2, 4, (unsigned char *) &size) != 4)
+      goto MATLAB_KO;
 
     NEXT_FRAME:
     switch (CellType)
@@ -787,11 +1127,11 @@ MATLAB_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
       case miINT8:
       case miUINT8:
         sample_size = 8;
-        if(MATLAB_HDR.StructureFlag & FLAG_LOGICAL) 
+        if(MATLAB_HDR.StructureFlag & FLAG_LOGICAL)
           image->depth = 1;
         else
           image->depth = 8;         /* Byte type cell */
-        ldblk = (ssize_t) MATLAB_HDR.SizeX;      
+        ldblk = (ssize_t) MATLAB_HDR.SizeX;
         break;
       case miINT16:
       case miUINT16:
@@ -803,49 +1143,57 @@ MATLAB_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
       case miUINT32:
         sample_size = 32;
         image->depth = 32;        /* Dword type cell */
-        ldblk = (ssize_t) (4 * MATLAB_HDR.SizeX);      
+        ldblk = (ssize_t) (4 * MATLAB_HDR.SizeX);
         break;
       case miINT64:
       case miUINT64:
         sample_size = 64;
         image->depth = 64;        /* Qword type cell */
-        ldblk = (ssize_t) (8 * MATLAB_HDR.SizeX);      
-        break;   
+        ldblk = (ssize_t) (8 * MATLAB_HDR.SizeX);
+        break;
       case miSINGLE:
         sample_size = 32;
         image->depth = 32;        /* double type cell */
         (void) SetImageOption(clone_info,"quantum:format","floating-point");
         if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX)
-  {              /* complex float type cell */
-  }
+          {              /* complex float type cell */
+          }
         ldblk = (ssize_t) (4 * MATLAB_HDR.SizeX);
         break;
       case miDOUBLE:
-        sample_size = 64; 
+        sample_size = 64;
         image->depth = 64;        /* double type cell */
         (void) SetImageOption(clone_info,"quantum:format","floating-point");
 DisableMSCWarning(4127)
         if (sizeof(double) != 8)
 RestoreMSCWarning
-          ThrowReaderException(CoderError, "IncompatibleSizeOfDouble");
+          {
+            if (clone_info != (ImageInfo *) NULL)
+              clone_info=DestroyImageInfo(clone_info);
+            if ((image != image2) && (image2 != (Image *) NULL))
+              image2=DestroyImage(image2);
+            ThrowReaderException(CoderError, "IncompatibleSizeOfDouble");
+          }
         if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX)
-  {                         /* complex double type cell */        
-  }
+          {                         /* complex double type cell */
+          }
         ldblk = (ssize_t) (8 * MATLAB_HDR.SizeX);
         break;
       default:
+        if ((image != image2) && (image2 != (Image *) NULL))
+          image2=DestroyImage(image2);
+        if (clone_info)
+          clone_info=DestroyImageInfo(clone_info);
         ThrowReaderException(CoderError, "UnsupportedCellTypeInTheMatrix");
     }
     (void) sample_size;
     image->columns = MATLAB_HDR.SizeX;
-    image->rows = MATLAB_HDR.SizeY;    
-    quantum_info=AcquireQuantumInfo(clone_info,image);
-    if (quantum_info == (QuantumInfo *) NULL)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-    one=1;
-    image->colors = one << image->depth;
+    image->rows = MATLAB_HDR.SizeY;
+    image->colors = GetQuantumRange(image->depth);
     if (image->columns == 0 || image->rows == 0)
       goto MATLAB_KO;
+    if((unsigned int)ldblk*MATLAB_HDR.SizeY > MATLAB_HDR.ObjectSize)
+      goto MATLAB_KO;
     /* Image is gray when no complex flag is set and 2D Matrix */
     if ((MATLAB_HDR.DimFlag == 8) &&
         ((MATLAB_HDR.StructureFlag & FLAG_COMPLEX) == 0))
@@ -865,19 +1213,49 @@ RestoreMSCWarning
       image->columns = image->rows;
       image->rows = temp;
       goto done_reading; /* !!!!!! BAD  !!!! */
-    }  
+    }
+    status=SetImageExtent(image,image->columns,image->rows,exception);
+    if (status == MagickFalse)
+      {
+        if (clone_info != (ImageInfo *) NULL)
+          clone_info=DestroyImageInfo(clone_info);
+        if ((image != image2) && (image2 != (Image *) NULL))
+          image2=DestroyImage(image2);
+        return(DestroyImageList(image));
+      }
+    (void) SetImageBackgroundColor(image,exception);
+    quantum_info=AcquireQuantumInfo(clone_info,image);
+    if (quantum_info == (QuantumInfo *) NULL)
+      {
+        if (clone_info != (ImageInfo *) NULL)
+          clone_info=DestroyImageInfo(clone_info);
+        if ((image != image2) && (image2 != (Image *) NULL))
+          image2=DestroyImage(image2);
+        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      }
 
   /* ----- Load raster data ----- */
-    BImgBuff = (unsigned char *) AcquireQuantumMemory((size_t) (ldblk),sizeof(unsigned char *));    /* Ldblk was set in the check phase */
+    BImgBuff = (unsigned char *) AcquireQuantumMemory((size_t) (ldblk),sizeof(double));    /* Ldblk was set in the check phase */
     if (BImgBuff == NULL)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      {
+        if (clone_info != (ImageInfo *) NULL)
+          clone_info=DestroyImageInfo(clone_info);
+        if ((image != image2) && (image2 != (Image *) NULL))
+          image2=DestroyImage(image2);
+        if (quantum_info != (QuantumInfo *) NULL)
+          quantum_info=DestroyQuantumInfo(quantum_info);
+        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      }
+    (void) memset(BImgBuff,0,ldblk*sizeof(double));
 
     MinVal = 0;
     MaxVal = 0;
     if (CellType==miDOUBLE || CellType==miSINGLE)        /* Find Min and Max Values for floats */
-    {
-      CalcMinMax(image2, image_info->endian,  MATLAB_HDR.SizeX, MATLAB_HDR.SizeY, CellType, ldblk, BImgBuff, &quantum_info->minimum, &quantum_info->maximum);
-    }
+      {
+        CalcMinMax(image2,image_info->endian,MATLAB_HDR.SizeX,MATLAB_HDR.SizeY,
+          CellType,ldblk,BImgBuff,&quantum_info->minimum,
+          &quantum_info->maximum);
+      }
 
     /* Main loop for reading all scanlines */
     if(z==1) z=0; /* read grey scanlines */
@@ -887,46 +1265,46 @@ RestoreMSCWarning
       for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++)
       {
         q=GetAuthenticPixels(image,0,MATLAB_HDR.SizeY-i-1,image->columns,1,exception);
-        if (q == (Quantum *)NULL)
-  {
-    if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+        if (q == (Quantum *) NULL)
+          {
+            if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
               "  MAT set image pixels returns unexpected NULL on a row %u.", (unsigned)(MATLAB_HDR.SizeY-i-1));
-    goto done_reading;    /* Skip image rotation, when cannot set image pixels    */
-  }
+            goto done_reading;    /* Skip image rotation, when cannot set image pixels    */
+          }
         if(ReadBlob(image2,ldblk,(unsigned char *)BImgBuff) != (ssize_t) ldblk)
-  {
-    if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
-             "  MAT cannot read scanrow %u from a file.", (unsigned)(MATLAB_HDR.SizeY-i-1));
-    goto ExitLoop;
-  }
+          {
+            if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+              "  MAT cannot read scanrow %u from a file.", (unsigned)(MATLAB_HDR.SizeY-i-1));
+            goto ExitLoop;
+          }
         if((CellType==miINT8 || CellType==miUINT8) && (MATLAB_HDR.StructureFlag & FLAG_LOGICAL))
         {
           FixLogical((unsigned char *)BImgBuff,ldblk);
           if(ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,z2qtype[z],BImgBuff,exception) <= 0)
-    {
+            {
 ImportQuantumPixelsFailed:
-      if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
-              "  MAT failed to ImportQuantumPixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1));
-      break;
-    }
+              if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+                "  MAT failed to ImportQuantumPixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1));
+              break;
+            }
         }
         else
         {
           if(ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,z2qtype[z],BImgBuff,exception) <= 0)
-      goto ImportQuantumPixelsFailed;
+            goto ImportQuantumPixelsFailed;
 
 
           if (z<=1 &&       /* fix only during a last pass z==0 || z==1 */
-          (CellType==miINT8 || CellType==miINT16 || CellType==miINT32 || CellType==miINT64))
-      FixSignedValues(image,q,MATLAB_HDR.SizeX);
+             (CellType==miINT8 || CellType==miINT16 || CellType==miINT32 || CellType==miINT64))
+            FixSignedValues(image,q,MATLAB_HDR.SizeX);
         }
 
         if (!SyncAuthenticPixels(image,exception))
-  {
-    if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
-            "  MAT failed to sync image pixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1));
-    goto ExitLoop;
-  }
+          {
+            if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+              "  MAT failed to sync image pixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1));
+            goto ExitLoop;
+          }
       }
     } while(z-- >= 2);
 ExitLoop:
@@ -940,24 +1318,24 @@ ExitLoop:
 
       if (CellType==miDOUBLE || CellType==miSINGLE)
       {
-        CalcMinMax(image2,  image_info->endian, MATLAB_HDR.SizeX, MATLAB_HDR.SizeY, CellType, ldblk, BImgBuff, &MinVal, &MaxVal);      
+        CalcMinMax(image2,  image_info->endian, MATLAB_HDR.SizeX, MATLAB_HDR.SizeY, CellType, ldblk, BImgBuff, &MinVal, &MaxVal);
       }
 
       if (CellType==miDOUBLE)
         for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++)
-  {
+        {
           ReadBlobDoublesXXX(image2, ldblk, (double *)BImgBuff);
           InsertComplexDoubleRow(image, (double *)BImgBuff, i, MinVal, MaxVal,
             exception);
-  }
+        }
 
       if (CellType==miSINGLE)
         for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++)
-  {
+        {
           ReadBlobFloatsXXX(image2, ldblk, (float *)BImgBuff);
           InsertComplexFloatRow(image,(float *)BImgBuff,i,MinVal,MaxVal,
             exception);
-  }    
+        }
     }
 
       /* Image is gray when no complex flag is set and 2D Matrix AGAIN!!! */
@@ -977,13 +1355,11 @@ ExitLoop:
         /* Remove page offsets added by RotateImage */
       rotated_image->page.x=0;
       rotated_image->page.y=0;
-
-      blob = rotated_image->blob;
-      rotated_image->blob = image->blob;
       rotated_image->colors = image->colors;
-      image->blob = blob;
-      AppendImageToList(&image,rotated_image);      
-      DeleteImageFromList(&image);      
+      DestroyBlob(rotated_image);
+      rotated_image->blob=ReferenceBlob(image->blob);
+      AppendImageToList(&image,rotated_image);
+      DeleteImageFromList(&image);
     }
 
 done_reading:
@@ -991,34 +1367,39 @@ done_reading:
     if(image2!=NULL)
       if(image2!=image)
       {
-        DeleteImageFromList(&image2); 
-  if(clone_info)
-  {
+        DeleteImageFromList(&image2);
+        if(clone_info)
+        {
           if(clone_info->file)
-    {
+          {
             fclose(clone_info->file);
             clone_info->file = NULL;
             (void) remove_utf8(clone_info->filename);
-    }
-        }    
+          }
+        }
       }
+    if (EOFBlob(image) != MagickFalse)
+      break;
 
-      /* Allocate next image structure. */    
+      /* Allocate next image structure. */
     AcquireNextImage(image_info,image,exception);
-    if (image->next == (Image *) NULL) break;                
+    if (image->next == (Image *) NULL) break;
     image=SyncNextImageInList(image);
     image->columns=image->rows=0;
-    image->colors=0;    
+    image->colors=0;
 
       /* row scan buffer is no longer needed */
     RelinquishMagickMemory(BImgBuff);
     BImgBuff = NULL;
+    if (quantum_info != (QuantumInfo *) NULL)
+      quantum_info=DestroyQuantumInfo(quantum_info);
 
     if(--Frames>0)
     {
       z = z2;
       if(image2==NULL) image2 = image;
-      goto NEXT_FRAME;
+      if(!EOFBlob(image) && TellBlob(image)<filepos)
+        goto NEXT_FRAME;
     }
     if ((image2!=NULL) && (image2!=image))   /* Does shadow temporary decompressed image exist? */
       {
@@ -1033,35 +1414,42 @@ done_reading:
             (void) remove_utf8(clone_info->filename);
           }
         }
-        }
+      }
+
+    if (clone_info)
+      clone_info=DestroyImageInfo(clone_info);
   }
 
-  clone_info=DestroyImageInfo(clone_info);
   RelinquishMagickMemory(BImgBuff);
+  if (quantum_info != (QuantumInfo *) NULL)
+    quantum_info=DestroyQuantumInfo(quantum_info);
+END_OF_READING:
   CloseBlob(image);
 
 
   {
-    Image *p;    
+    Image *p;
     ssize_t scene=0;
-    
+
     /*
       Rewind list, removing any empty images while rewinding.
     */
     p=image;
     image=NULL;
-    while (p != (Image *)NULL)
+    while (p != (Image *) NULL)
       {
         Image *tmp=p;
         if ((p->rows == 0) || (p->columns == 0)) {
           p=p->previous;
+          if (tmp == image2)
+            image2=(Image *) NULL;
           DeleteImageFromList(&tmp);
         } else {
           image=p;
           p=p->previous;
         }
       }
-    
+
     /*
       Fix scene numbers
     */
@@ -1081,9 +1469,11 @@ done_reading:
     clone_info = NULL;
   }
   if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return");
-  if(image==NULL)
-    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
-  return (image);
+  if ((image != image2) && (image2 != (Image *) NULL))
+    image2=DestroyImage(image2);
+  if (image == (Image *) NULL)
+    ThrowReaderException(CorruptImageError,"ImproperImageHeader")
+  return(image);
 }
 \f
 /*
@@ -1114,13 +1504,11 @@ ModuleExport size_t RegisterMATImage(void)
   MagickInfo
     *entry;
 
-  entry=SetMagickInfo("MAT");
+  entry=AcquireMagickInfo("MAT","MAT","MATLAB level 5 image format");
   entry->decoder=(DecodeImageHandler *) ReadMATImage;
   entry->encoder=(EncodeImageHandler *) WriteMATImage;
-  entry->blob_support=MagickFalse;
-  entry->seekable_stream=MagickTrue;
-  entry->description=AcquireString("MATLAB level 5 image format");
-  entry->module=AcquireString("MAT");
+  entry->flags^=CoderBlobSupportFlag;
+  entry->flags|=CoderDecoderSeekableStreamFlag;
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);
 }
@@ -1160,7 +1548,7 @@ ModuleExport void UnregisterMATImage(void)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  Function WriteMATImage writes an Matlab matrix to a file.  
+%  Function WriteMATImage writes an Matlab matrix to a file.
 %
 %  The format of the WriteMATImage method is:
 %
@@ -1179,37 +1567,34 @@ ModuleExport void UnregisterMATImage(void)
 static MagickBooleanType WriteMATImage(const ImageInfo *image_info,Image *image,
   ExceptionInfo *exception)
 {
-  ssize_t y;
-  unsigned z;
-  register const Quantum *p;
+  char
+    MATLAB_HDR[0x80];
 
-  unsigned int status;
-  int logging;
-  size_t DataSize;
-  char padding;
-  char MATLAB_HDR[0x80];
-  time_t current_time;
-  struct tm local_time;
-  unsigned char *pixels;
-  int is_gray;
+  MagickBooleanType
+    status;
 
   MagickOffsetType
     scene;
 
-  QuantumInfo
-    *quantum_info;
+  size_t
+    imageListLength;
+
+  struct tm
+    local_time;
+
+  time_t
+    current_time;
 
   /*
     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);
-  logging=LogMagickEvent(CoderEvent,GetMagickModule(),"enter MAT");
-  (void) logging;
+  assert(image->signature == MagickCoreSignature);
+  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"enter MAT");
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   if (status == MagickFalse)
     return(MagickFalse);
@@ -1233,39 +1618,60 @@ static MagickBooleanType WriteMATImage(const ImageInfo *image_info,Image *image,
   MATLAB_HDR[0x7F]='M';
   (void) WriteBlob(image,sizeof(MATLAB_HDR),(unsigned char *) MATLAB_HDR);
   scene=0;
+  imageListLength=GetImageListLength(image);
   do
   {
+    char
+      padding;
+
+    MagickBooleanType
+      is_gray;
+
+    QuantumInfo
+      *quantum_info;
+
+    size_t
+      data_size;
+
+    unsigned char
+      *pixels;
+
+    unsigned int
+      z;
+
     (void) TransformImageColorspace(image,sRGBColorspace,exception);
-    is_gray = IsImageGray(image,exception);
-    z = is_gray ? 0 : 3;
+    is_gray=SetImageGray(image,exception);
+    z=(is_gray != MagickFalse) ? 0 : 3;
 
     /*
       Store MAT header.
     */
-    DataSize = image->rows /*Y*/ * image->columns /*X*/;
-    if(!is_gray) DataSize *= 3 /*Z*/;
-    padding=((unsigned char)(DataSize-1) & 0x7) ^ 0x7;
-
-    (void) WriteBlobLSBLong(image, miMATRIX);
-    (void) WriteBlobLSBLong(image, (unsigned int) DataSize+padding+(is_gray ? 48 : 56));
-    (void) WriteBlobLSBLong(image, 0x6); /* 0x88 */
-    (void) WriteBlobLSBLong(image, 0x8); /* 0x8C */
-    (void) WriteBlobLSBLong(image, 0x6); /* 0x90 */  
-    (void) WriteBlobLSBLong(image, 0);   
-    (void) WriteBlobLSBLong(image, 0x5); /* 0x98 */
-    (void) WriteBlobLSBLong(image, is_gray ? 0x8 : 0xC); /* 0x9C - DimFlag */
-    (void) WriteBlobLSBLong(image, (unsigned int) image->rows);    /* x: 0xA0 */  
-    (void) WriteBlobLSBLong(image, (unsigned int) image->columns); /* y: 0xA4 */  
-    if(!is_gray)
-    {
-      (void) WriteBlobLSBLong(image, 3); /* z: 0xA8 */  
-      (void) WriteBlobLSBLong(image, 0);
-    }
-    (void) WriteBlobLSBShort(image, 1);  /* 0xB0 */  
-    (void) WriteBlobLSBShort(image, 1);  /* 0xB2 */
-    (void) WriteBlobLSBLong(image, 'M'); /* 0xB4 */
-    (void) WriteBlobLSBLong(image, 0x2); /* 0xB8 */  
-    (void) WriteBlobLSBLong(image, (unsigned int) DataSize); /* 0xBC */
+    data_size = image->rows * image->columns;
+    if (is_gray == MagickFalse)
+      data_size*=3;
+    padding=((unsigned char)(data_size-1) & 0x7) ^ 0x7;
+
+    (void) WriteBlobLSBLong(image,miMATRIX);
+    (void) WriteBlobLSBLong(image,(unsigned int) data_size+padding+
+      ((is_gray != MagickFalse) ? 48 : 56));
+    (void) WriteBlobLSBLong(image,0x6); /* 0x88 */
+    (void) WriteBlobLSBLong(image,0x8); /* 0x8C */
+    (void) WriteBlobLSBLong(image,0x6); /* 0x90 */
+    (void) WriteBlobLSBLong(image,0);
+    (void) WriteBlobLSBLong(image,0x5); /* 0x98 */
+    (void) WriteBlobLSBLong(image,(is_gray != MagickFalse) ? 0x8 : 0xC); /* 0x9C - DimFlag */
+    (void) WriteBlobLSBLong(image,(unsigned int) image->rows);    /* x: 0xA0 */
+    (void) WriteBlobLSBLong(image,(unsigned int) image->columns); /* y: 0xA4 */
+    if (is_gray == MagickFalse)
+      {
+        (void) WriteBlobLSBLong(image,3); /* z: 0xA8 */
+        (void) WriteBlobLSBLong(image,0);
+      }
+    (void) WriteBlobLSBShort(image,1);  /* 0xB0 */
+    (void) WriteBlobLSBShort(image,1);  /* 0xB2 */
+    (void) WriteBlobLSBLong(image,'M'); /* 0xB4 */
+    (void) WriteBlobLSBLong(image,0x2); /* 0xB8 */
+    (void) WriteBlobLSBLong(image,(unsigned int) data_size); /* 0xBC */
 
     /*
       Store image data.
@@ -1273,9 +1679,15 @@ static MagickBooleanType WriteMATImage(const ImageInfo *image_info,Image *image,
     quantum_info=AcquireQuantumInfo(image_info,image);
     if (quantum_info == (QuantumInfo *) NULL)
       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
-    pixels=GetQuantumPixels(quantum_info);
+    pixels=(unsigned char *) GetQuantumPixels(quantum_info);
     do
     {
+      const Quantum
+        *p;
+
+      ssize_t
+        y;
+
       for (y=0; y < (ssize_t)image->columns; y++)
       {
         p=GetVirtualPixels(image,y,0,1,image->rows,exception);
@@ -1284,20 +1696,20 @@ static MagickBooleanType WriteMATImage(const ImageInfo *image_info,Image *image,
         (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
           z2qtype[z],pixels,exception);
         (void) WriteBlob(image,image->rows,pixels);
-      }    
+      }
       if (SyncAuthenticPixels(image,exception) == MagickFalse)
         break;
-    } while(z-- >= 2);
-    while(padding-->0) (void) WriteBlobByte(image,0);
+    } while (z-- >= 2);
+    while (padding-- > 0)
+      (void) WriteBlobByte(image,0);
     quantum_info=DestroyQuantumInfo(quantum_info);
     if (GetNextImageInList(image) == (Image *) NULL)
       break;
     image=SyncNextImageInList(image);
-    status=SetImageProgress(image,SaveImagesTag,scene++,
-      GetImageListLength(image));
+    status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
     if (status == MagickFalse)
       break;
   } while (image_info->adjoin != MagickFalse);
   (void) CloseBlob(image);
-  return(MagickTrue);
+  return(status);
 }