]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/blob.c
...
[imagemagick] / MagickCore / blob.c
index c788bf58c7cd7e530940fd7fa7d06cfe43a050f8..477527d05914c0c50204d65e49a86dc89dced3be 100644 (file)
 %                                 July 1999                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
 %  obtain a copy of the License at                                            %
 %                                                                             %
-%    http://www.imagemagick.org/script/license.php                            %
+%    https://www.imagemagick.org/script/license.php                           %
 %                                                                             %
 %  Unless required by applicable law or agreed to in writing, software        %
 %  distributed under the License is distributed on an "AS IS" BASIS,          %
 /*
   Include declarations.
 */
+#ifdef __VMS
+#include  <types.h>
+#include  <mman.h>
+#endif
 #include "MagickCore/studio.h"
 #include "MagickCore/blob.h"
 #include "MagickCore/blob-private.h"
@@ -56,6 +60,7 @@
 #include "MagickCore/magick.h"
 #include "MagickCore/memory_.h"
 #include "MagickCore/nt-base-private.h"
+#include "MagickCore/option.h"
 #include "MagickCore/policy.h"
 #include "MagickCore/resource_.h"
 #include "MagickCore/semaphore.h"
@@ -140,6 +145,9 @@ struct _BlobInfo
   StreamHandler
     stream;
 
+  CustomStreamInfo
+    *custom_stream;
+
   unsigned char
     *data;
 
@@ -155,6 +163,25 @@ struct _BlobInfo
   size_t
     signature;
 };
+
+struct _CustomStreamInfo
+{
+  CustomStreamHandler
+    reader,
+    writer;
+
+  CustomStreamSeeker
+    seeker;
+
+  CustomStreamTeller
+    teller;
+
+  void
+    *data;
+
+  size_t
+    signature;
+};
 \f
 /*
   Forward declarations.
@@ -167,6 +194,44 @@ static int
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   A c q u i r e C u s t o m S t r e a m I n f o                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
+%
+%  The format of the AcquireCustomStreamInfo method is:
+%
+%      CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
+  ExceptionInfo *magick_unused(exception))
+{
+  CustomStreamInfo
+    *custom_stream;
+
+  magick_unreferenced(exception);
+  custom_stream=(CustomStreamInfo *) AcquireMagickMemory(
+    sizeof(*custom_stream));
+  if (custom_stream == (CustomStreamInfo *) NULL)
+    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+  (void) ResetMagickMemory(custom_stream,0,sizeof(*custom_stream));
+  custom_stream->signature=MagickCoreSignature;
+  return(custom_stream);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +   A t t a c h B l o b                                                       %
 %                                                                             %
 %                                                                             %
@@ -261,8 +326,7 @@ MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
     }
   for (i=0; i < length; i+=count)
   {
-    count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
-      SSIZE_MAX));
+    count=write(file,(const char *) blob+i,MagickMin(length-i,SSIZE_MAX));
     if (count <= 0)
       {
         count=0;
@@ -327,7 +391,7 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
     status;
 
   assert(image_info != (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);
@@ -358,9 +422,9 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
         Native blob support for this image format.
       */
       (void) CopyMagickString(blob_info->filename,image_info->filename,
-        MaxTextExtent);
+        MagickPathExtent);
       (void) CopyMagickString(blob_info->magick,image_info->magick,
-        MaxTextExtent);
+        MagickPathExtent);
       image=ReadImage(blob_info,exception);
       if (image != (Image *) NULL)
         (void) DetachBlob(image->blob);
@@ -381,7 +445,7 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
       return((Image *) NULL);
     }
   clone_info=CloneImageInfo(blob_info);
-  (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
+  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
     blob_info->magick,blob_info->filename);
   image=ReadImage(clone_info,exception);
   if (image != (Image *) NULL)
@@ -395,11 +459,11 @@ MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
       {
         (void) CopyMagickString(images->filename,image_info->filename,
-          MaxTextExtent);
+          MagickPathExtent);
         (void) CopyMagickString(images->magick_filename,image_info->filename,
-          MaxTextExtent);
+          MagickPathExtent);
         (void) CopyMagickString(images->magick,magick_info->name,
-          MaxTextExtent);
+          MagickPathExtent);
         images=GetNextImageInList(images);
       }
     }
@@ -458,6 +522,7 @@ MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
   clone_info->file_info.file=blob_info->file_info.file;
   clone_info->properties=blob_info->properties;
   clone_info->stream=blob_info->stream;
+  clone_info->custom_stream=blob_info->custom_stream;
   clone_info->data=blob_info->data;
   clone_info->debug=IsEventLogging();
   clone_info->reference_count=1;
@@ -495,7 +560,7 @@ MagickExport MagickBooleanType CloseBlob(Image *image)
     Close image file.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
@@ -541,6 +606,8 @@ MagickExport MagickBooleanType CloseBlob(Image *image)
         }
       break;
     }
+    case CustomStream:
+      break;
   }
   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
   image->blob->size=GetBlobSize(image);
@@ -590,6 +657,8 @@ MagickExport MagickBooleanType CloseBlob(Image *image)
         status=fclose(image->blob->file_info.file);
       break;
     }
+    case CustomStream:
+      break;
   }
   (void) DetachBlob(image->blob);
   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
@@ -624,11 +693,11 @@ MagickExport void DestroyBlob(Image *image)
     destroy;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
-  assert(image->blob->signature == MagickSignature);
+  assert(image->blob->signature == MagickCoreSignature);
   destroy=MagickFalse;
   LockSemaphoreInfo(image->blob->semaphore);
   image->blob->reference_count--;
@@ -646,7 +715,7 @@ MagickExport void DestroyBlob(Image *image)
     }
   if (image->blob->semaphore != (SemaphoreInfo *) NULL)
     RelinquishSemaphoreInfo(&image->blob->semaphore);
-  image->blob->signature=(~MagickSignature);
+  image->blob->signature=(~MagickCoreSignature);
   image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
 }
 \f
@@ -655,6 +724,40 @@ MagickExport void DestroyBlob(Image *image)
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   D e s t r o y C u s t o m S t r e a m I n f o                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  DestroyCustomStreamInfo() destroys memory associated with the
+%  CustomStreamInfo structure.
+%
+%  The format of the DestroyCustomStreamInfo method is:
+%
+%      CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
+%
+%  A description of each parameter follows:
+%
+%    o custom_stream: the custom stream info.
+%
+*/
+MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
+  CustomStreamInfo *custom_stream)
+{
+  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
+  assert(custom_stream != (CustomStreamInfo *) NULL);
+  assert(custom_stream->signature == MagickCoreSignature);
+  custom_stream->signature=(~MagickCoreSignature);
+  custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
+  return(custom_stream);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +   D e t a c h B l o b                                                       %
 %                                                                             %
 %                                                                             %
@@ -696,6 +799,7 @@ MagickExport void *DetachBlob(BlobInfo *blob_info)
   data=blob_info->data;
   blob_info->data=(unsigned char *) NULL;
   blob_info->stream=(StreamHandler) NULL;
+  blob_info->custom_stream=(CustomStreamInfo *) NULL;
   return(data);
 }
 \f
@@ -723,7 +827,7 @@ MagickExport void *DetachBlob(BlobInfo *blob_info)
 %    o image: the image.
 %
 */
-MagickPrivate void DisassociateBlob(Image *image)
+MagickExport void DisassociateBlob(Image *image)
 {
   BlobInfo
     *blob;
@@ -732,11 +836,11 @@ MagickPrivate void DisassociateBlob(Image *image)
     clone;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
-  assert(image->blob->signature == MagickSignature);
+  assert(image->blob->signature == MagickCoreSignature);
   clone=MagickFalse;
   LockSemaphoreInfo(image->blob->semaphore);
   assert(image->blob->reference_count >= 0);
@@ -791,7 +895,9 @@ MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
     buffer[16384];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
+  if (length != (MagickSizeType) ((MagickOffsetType) length))
+    return(MagickFalse);
   count=0;
   for (i=0; i < (MagickOffsetType) length; i+=count)
   {
@@ -834,11 +940,11 @@ MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(duplicate != (Image *) NULL);
-  assert(duplicate->signature == MagickSignature);
+  assert(duplicate->signature == MagickCoreSignature);
   DestroyBlob(image);
   image->blob=ReferenceBlob(duplicate->blob);
 }
@@ -869,7 +975,7 @@ MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
 MagickExport int EOFBlob(const Image *image)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(image->blob != (BlobInfo *) NULL);
@@ -910,6 +1016,8 @@ MagickExport int EOFBlob(const Image *image)
     }
     case BlobStream:
       break;
+    case CustomStream:
+      break;
   }
   return((int) image->blob->eof);
 }
@@ -919,7 +1027,7 @@ MagickExport int EOFBlob(const Image *image)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   F i l e T o B l o b                                                       %
+%   F i l e T o B l o b                                                       %
 %                                                                             %
 %                                                                             %
 %                                                                             %
@@ -998,9 +1106,8 @@ MagickExport void *FileToBlob(const char *filename,const size_t extent,
       */
       offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
       quantum=(size_t) MagickMaxBufferExtent;
-      if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
-        quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
-          MagickMaxBufferExtent);
+      if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
+        quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
       for (i=0; blob != (unsigned char *) NULL; i+=count)
       {
@@ -1039,10 +1146,11 @@ MagickExport void *FileToBlob(const char *filename,const size_t extent,
       blob[*length]='\0';
       return(blob);
     }
-  *length=(size_t) MagickMin((MagickSizeType) offset,extent);
+  *length=(size_t) MagickMin(offset,(MagickOffsetType)
+    MagickMin(extent,SSIZE_MAX));
   blob=(unsigned char *) NULL;
-  if (~(*length) >= (MaxTextExtent-1))
-    blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
+  if (~(*length) >= (MagickPathExtent-1))
+    blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
       sizeof(*blob));
   if (blob == (unsigned char *) NULL)
     {
@@ -1062,8 +1170,7 @@ MagickExport void *FileToBlob(const char *filename,const size_t extent,
       (void) lseek(file,0,SEEK_SET);
       for (i=0; i < *length; i+=count)
       {
-        count=read(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
-          SSIZE_MAX));
+        count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
         if (count <= 0)
           {
             count=0;
@@ -1128,7 +1235,7 @@ static inline ssize_t WriteBlobStream(Image *image,const size_t length,
   assert(image->blob->type != UndefinedStream);
   assert(data != NULL);
   if (image->blob->type != BlobStream)
-    return(WriteBlob(image,length,data));
+    return(WriteBlob(image,length,(const unsigned char *) data));
   extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
   if (extent >= image->blob->extent)
     {
@@ -1165,7 +1272,7 @@ MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
     *blob;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(filename != (const char *) NULL);
   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
   file=fileno(stdin);
@@ -1177,7 +1284,7 @@ MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
       return(MagickFalse);
     }
   quantum=(size_t) MagickMaxBufferExtent;
-  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
+  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
   if (blob == (unsigned char *) NULL)
@@ -1210,8 +1317,7 @@ MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
   blob=(unsigned char *) RelinquishMagickMemory(blob);
   return(MagickTrue);
 }
-
-
+\f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -1235,10 +1341,10 @@ MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
 %    o image: the image.
 %
 */
-MagickPrivate MagickBooleanType GetBlobError(const Image *image)
+MagickExport MagickBooleanType GetBlobError(const Image *image)
 {
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   return(image->blob->status);
@@ -1269,7 +1375,7 @@ MagickPrivate MagickBooleanType GetBlobError(const Image *image)
 MagickExport FILE *GetBlobFileHandle(const Image *image)
 {
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   return(image->blob->file_info.file);
 }
 \f
@@ -1295,7 +1401,7 @@ MagickExport FILE *GetBlobFileHandle(const Image *image)
 %    o blob_info: Specifies a pointer to a BlobInfo structure.
 %
 */
-MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
+MagickExport void GetBlobInfo(BlobInfo *blob_info)
 {
   assert(blob_info != (BlobInfo *) NULL);
   (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
@@ -1306,7 +1412,7 @@ MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
   blob_info->debug=IsEventLogging();
   blob_info->reference_count=1;
   blob_info->semaphore=AcquireSemaphoreInfo();
-  blob_info->signature=MagickSignature;
+  blob_info->signature=MagickCoreSignature;
 }
 \f
 /*
@@ -1331,10 +1437,10 @@ MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
 %    o image: the image.
 %
 */
-MagickPrivate const struct stat *GetBlobProperties(const Image *image)
+MagickExport const struct stat *GetBlobProperties(const Image *image)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   return(&image->blob->properties);
@@ -1369,7 +1475,7 @@ MagickExport MagickSizeType GetBlobSize(const Image *image)
     extent;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
@@ -1377,10 +1483,6 @@ MagickExport MagickSizeType GetBlobSize(const Image *image)
   switch (image->blob->type)
   {
     case UndefinedStream:
-    {
-      extent=image->blob->size;
-      break;
-    }
     case StandardStream:
     {
       extent=image->blob->size;
@@ -1415,6 +1517,23 @@ MagickExport MagickSizeType GetBlobSize(const Image *image)
       extent=(MagickSizeType) image->blob->length;
       break;
     }
+    case CustomStream:
+    {
+      if ((image->blob->custom_stream->teller != (CustomStreamTeller) NULL) &&
+          (image->blob->custom_stream->seeker != (CustomStreamSeeker) NULL))
+        {
+          MagickOffsetType
+            offset;
+
+          offset=image->blob->custom_stream->teller(
+            image->blob->custom_stream->data);
+          extent=image->blob->custom_stream->seeker(0,SEEK_END,
+            image->blob->custom_stream->data);
+          image->blob->custom_stream->seeker(offset,SEEK_SET,
+            image->blob->custom_stream->data);
+        }
+      break;
+    }
   }
   return(extent);
 }
@@ -1444,7 +1563,7 @@ MagickExport MagickSizeType GetBlobSize(const Image *image)
 MagickExport void *GetBlobStreamData(const Image *image)
 {
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   return(image->blob->data);
 }
 \f
@@ -1470,10 +1589,10 @@ MagickExport void *GetBlobStreamData(const Image *image)
 %    o image: the image.
 %
 */
-MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
+MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
 {
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   return(image->blob->stream);
@@ -1524,16 +1643,16 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,
   MagickBooleanType
     status;
 
-  unsigned char
+  void
     *blob;
 
   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(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(exception != (ExceptionInfo *) NULL);
   *length=0;
   blob=(unsigned char *) NULL;
@@ -1541,7 +1660,7 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,
   blob_info->adjoin=MagickFalse;
   (void) SetImageInfo(blob_info,1,exception);
   if (*blob_info->magick != '\0')
-    (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
+    (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
   magick_info=GetMagickInfo(image->magick,exception);
   if (magick_info == (const MagickInfo *) NULL)
     {
@@ -1551,7 +1670,7 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,
       blob_info=DestroyImageInfo(blob_info);
       return(blob);
     }
-  (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
+  (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
   if (GetMagickBlobSupport(magick_info) != MagickFalse)
     {
       /*
@@ -1572,16 +1691,15 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,
           *length=image->blob->length;
           blob=DetachBlob(image->blob);
           if (status == MagickFalse)
-            blob=(unsigned char *) RelinquishMagickMemory(blob);
+            blob=RelinquishMagickMemory(blob);
           else
-            blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
-              sizeof(*blob));
+            blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
         }
     }
   else
     {
       char
-        unique[MaxTextExtent];
+        unique[MagickPathExtent];
 
       int
         file;
@@ -1600,8 +1718,8 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,
           blob_info->file=fdopen(file,"wb");
           if (blob_info->file != (FILE *) NULL)
             {
-              (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
-                image->magick,unique);
+              (void) FormatLocaleString(image->filename,MagickPathExtent,
+                "%s:%s",image->magick,unique);
               status=WriteImage(blob_info,image,exception);
               (void) CloseBlob(image);
               (void) fclose(blob_info->file);
@@ -1620,6 +1738,145 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info,
 %                                                                             %
 %                                                                             %
 %                                                                             %
++  I m a g e T o C u s t o m S t r e a m                                      %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ImageToCustomStream() is the equivalent of WriteImage(), but writes the
+%  formatted "file" to the custom stream rather than to an actual file.
+%
+%  The format of the ImageToCustomStream method is:
+%
+%      void ImageToCustomStream(const ImageInfo *image_info,Image *image,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: the image info.
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
+  ExceptionInfo *exception)
+{
+  const MagickInfo
+    *magick_info;
+
+  ImageInfo
+    *blob_info;
+
+  MagickBooleanType
+    status;
+
+  assert(image_info != (const ImageInfo *) NULL);
+  assert(image_info->signature == MagickCoreSignature);
+  if (image_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
+      image_info->filename);
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
+  assert(image_info->custom_stream->signature == MagickCoreSignature);
+  assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
+  assert(exception != (ExceptionInfo *) NULL);
+  blob_info=CloneImageInfo(image_info);
+  blob_info->adjoin=MagickFalse;
+  (void) SetImageInfo(blob_info,1,exception);
+  if (*blob_info->magick != '\0')
+    (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
+  magick_info=GetMagickInfo(image->magick,exception);
+  if (magick_info == (const MagickInfo *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
+        image->magick);
+      blob_info=DestroyImageInfo(blob_info);
+      return;
+    }
+  (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
+  if (GetMagickBlobSupport(magick_info) != MagickFalse)
+    {
+      /*
+        Native blob support for this image format.
+      */
+      (void) CloseBlob(image);
+      *image->filename='\0';
+      (void) WriteImage(blob_info,image,exception);
+      (void) CloseBlob(image);
+    }
+  else
+    {
+      char
+        unique[MagickPathExtent];
+
+      int
+        file;
+
+      unsigned char
+        *blob;
+
+      /*
+        Write file to disk in blob image format.
+      */
+      blob_info->custom_stream=(CustomStreamInfo *) NULL;
+      blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
+        sizeof(*blob));
+      if (blob == (unsigned char *) NULL)
+        {
+          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
+            image_info->filename);
+          blob_info=DestroyImageInfo(blob_info);
+          return;
+        }
+      file=AcquireUniqueFileResource(unique);
+      if (file == -1)
+        {
+          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
+            image_info->filename);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          blob_info=DestroyImageInfo(blob_info);
+          return;
+        }
+      blob_info->file=fdopen(file,"wb+");
+      if (blob_info->file != (FILE *) NULL)
+        {
+          ssize_t
+            count;
+
+          (void) FormatLocaleString(image->filename,MagickPathExtent,
+            "%s:%s",image->magick,unique);
+          status=WriteImage(blob_info,image,exception);
+          (void) CloseBlob(image);
+          if (status != MagickFalse)
+            {
+              (void) fseek(blob_info->file,0,SEEK_SET);
+              count=(ssize_t) MagickMaxBufferExtent;
+              while (count == (ssize_t) MagickMaxBufferExtent)
+              {
+                count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
+                  blob_info->file);
+                image_info->custom_stream->writer(blob,count,
+                  image_info->custom_stream->data);
+              }
+            }
+          (void) fclose(blob_info->file);
+        }
+      blob=(unsigned char *) RelinquishMagickMemory(blob);
+      (void) RelinquishUniqueFileResource(unique);
+    }
+  blob_info=DestroyImageInfo(blob_info);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   I m a g e T o F i l e                                                     %
 %                                                                             %
 %                                                                             %
@@ -1669,7 +1926,7 @@ MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
     *buffer;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->blob != (BlobInfo *) NULL);
   assert(image->blob->type != UndefinedStream);
   if (image->debug != MagickFalse)
@@ -1688,9 +1945,8 @@ MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
       return(MagickFalse);
     }
   quantum=(size_t) MagickMaxBufferExtent;
-  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
-    quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
-      MagickMaxBufferExtent);
+  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
+    quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
   if (buffer == (unsigned char *) NULL)
     {
@@ -1700,8 +1956,8 @@ MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
       return(MagickFalse);
     }
   length=0;
-  p=ReadBlobStream(image,quantum,buffer,&count);
-  for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
+  p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
+  for (i=0; count > 0; )
   {
     length=(size_t) count;
     for (i=0; i < length; i+=count)
@@ -1716,6 +1972,7 @@ MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
     }
     if (i < length)
       break;
+    p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
   }
   if (LocaleCompare(filename,"-") != 0)
     file=close(file);
@@ -1777,16 +2034,16 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
   MagickBooleanType
     status;
 
-  unsigned char
+  void
     *blob;
 
   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(images != (Image *) NULL);
-  assert(images->signature == MagickSignature);
+  assert(images->signature == MagickCoreSignature);
   assert(exception != (ExceptionInfo *) NULL);
   *length=0;
   blob=(unsigned char *) NULL;
@@ -1794,7 +2051,7 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
     exception);
   if (*blob_info->magick != '\0')
-    (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
+    (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
   magick_info=GetMagickInfo(images->magick,exception);
   if (magick_info == (const MagickInfo *) NULL)
     {
@@ -1809,7 +2066,7 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
       blob_info=DestroyImageInfo(blob_info);
       return(ImageToBlob(image_info,images,length,exception));
     }
-  (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
+  (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
   if (GetMagickBlobSupport(magick_info) != MagickFalse)
     {
       /*
@@ -1830,17 +2087,16 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
           *length=images->blob->length;
           blob=DetachBlob(images->blob);
           if (status == MagickFalse)
-            blob=(unsigned char *) RelinquishMagickMemory(blob);
+            blob=RelinquishMagickMemory(blob);
           else
-            blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
-              sizeof(*blob));
+            blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
         }
     }
   else
     {
       char
-        filename[MaxTextExtent],
-        unique[MaxTextExtent];
+        filename[MagickPathExtent],
+        unique[MagickPathExtent];
 
       int
         file;
@@ -1859,7 +2115,7 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
           blob_info->file=fdopen(file,"wb");
           if (blob_info->file != (FILE *) NULL)
             {
-              (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
+              (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
                 images->magick,unique);
               status=WriteImages(blob_info,images,filename,exception);
               (void) CloseBlob(images);
@@ -1873,107 +2129,250 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
   blob_info=DestroyImageInfo(blob_info);
   return(blob);
 }
+\f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   I n j e c t I m a g e B l o b                                             %
++  I m a g e s T o C u s t o m B l o b                                        %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  InjectImageBlob() injects the image with a copy of itself in the specified
-%  format (e.g. inject JPEG into a PDF image).
+%  ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
+%  formatted "file" to the custom stream rather than to an actual file.
 %
-%  The format of the InjectImageBlob method is:
+%  The format of the ImageToCustomStream method is:
 %
-%      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
-%        Image *image,Image *inject_image,const char *format,
+%      void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
 %        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
-%    o image_info: the image info..
-%
-%    o image: the image.
-%
-%    o inject_image: inject into the image stream.
+%    o image_info: the image info.
 %
-%    o format: the image format.
+%    o images: the image list.
 %
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
-  Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
+MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
+  Image *images,ExceptionInfo *exception)
 {
-  char
-    filename[MaxTextExtent];
-
-  FILE
-    *unique_file;
-
-  Image
-    *byte_image;
+  const MagickInfo
+    *magick_info;
 
   ImageInfo
-    *write_info;
-
-  int
-    file;
+    *blob_info;
 
   MagickBooleanType
     status;
 
-  register ssize_t
-    i;
-
-  size_t
-    quantum;
-
-  ssize_t
-    count;
-
-  struct stat
-    file_stats;
-
-  unsigned char
-    *buffer;
-
-  /*
-    Write inject image to a temporary file.
-  */
-  assert(image_info != (ImageInfo *) NULL);
-  assert(image_info->signature == MagickSignature);
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  assert(inject_image != (Image *) NULL);
-  assert(inject_image->signature == MagickSignature);
+  assert(image_info != (const ImageInfo *) NULL);
+  assert(image_info->signature == MagickCoreSignature);
+  if (image_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
+      image_info->filename);
+  assert(images != (Image *) NULL);
+  assert(images->signature == MagickCoreSignature);
+  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
+  assert(image_info->custom_stream->signature == MagickCoreSignature);
+  assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
+  assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
   assert(exception != (ExceptionInfo *) NULL);
-  unique_file=(FILE *) NULL;
-  file=AcquireUniqueFileResource(filename);
-  if (file != -1)
-    unique_file=fdopen(file,"wb");
-  if ((file == -1) || (unique_file == (FILE *) NULL))
+  blob_info=CloneImageInfo(image_info);
+  (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
+    exception);
+  if (*blob_info->magick != '\0')
+    (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
+  magick_info=GetMagickInfo(images->magick,exception);
+  if (magick_info == (const MagickInfo *) NULL)
     {
-      (void) CopyMagickString(image->filename,filename,MaxTextExtent);
-      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
-        image->filename);
-      return(MagickFalse);
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
+        images->magick);
+      blob_info=DestroyImageInfo(blob_info);
+      return;
     }
-  byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
-  if (byte_image == (Image *) NULL)
+  (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
+  if (GetMagickBlobSupport(magick_info) != MagickFalse)
+    {
+      /*
+        Native blob support for this image format.
+      */
+      (void) CloseBlob(images);
+      *images->filename='\0';
+      (void) WriteImages(blob_info,images,images->filename,exception);
+      (void) CloseBlob(images);
+    }
+  else
+    {
+      char
+        filename[MagickPathExtent],
+        unique[MagickPathExtent];
+
+      int
+        file;
+
+      unsigned char
+        *blob;
+
+      /*
+        Write file to disk in blob image format.
+      */
+      blob_info->custom_stream=(CustomStreamInfo *) NULL;
+      blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
+        sizeof(*blob));
+      if (blob == (unsigned char *) NULL)
+        {
+          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
+            image_info->filename);
+          blob_info=DestroyImageInfo(blob_info);
+          return;
+        }
+      file=AcquireUniqueFileResource(unique);
+      if (file == -1)
+        {
+          ThrowFileException(exception,BlobError,"UnableToWriteBlob",
+            image_info->filename);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          blob_info=DestroyImageInfo(blob_info);
+          return;
+        }
+      blob_info->file=fdopen(file,"wb+");
+      if (blob_info->file != (FILE *) NULL)
+        {
+          ssize_t
+            count;
+
+          (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
+            images->magick,unique);
+          status=WriteImages(blob_info,images,filename,exception);
+          (void) CloseBlob(images);
+          if (status != MagickFalse)
+            {
+              (void) fseek(blob_info->file,0,SEEK_SET);
+              count=(ssize_t) MagickMaxBufferExtent;
+              while (count == (ssize_t) MagickMaxBufferExtent)
+              {
+                count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
+                  blob_info->file);
+                image_info->custom_stream->writer(blob,count,
+                  image_info->custom_stream->data);
+              }
+            }
+          (void) fclose(blob_info->file);
+        }
+      blob=(unsigned char *) RelinquishMagickMemory(blob);
+      (void) RelinquishUniqueFileResource(unique);
+    }
+  blob_info=DestroyImageInfo(blob_info);
+  return;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   I n j e c t I m a g e B l o b                                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  InjectImageBlob() injects the image with a copy of itself in the specified
+%  format (e.g. inject JPEG into a PDF image).
+%
+%  The format of the InjectImageBlob method is:
+%
+%      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
+%        Image *image,Image *inject_image,const char *format,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: the image info..
+%
+%    o image: the image.
+%
+%    o inject_image: inject into the image stream.
+%
+%    o format: the image format.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
+  Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
+{
+  char
+    filename[MagickPathExtent];
+
+  FILE
+    *unique_file;
+
+  Image
+    *byte_image;
+
+  ImageInfo
+    *write_info;
+
+  int
+    file;
+
+  MagickBooleanType
+    status;
+
+  register ssize_t
+    i;
+
+  size_t
+    quantum;
+
+  ssize_t
+    count;
+
+  struct stat
+    file_stats;
+
+  unsigned char
+    *buffer;
+
+  /*
+    Write inject image to a temporary file.
+  */
+  assert(image_info != (ImageInfo *) NULL);
+  assert(image_info->signature == MagickCoreSignature);
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  assert(inject_image != (Image *) NULL);
+  assert(inject_image->signature == MagickCoreSignature);
+  assert(exception != (ExceptionInfo *) NULL);
+  unique_file=(FILE *) NULL;
+  file=AcquireUniqueFileResource(filename);
+  if (file != -1)
+    unique_file=fdopen(file,"wb");
+  if ((file == -1) || (unique_file == (FILE *) NULL))
+    {
+      (void) CopyMagickString(image->filename,filename,MagickPathExtent);
+      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
+        image->filename);
+      return(MagickFalse);
+    }
+  byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
+  if (byte_image == (Image *) NULL)
     {
       (void) fclose(unique_file);
       (void) RelinquishUniqueFileResource(filename);
       return(MagickFalse);
     }
-  (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
-    filename);
+  (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
+    format,filename);
   DestroyBlob(byte_image);
   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
   write_info=CloneImageInfo(image_info);
@@ -1999,7 +2398,7 @@ MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
       return(MagickFalse);
     }
   quantum=(size_t) MagickMaxBufferExtent;
-  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
+  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
   if (buffer == (unsigned char *) NULL)
@@ -2034,7 +2433,7 @@ MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   I s B l o b E x e m p t                                                   %
+%   I s B l o b E x e m p t                                                   %
 %                                                                             %
 %                                                                             %
 %                                                                             %
@@ -2051,10 +2450,10 @@ MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
 %    o image: the image.
 %
 */
-MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
+MagickExport MagickBooleanType IsBlobExempt(const Image *image)
 {
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   return(image->blob->exempt);
@@ -2065,7 +2464,7 @@ MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   I s B l o b S e e k a b l e                                               %
+%   I s B l o b S e e k a b l e                                               %
 %                                                                             %
 %                                                                             %
 %                                                                             %
@@ -2082,13 +2481,13 @@ MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
 %    o image: the image.
 %
 */
-MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
+MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
 {
   MagickBooleanType
     seekable;
 
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   switch (image->blob->type)
@@ -2100,11 +2499,25 @@ MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
       seekable=MagickTrue;
       break;
     }
+    case UndefinedStream:
+    case StandardStream:
+    case BZipStream:
+    case FifoStream:
+    case PipeStream:
     default:
     {
       seekable=MagickFalse;
       break;
     }
+    case CustomStream:
+    {
+      if ((image->blob->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
+          (image->blob->custom_stream->teller != (CustomStreamTeller) NULL))
+        seekable=MagickTrue;
+      else
+        seekable=MagickFalse;
+      break;
+    }
   }
   return(seekable);
 }
@@ -2114,7 +2527,7 @@ MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+   I s B l o b T e m p o r a r y                                             %
+%   I s B l o b T e m p o r a r y                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
@@ -2131,10 +2544,10 @@ MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
 %    o image: the image.
 %
 */
-MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
+MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
 {
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   return(image->blob->temporary);
@@ -2357,12 +2770,34 @@ MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
 %    o mode: the mode for opening the file.
 %
 */
+
+static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
+  Image *image)
+{
+  const char
+    *option;
+
+  int
+    status;
+
+  size_t
+    size;
+
+  size=16384;
+  option=GetImageOption(image_info,"stream:buffer-size");
+  if (option != (const char *) NULL)
+    size=StringToUnsignedLong(option);
+  status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
+    _IONBF : _IOFBF,size);
+  return(status == 0 ? MagickTrue : MagickFalse);
+}
+
 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
   Image *image,const BlobMode mode,ExceptionInfo *exception)
 {
   char
-    extension[MaxTextExtent],
-    filename[MaxTextExtent];
+    extension[MagickPathExtent],
+    filename[MagickPathExtent];
 
   const char
     *type;
@@ -2374,12 +2809,12 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
     rights;
 
   assert(image_info != (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(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image_info->blob != (void *) NULL)
     {
       if (image_info->stream != (StreamHandler) NULL)
@@ -2387,6 +2822,13 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
       AttachBlob(image->blob,image_info->blob,image_info->length);
       return(MagickTrue);
     }
+  if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
+      (*image->filename == '\0'))
+    {
+      image->blob->type=CustomStream;
+      image->blob->custom_stream=image_info->custom_stream;
+      return(MagickTrue);
+    }
   (void) DetachBlob(image->blob);
   switch (mode)
   {
@@ -2402,7 +2844,7 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
     image->blob->synchronize=image_info->synchronize;
   if (image_info->stream != (StreamHandler) NULL)
     {
-      image->blob->stream=(StreamHandler) image_info->stream;
+      image->blob->stream=image_info->stream;
       if (*type == 'w')
         {
           image->blob->type=FifoStream;
@@ -2413,7 +2855,7 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
     Open image file.
   */
   *filename='\0';
-  (void) CopyMagickString(filename,image->filename,MaxTextExtent);
+  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
   rights=ReadPolicyRights;
   if (*type == 'w')
     rights=WritePolicyRights;
@@ -2430,33 +2872,34 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
       image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
       if (strchr(type,'b') != (char *) NULL)
-        setmode(_fileno(image->blob->file_info.file),_O_BINARY);
+        setmode(fileno(image->blob->file_info.file),_O_BINARY);
 #endif
       image->blob->type=StandardStream;
       image->blob->exempt=MagickTrue;
-      return(MagickTrue);
+      return(SetStreamBuffering(image_info,image));
     }
   if (LocaleNCompare(filename,"fd:",3) == 0)
     {
       char
-        mode[MaxTextExtent];
+        fileMode[MagickPathExtent];
 
-      *mode=(*type);
-      mode[1]='\0';
-      image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
+      *fileMode =(*type);
+      fileMode[1]='\0';
+      image->blob->file_info.file=fdopen(StringToLong(filename+3),fileMode);
 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
       if (strchr(type,'b') != (char *) NULL)
-        setmode(_fileno(image->blob->file_info.file),_O_BINARY);
+        setmode(fileno(image->blob->file_info.file),_O_BINARY);
 #endif
       image->blob->type=StandardStream;
       image->blob->exempt=MagickTrue;
-      return(MagickTrue);
+      return(SetStreamBuffering(image_info,image));
     }
-#if defined(MAGICKCORE_HAVE_POPEN)
+#if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
   if (*filename == '|')
     {
       char
-        mode[MaxTextExtent];
+        fileMode[MagickPathExtent],
+        *sanitize_command;
 
       /*
         Pipe image to or from a system command.
@@ -2465,9 +2908,12 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
       if (*type == 'w')
         (void) signal(SIGPIPE,SIG_IGN);
 #endif
-      *mode=(*type);
-      mode[1]='\0';
-      image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
+      *fileMode =(*type);
+      fileMode[1]='\0';
+      sanitize_command=SanitizeString(filename+1);
+      image->blob->file_info.file=(FILE *) popen_utf8(sanitize_command,
+        fileMode);
+      sanitize_command=DestroyString(sanitize_command);
       if (image->blob->file_info.file == (FILE *) NULL)
         {
           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
@@ -2475,7 +2921,7 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
         }
       image->blob->type=PipeStream;
       image->blob->exempt=MagickTrue;
-      return(MagickTrue);
+      return(SetStreamBuffering(image_info,image));
     }
 #endif
   status=GetPathAttributes(filename,&image->blob->properties);
@@ -2490,13 +2936,13 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
         }
       image->blob->type=FileStream;
       image->blob->exempt=MagickTrue;
-      return(MagickTrue);
+      return(SetStreamBuffering(image_info,image));
     }
 #endif
   GetPathComponent(image->filename,ExtensionPath,extension);
   if (*type == 'w')
     {
-      (void) CopyMagickString(filename,image->filename,MaxTextExtent);
+      (void) CopyMagickString(filename,image->filename,MagickPathExtent);
       if ((image_info->adjoin == MagickFalse) ||
           (strchr(filename,'%') != (char *) NULL))
         {
@@ -2510,17 +2956,17 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
                (GetNextImageInList(image) != (Image *) NULL)))
             {
               char
-                path[MaxTextExtent];
+                path[MagickPathExtent];
 
               GetPathComponent(image->filename,RootPath,path);
               if (*extension == '\0')
-                (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
+                (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
                   path,(double) image->scene);
               else
-                (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
-                  path,(double) image->scene,extension);
+                (void) FormatLocaleString(filename,MagickPathExtent,
+                  "%s-%.20g.%s",path,(double) image->scene,extension);
             }
-          (void) CopyMagickString(image->filename,filename,MaxTextExtent);
+          (void) CopyMagickString(image->filename,filename,MagickPathExtent);
 #if defined(macintosh)
           SetApplicationType(filename,image_info->magick,'8BIM');
 #endif
@@ -2545,14 +2991,13 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
               magick[3];
 
             image->blob->type=FileStream;
-#if defined(MAGICKCORE_HAVE_SETVBUF)
-            (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
-              _IOFBF,16384);
-#endif
+            (void) SetStreamBuffering(image_info,image);
             (void) ResetMagickMemory(magick,0,sizeof(magick));
             count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
             (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
+#if defined(MAGICKCORE_POSIX_SUPPORT)
             (void) fflush(image->blob->file_info.file);
+#endif
             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
                "  read %.20g magic header bytes",(double) count);
 #if defined(MAGICKCORE_ZLIB_DELEGATE)
@@ -2653,10 +3098,7 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
               if (image->blob->file_info.file != (FILE *) NULL)
                 {
                   image->blob->type=FileStream;
-#if defined(MAGICKCORE_HAVE_SETVBUF)
-                  (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
-                    _IOFBF,16384);
-#endif
+                  (void) SetStreamBuffering(image_info,image);
                 }
        }
   image->blob->status=MagickFalse;
@@ -2711,6 +3153,8 @@ extern "C" {
 static size_t PingStream(const Image *magick_unused(image),
   const void *magick_unused(pixels),const size_t columns)
 {
+  magick_unreferenced(image);
+  magick_unreferenced(pixels);
   return(columns);
 }
 
@@ -2728,7 +3172,7 @@ MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
     *ping_info;
 
   assert(image_info != (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);
@@ -2799,37 +3243,19 @@ MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
     count;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->blob != (BlobInfo *) NULL);
   assert(image->blob->type != UndefinedStream);
   if (length == 0)
     return(0);
   assert(data != (void *) NULL);
   count=0;
-  q=data;
+  q=(unsigned char *) data;
   switch (image->blob->type)
   {
     case UndefinedStream:
       break;
     case StandardStream:
-    {
-      register ssize_t
-        i;
-
-      for (i=0; i < (ssize_t) length; i+=count)
-      {
-        count=read(fileno(image->blob->file_info.file),q+i,MagickMin(length-i,
-          (size_t) SSIZE_MAX));
-        if (count <= 0)
-          {
-            count=0;
-            if (errno != EINTR)
-              break;
-          }
-      }
-      count=i;
-      break;
-    }
     case FileStream:
     case PipeStream:
     {
@@ -2840,6 +3266,22 @@ MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
           count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
           break;
         }
+        case 4:
+        {
+          c=getc(image->blob->file_info.file);
+          if (c == EOF)
+            break;
+          *q++=(unsigned char) c;
+          count++;
+        }
+        case 3:
+        {
+          c=getc(image->blob->file_info.file);
+          if (c == EOF)
+            break;
+          *q++=(unsigned char) c;
+          count++;
+        }
         case 2:
         {
           c=getc(image->blob->file_info.file);
@@ -2872,6 +3314,22 @@ MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
             (unsigned int) length);
           break;
         }
+        case 4:
+        {
+          c=gzgetc(image->blob->file_info.gzfile);
+          if (c == EOF)
+            break;
+          *q++=(unsigned char) c;
+          count++;
+        }
+        case 3:
+        {
+          c=gzgetc(image->blob->file_info.gzfile);
+          if (c == EOF)
+            break;
+          *q++=(unsigned char) c;
+          count++;
+        }
         case 2:
         {
           c=gzgetc(image->blob->file_info.gzfile);
@@ -2914,14 +3372,20 @@ MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
           break;
         }
       p=image->blob->data+image->blob->offset;
-      count=(ssize_t) MagickMin((MagickOffsetType) length,image->blob->length-
-        image->blob->offset);
+      count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
       image->blob->offset+=count;
       if (count != (ssize_t) length)
         image->blob->eof=MagickTrue;
       (void) memcpy(q,p,(size_t) count);
       break;
     }
+    case CustomStream:
+    {
+      if (image->blob->custom_stream->reader != (CustomStreamHandler) NULL)
+        count=image->blob->custom_stream->reader(q,length,
+          image->blob->custom_stream->data);
+      break;
+    }
   }
   return(count);
 }
@@ -2960,8 +3424,8 @@ MagickExport int ReadBlobByte(Image *image)
     buffer[1];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  p=ReadBlobStream(image,1,buffer,&count);
+  assert(image->signature == MagickCoreSignature);
+  p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
   if (count != 1)
     return(EOF);
   return((int) (*p));
@@ -3056,8 +3520,8 @@ MagickExport float ReadBlobFloat(Image *image)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
-%  specified by the endian member of the image structure.
+%  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
+%  byte-order specified by the endian member of the image structure.
 %
 %  The format of the ReadBlobLong method is:
 %
@@ -3083,24 +3547,24 @@ MagickExport unsigned int ReadBlobLong(Image *image)
     value;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,4,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
   if (count != 4)
     return(0UL);
   if (image->endian == LSBEndian)
     {
       value=(unsigned int) (*p++);
-      value|=((unsigned int) (*p++)) << 8;
-      value|=((unsigned int) (*p++)) << 16;
-      value|=((unsigned int) (*p++)) << 24;
-      return(value);
+      value|=(unsigned int) (*p++) << 8;
+      value|=(unsigned int) (*p++) << 16;
+      value|=(unsigned int) (*p++) << 24;
+      return(value & 0xffffffff);
     }
-  value=((unsigned int) (*p++)) << 24;
-  value|=((unsigned int) (*p++)) << 16;
-  value|=((unsigned int) (*p++)) << 8;
-  value|=((unsigned int) (*p++));
-  return(value);
+  value=(unsigned int) (*p++) << 24;
+  value|=(unsigned int) (*p++) << 16;
+  value|=(unsigned int) (*p++) << 8;
+  value|=(unsigned int) (*p++);
+  return(value & 0xffffffff);
 }
 \f
 /*
@@ -3141,31 +3605,31 @@ MagickExport MagickSizeType ReadBlobLongLong(Image *image)
     buffer[8];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,8,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
   if (count != 8)
     return(MagickULLConstant(0));
   if (image->endian == LSBEndian)
     {
       value=(MagickSizeType) (*p++);
-      value|=((MagickSizeType) (*p++)) << 8;
-      value|=((MagickSizeType) (*p++)) << 16;
-      value|=((MagickSizeType) (*p++)) << 24;
-      value|=((MagickSizeType) (*p++)) << 32;
-      value|=((MagickSizeType) (*p++)) << 40;
-      value|=((MagickSizeType) (*p++)) << 48;
-      value|=((MagickSizeType) (*p++)) << 56;
+      value|=(MagickSizeType) (*p++) << 8;
+      value|=(MagickSizeType) (*p++) << 16;
+      value|=(MagickSizeType) (*p++) << 24;
+      value|=(MagickSizeType) (*p++) << 32;
+      value|=(MagickSizeType) (*p++) << 40;
+      value|=(MagickSizeType) (*p++) << 48;
+      value|=(MagickSizeType) (*p++) << 56;
       return(value & MagickULLConstant(0xffffffffffffffff));
     }
-  value=((MagickSizeType) (*p++)) << 56;
-  value|=((MagickSizeType) (*p++)) << 48;
-  value|=((MagickSizeType) (*p++)) << 40;
-  value|=((MagickSizeType) (*p++)) << 32;
-  value|=((MagickSizeType) (*p++)) << 24;
-  value|=((MagickSizeType) (*p++)) << 16;
-  value|=((MagickSizeType) (*p++)) << 8;
-  value|=((MagickSizeType) (*p++));
+  value=(MagickSizeType) (*p++) << 56;
+  value|=(MagickSizeType) (*p++) << 48;
+  value|=(MagickSizeType) (*p++) << 40;
+  value|=(MagickSizeType) (*p++) << 32;
+  value|=(MagickSizeType) (*p++) << 24;
+  value|=(MagickSizeType) (*p++) << 16;
+  value|=(MagickSizeType) (*p++) << 8;
+  value|=(MagickSizeType) (*p++);
   return(value & MagickULLConstant(0xffffffffffffffff));
 }
 \f
@@ -3197,7 +3661,7 @@ MagickExport unsigned short ReadBlobShort(Image *image)
   register const unsigned char
     *p;
 
-  register unsigned int
+  register unsigned short
     value;
 
   ssize_t
@@ -3207,20 +3671,20 @@ MagickExport unsigned short ReadBlobShort(Image *image)
     buffer[2];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,2,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
   if (count != 2)
     return((unsigned short) 0U);
   if (image->endian == LSBEndian)
     {
-      value=(unsigned int) (*p++);
-      value|=((unsigned int) (*p++)) << 8;
-      return((unsigned short) (value & 0xffff));
+      value=(unsigned short) (*p++);
+      value|=(unsigned short) (*p++) << 8;
+      return(value);
     }
-  value=(unsigned int) ((*p++) << 8);
-  value|=(unsigned int) (*p++);
-  return((unsigned short) (value & 0xffff));
+  value=(unsigned short) (*p++) << 8;
+  value|=(unsigned short) (*p++);
+  return(value);
 }
 \f
 /*
@@ -3234,7 +3698,7 @@ MagickExport unsigned short ReadBlobShort(Image *image)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
+%  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
 %  least-significant byte first order.
 %
 %  The format of the ReadBlobLSBLong method is:
@@ -3261,16 +3725,54 @@ MagickExport unsigned int ReadBlobLSBLong(Image *image)
     buffer[4];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,4,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
   if (count != 4)
     return(0U);
   value=(unsigned int) (*p++);
-  value|=((unsigned int) (*p++)) << 8;
-  value|=((unsigned int) (*p++)) << 16;
-  value|=((unsigned int) (*p++)) << 24;
-  return(value);
+  value|=(unsigned int) (*p++) << 8;
+  value|=(unsigned int) (*p++) << 16;
+  value|=(unsigned int) (*p++) << 24;
+  return(value & 0xffffffff);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  R e a d B l o b L S B S i g n e d L o n g                                  %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
+%  least-significant byte first order.
+%
+%  The format of the ReadBlobLSBSignedLong method is:
+%
+%      signed int ReadBlobLSBSignedLong(Image *image)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+*/
+MagickExport signed int ReadBlobLSBSignedLong(Image *image)
+{
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
+  quantum.unsigned_value=ReadBlobLSBLong(image);
+  return(quantum.signed_value);
 }
 \f
 /*
@@ -3301,7 +3803,7 @@ MagickExport unsigned short ReadBlobLSBShort(Image *image)
   register const unsigned char
     *p;
 
-  register unsigned int
+  register unsigned short
     value;
 
   ssize_t
@@ -3311,14 +3813,14 @@ MagickExport unsigned short ReadBlobLSBShort(Image *image)
     buffer[2];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,2,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
   if (count != 2)
     return((unsigned short) 0U);
   value=(unsigned int) (*p++);
-  value|=((unsigned int) ((*p++)) << 8);
-  return((unsigned short) (value & 0xffff));
+  value|=(unsigned int) (*p++) << 8;
+  return(value & 0xffff);
 }
 \f
 /*
@@ -3326,25 +3828,63 @@ MagickExport unsigned short ReadBlobLSBShort(Image *image)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-+  R e a d B l o b M S B L o n g                                              %
++  R e a d B l o b L S B S i g n e d S h o r t                                %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
-%  most-significant byte first order.
+%  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
+%  least-significant byte-order.
 %
-%  The format of the ReadBlobMSBLong method is:
+%  The format of the ReadBlobLSBSignedShort method is:
 %
-%      unsigned int ReadBlobMSBLong(Image *image)
+%      signed short ReadBlobLSBSignedShort(Image *image)
 %
 %  A description of each parameter follows.
 %
 %    o image: the image.
 %
 */
-MagickExport unsigned int ReadBlobMSBLong(Image *image)
+MagickExport signed short ReadBlobLSBSignedShort(Image *image)
+{
+  union
+  {
+    unsigned short
+      unsigned_value;
+
+    signed short
+      signed_value;
+  } quantum;
+
+  quantum.unsigned_value=ReadBlobLSBShort(image);
+  return(quantum.signed_value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  R e a d B l o b M S B L o n g                                              %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
+%  most-significant byte first order.
+%
+%  The format of the ReadBlobMSBLong method is:
+%
+%      unsigned int ReadBlobMSBLong(Image *image)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+*/
+MagickExport unsigned int ReadBlobMSBLong(Image *image)
 {
   register const unsigned char
     *p;
@@ -3359,14 +3899,14 @@ MagickExport unsigned int ReadBlobMSBLong(Image *image)
     buffer[4];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,4,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
   if (count != 4)
     return(0UL);
-  value=((unsigned int) (*p++) << 24);
-  value|=((unsigned int) (*p++) << 16);
-  value|=((unsigned int) (*p++) << 8);
+  value=(unsigned int) (*p++) << 24;
+  value|=(unsigned int) (*p++) << 16;
+  value|=(unsigned int) (*p++) << 8;
   value|=(unsigned int) (*p++);
   return(value);
 }
@@ -3382,8 +3922,8 @@ MagickExport unsigned int ReadBlobMSBLong(Image *image)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
-%  most-significant byte first order.
+%  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
+%  in most-significant byte first order.
 %
 %  The format of the ReadBlobMSBLongLong method is:
 %
@@ -3409,19 +3949,19 @@ MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
     buffer[8];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,8,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
   if (count != 8)
     return(MagickULLConstant(0));
-  value=((MagickSizeType) (*p++)) << 56;
-  value|=((MagickSizeType) (*p++)) << 48;
-  value|=((MagickSizeType) (*p++)) << 40;
-  value|=((MagickSizeType) (*p++)) << 32;
-  value|=((MagickSizeType) (*p++)) << 24;
-  value|=((MagickSizeType) (*p++)) << 16;
-  value|=((MagickSizeType) (*p++)) << 8;
-  value|=((MagickSizeType) (*p++));
+  value=(MagickSizeType) (*p++) << 56;
+  value|=(MagickSizeType) (*p++) << 48;
+  value|=(MagickSizeType) (*p++) << 40;
+  value|=(MagickSizeType) (*p++) << 32;
+  value|=(MagickSizeType) (*p++) << 24;
+  value|=(MagickSizeType) (*p++) << 16;
+  value|=(MagickSizeType) (*p++) << 8;
+  value|=(MagickSizeType) (*p++);
   return(value & MagickULLConstant(0xffffffffffffffff));
 }
 \f
@@ -3453,7 +3993,7 @@ MagickExport unsigned short ReadBlobMSBShort(Image *image)
   register const unsigned char
     *p;
 
-  register unsigned int
+  register unsigned short
     value;
 
   ssize_t
@@ -3463,14 +4003,166 @@ MagickExport unsigned short ReadBlobMSBShort(Image *image)
     buffer[2];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   *buffer='\0';
-  p=ReadBlobStream(image,2,buffer,&count);
+  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
   if (count != 2)
     return((unsigned short) 0U);
-  value=(unsigned int) ((*p++) << 8);
-  value|=(unsigned int) (*p++);
-  return((unsigned short) (value & 0xffff));
+  value=(unsigned short) (*p++) << 8;
+  value|=(unsigned short) (*p++);
+  return(value & 0xffff);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  R e a d B l o b M S B S i g n e d L o n g                                  %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
+%  most-significant byte-order.
+%
+%  The format of the ReadBlobMSBSignedLong method is:
+%
+%      signed int ReadBlobMSBSignedLong(Image *image)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+*/
+MagickExport signed int ReadBlobMSBSignedLong(Image *image)
+{
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
+  quantum.unsigned_value=ReadBlobMSBLong(image);
+  return(quantum.signed_value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  R e a d B l o b M S B S i g n e d S h o r t                                %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
+%  most-significant byte-order.
+%
+%  The format of the ReadBlobMSBSignedShort method is:
+%
+%      signed short ReadBlobMSBSignedShort(Image *image)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+*/
+MagickExport signed short ReadBlobMSBSignedShort(Image *image)
+{
+  union
+  {
+    unsigned short
+      unsigned_value;
+
+    signed short
+      signed_value;
+  } quantum;
+
+  quantum.unsigned_value=ReadBlobMSBShort(image);
+  return(quantum.signed_value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  R e a d B l o b S i g n e d L o n g                                        %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
+%  byte-order specified by the endian member of the image structure.
+%
+%  The format of the ReadBlobSignedLong method is:
+%
+%      signed int ReadBlobSignedLong(Image *image)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+*/
+MagickExport signed int ReadBlobSignedLong(Image *image)
+{
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
+  quantum.unsigned_value=ReadBlobLong(image);
+  return(quantum.signed_value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  R e a d B l o b S i g n e d S h o r t                                      %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
+%  byte-order specified by the endian member of the image structure.
+%
+%  The format of the ReadBlobSignedShort method is:
+%
+%      signed short ReadBlobSignedShort(Image *image)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+*/
+MagickExport signed short ReadBlobSignedShort(Image *image)
+{
+  union
+  {
+    unsigned short
+      unsigned_value;
+
+    signed short
+      signed_value;
+  } quantum;
+
+  quantum.unsigned_value=ReadBlobShort(image);
+  return(quantum.signed_value);
 }
 \f
 /*
@@ -3512,14 +4204,14 @@ MagickExport const void *ReadBlobStream(Image *image,const size_t length,
   void *data,ssize_t *count)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(image->blob != (BlobInfo *) NULL);
   assert(image->blob->type != UndefinedStream);
   assert(count != (ssize_t *) NULL);
   if (image->blob->type != BlobStream)
     {
       assert(data != NULL);
-      *count=ReadBlob(image,length,data);
+      *count=ReadBlob(image,length,(unsigned char *) data);
       return(data);
     }
   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
@@ -3529,8 +4221,7 @@ MagickExport const void *ReadBlobStream(Image *image,const size_t length,
       return(data);
     }
   data=image->blob->data+image->blob->offset;
-  *count=(ssize_t) MagickMin((MagickOffsetType) length,image->blob->length-
-    image->blob->offset);
+  *count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
   image->blob->offset+=(*count);
   if (*count != (ssize_t) length)
     image->blob->eof=MagickTrue;
@@ -3577,14 +4268,15 @@ MagickExport char *ReadBlobString(Image *image,char *string)
     buffer[1];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  for (i=0; i < (MaxTextExtent-1L); i++)
+  assert(image->signature == MagickCoreSignature);
+  for (i=0; i < (MagickPathExtent-1L); i++)
   {
-    p=ReadBlobStream(image,1,buffer,&count);
+    p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
     if (count != 1)
       {
         if (i == 0)
           return((char *) NULL);
+        string[i]='\0';
         break;
       }
     string[i]=(char) (*p);
@@ -3623,7 +4315,7 @@ MagickExport char *ReadBlobString(Image *image,char *string)
 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
 {
   assert(blob != (BlobInfo *) NULL);
-  assert(blob->signature == MagickSignature);
+  assert(blob->signature == MagickCoreSignature);
   if (blob->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   LockSemaphoreInfo(blob->semaphore);
@@ -3669,7 +4361,7 @@ MagickExport MagickOffsetType SeekBlob(Image *image,
   const MagickOffsetType offset,const int whence)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
@@ -3679,17 +4371,17 @@ MagickExport MagickOffsetType SeekBlob(Image *image,
     case UndefinedStream:
       break;
     case StandardStream:
+    case PipeStream:
       return(-1);
     case FileStream:
     {
-      if ((whence == SEEK_SET) && (offset < 0))
+      if ((offset < 0) && (whence == SEEK_SET))
         return(-1);
       if (fseek(image->blob->file_info.file,offset,whence) < 0)
         return(-1);
       image->blob->offset=TellBlob(image);
       break;
     }
-    case PipeStream:
     case ZipStream:
     {
 #if defined(MAGICKCORE_ZLIB_DELEGATE)
@@ -3736,11 +4428,14 @@ MagickExport MagickOffsetType SeekBlob(Image *image,
           image->blob->eof=MagickFalse;
           break;
         }
-      if (image->blob->mapped != MagickFalse)
-        return(-1);
       if (image->blob->offset < (MagickOffsetType)
           ((off_t) image->blob->extent))
         break;
+      if (image->blob->mapped != MagickFalse)
+        {
+          image->blob->eof=MagickTrue;
+          return(-1);
+        }
       image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
       image->blob->quantum<<=1;
       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
@@ -3753,6 +4448,14 @@ MagickExport MagickOffsetType SeekBlob(Image *image,
         }
       break;
     }
+    case CustomStream:
+    {
+      if (image->blob->custom_stream->seeker == (CustomStreamSeeker) NULL)
+        return(-1);
+      image->blob->offset=image->blob->custom_stream->seeker(offset,whence,
+        image->blob->custom_stream->data);
+      break;
+    }
   }
   return(image->blob->offset);
 }
@@ -3782,10 +4485,10 @@ MagickExport MagickOffsetType SeekBlob(Image *image,
 %    o exempt: Set to true if this blob is exempt from being closed.
 %
 */
-MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
+MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
 {
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   image->blob->exempt=exempt;
@@ -3817,11 +4520,11 @@ MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
 %    o extent:  the blob maximum extent.
 %
 */
-MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
+MagickExport MagickBooleanType SetBlobExtent(Image *image,
   const MagickSizeType extent)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
@@ -3934,6 +4637,8 @@ MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
         }
       break;
     }
+    case CustomStream:
+      break;
   }
   return(MagickTrue);
 }
@@ -3943,6 +4648,170 @@ MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
++  S e t C u s t o m S t r e a m D a t a                                      %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SetCustomStreamData() sets the stream info data member.
+%
+%  The format of the SetCustomStreamData method is:
+%
+%      void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
+%
+%  A description of each parameter follows:
+%
+%    o custom_stream: your custom stream.
+%
+%    o void: your data.
+%
+*/
+MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
+  void *data)
+{
+  assert(custom_stream != (CustomStreamInfo *) NULL);
+  assert(custom_stream->signature == MagickCoreSignature);
+  custom_stream->data=data;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  S e t C u s t o m S t r e a m R e a d e r                                  %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SetCustomStreamReader() sets the stream info reader member.
+%
+%  The format of the SetCustomStreamReader method is:
+%
+%      void SetCustomStreamReader(CustomStreamInfo *custom_stream,
+%        CustomStreamHandler reader)
+%
+%  A description of each parameter follows:
+%
+%    o custom_stream: your custom stream.
+%
+%    o reader: your custom stream reader.
+%
+*/
+MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
+  CustomStreamHandler reader)
+{
+  assert(custom_stream != (CustomStreamInfo *) NULL);
+  assert(custom_stream->signature == MagickCoreSignature);
+  custom_stream->reader=reader;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  S e t C u s t o m S t r e a m S e e k e r                                  %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SetCustomStreamSeeker() sets the stream info seeker member.
+%
+%  The format of the SetCustomStreamReader method is:
+%
+%      void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
+%        CustomStreamSeeker seeker)
+%
+%  A description of each parameter follows:
+%
+%    o custom_stream: your custom stream.
+%
+%    o seeker: your custom stream seeker.
+%
+*/
+MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
+  CustomStreamSeeker seeker)
+{
+  assert(custom_stream != (CustomStreamInfo *) NULL);
+  assert(custom_stream->signature == MagickCoreSignature);
+  custom_stream->seeker=seeker;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  S e t C u s t o m S t r e a m T e l l e r                                  %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SetCustomStreamTeller() sets the stream info teller member.
+%
+%  The format of the SetCustomStreamTeller method is:
+%
+%      void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
+%        CustomStreamTeller *teller)
+%
+%  A description of each parameter follows:
+%
+%    o custom_stream: your custom stream.
+%
+%    o teller: your custom stream teller.
+%
+*/
+MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
+  CustomStreamTeller teller)
+{
+  assert(custom_stream != (CustomStreamInfo *) NULL);
+  assert(custom_stream->signature == MagickCoreSignature);
+  custom_stream->teller=teller;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++  S e t C u s t o m S t r e a m W r i t e r                                  %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SetCustomStreamWriter() sets the stream info writer member.
+%
+%  The format of the SetCustomStreamWriter method is:
+%
+%      void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
+%        CustomStreamHandler *writer)
+%
+%  A description of each parameter follows:
+%
+%    o custom_stream: your custom stream.
+%
+%    o writer: your custom stream writer.
+%
+*/
+MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
+  CustomStreamHandler writer)
+{
+  assert(custom_stream != (CustomStreamInfo *) NULL);
+  assert(custom_stream->signature == MagickCoreSignature);
+  custom_stream->writer=writer;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +  S y n c B l o b                                                            %
 %                                                                             %
 %                                                                             %
@@ -3967,7 +4836,7 @@ static int SyncBlob(Image *image)
     status;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
@@ -4002,6 +4871,8 @@ static int SyncBlob(Image *image)
       break;
     case BlobStream:
       break;
+    case CustomStream:
+      break;
   }
   return(status);
 }
@@ -4034,7 +4905,7 @@ MagickExport MagickOffsetType TellBlob(const Image *image)
     offset;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(image->blob != (BlobInfo *) NULL);
@@ -4068,6 +4939,12 @@ MagickExport MagickOffsetType TellBlob(const Image *image)
       offset=image->blob->offset;
       break;
     }
+    case CustomStream:
+    {
+      if (image->blob->custom_stream->teller != (CustomStreamTeller) NULL)
+        offset=image->blob->custom_stream->teller(image->blob->custom_stream->data);
+      break;
+    }
   }
   return(offset);
 }
@@ -4117,6 +4994,160 @@ MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   C u s t o m S t r e a m T o I m a g e                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  CustomStreamToImage() is the equivalent of ReadImage(), but reads the
+%  formatted "file" from the suplied method rather than to an actual file.
+%
+%  The format of the CustomStreamToImage method is:
+%
+%      Image *CustomStreamToImage(const ImageInfo *image_info,
+%         ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: the image info.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
+  ExceptionInfo *exception)
+{
+  const MagickInfo
+    *magick_info;
+
+  Image
+    *image;
+
+  ImageInfo
+    *blob_info;
+
+  assert(image_info != (ImageInfo *) NULL);
+  assert(image_info->signature == MagickCoreSignature);
+  if (image_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
+      image_info->filename);
+  assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
+  assert(image_info->custom_stream->signature == MagickCoreSignature);
+  assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
+  assert(exception != (ExceptionInfo *) NULL);
+  blob_info=CloneImageInfo(image_info);
+  if (*blob_info->magick == '\0')
+    (void) SetImageInfo(blob_info,0,exception);
+  magick_info=GetMagickInfo(blob_info->magick,exception);
+  if (magick_info == (const MagickInfo *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
+        blob_info->magick);
+      blob_info=DestroyImageInfo(blob_info);
+      return((Image *) NULL);
+    }
+  image=(Image *) NULL;
+  if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
+      (blob_info->custom_stream == (CustomStreamInfo *) NULL))
+    {
+      /*
+        Native blob support for this image format or SetImageInfo changed the
+        blob to a file.
+      */
+      image=ReadImage(blob_info,exception);
+      if (image != (Image *) NULL)
+        (void) CloseBlob(image);
+    }
+  else
+    {
+      char
+        unique[MagickPathExtent];
+
+      int
+        file;
+
+      ImageInfo
+        *clone_info;
+
+      unsigned char
+        *blob;
+
+      /*
+        Write data to file on disk.
+      */
+      blob_info->custom_stream=(CustomStreamInfo *) NULL;
+      blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
+        sizeof(*blob));
+      if (blob == (unsigned char *) NULL)
+        {
+          ThrowFileException(exception,BlobError,"UnableToReadBlob",
+            image_info->filename);
+          blob_info=DestroyImageInfo(blob_info);
+          return((Image *) NULL);
+        }
+      file=AcquireUniqueFileResource(unique);
+      if (file == -1)
+        {
+          ThrowFileException(exception,BlobError,"UnableToReadBlob",
+            image_info->filename);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          blob_info=DestroyImageInfo(blob_info);
+          return((Image *) NULL);
+        }
+      clone_info=CloneImageInfo(blob_info);
+      blob_info->file=fdopen(file,"wb+");
+      if (blob_info->file != (FILE *) NULL)
+        {
+          ssize_t
+            count;
+
+          count=(ssize_t) MagickMaxBufferExtent;
+          while (count == (ssize_t) MagickMaxBufferExtent)
+          {
+            count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
+              image_info->custom_stream->data);
+            count=(ssize_t) write(file,(const char *) blob,count);
+          }
+          (void) fclose(blob_info->file);
+          (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
+            "%s:%s",blob_info->magick,unique);
+          image=ReadImage(clone_info,exception);
+          if (image != (Image *) NULL)
+            {
+              Image
+                *images;
+
+              /*
+                Restore original filenames and image format.
+              */
+              for (images=GetFirstImageInList(image); images != (Image *) NULL; )
+              {
+                (void) CopyMagickString(images->filename,image_info->filename,
+                  MagickPathExtent);
+                (void) CopyMagickString(images->magick_filename,
+                  image_info->filename,MagickPathExtent);
+                (void) CopyMagickString(images->magick,magick_info->name,
+                  MagickPathExtent);
+                (void) CloseBlob(images);
+                images=GetNextImageInList(images);
+              }
+            }
+        }
+      clone_info=DestroyImageInfo(clone_info);
+      blob=(unsigned char *) RelinquishMagickMemory(blob);
+      (void) RelinquishUniqueFileResource(unique);
+    }
+  blob_info=DestroyImageInfo(blob_info);
+  return(image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +  W r i t e B l o b                                                          %
 %                                                                             %
 %                                                                             %
@@ -4128,8 +5159,7 @@ MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
 %
 %  The format of the WriteBlob method is:
 %
-%      ssize_t WriteBlob(Image *image,const size_t length,
-%        const unsigned char *data)
+%      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
 %
 %  A description of each parameter follows:
 %
@@ -4142,7 +5172,7 @@ MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
 %
 */
 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
-  const unsigned char *data)
+  const void *data)
 {
   int
     c;
@@ -4154,18 +5184,19 @@ MagickExport ssize_t WriteBlob(Image *image,const size_t length,
     count;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  assert(data != (const unsigned char *) NULL);
+  assert(image->signature == MagickCoreSignature);
   assert(image->blob != (BlobInfo *) NULL);
   assert(image->blob->type != UndefinedStream);
   if (length == 0)
     return(0);
+  assert(data != (const void *) NULL);
   count=0;
-  p=data;
+  p=(const unsigned char *) data;
   switch (image->blob->type)
   {
     case UndefinedStream:
       break;
+    case StandardStream:
     case FileStream:
     case PipeStream:
     {
@@ -4295,6 +5326,14 @@ MagickExport ssize_t WriteBlob(Image *image,const size_t length,
       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
         image->blob->length=(size_t) image->blob->offset;
       count=(ssize_t) length;
+      break;
+    }
+    case CustomStream:
+    {
+      if (image->blob->custom_stream->writer != (CustomStreamHandler) NULL)
+        count=image->blob->custom_stream->writer((const unsigned char *) data,
+          length,image->blob->custom_stream->data);
+      break;
     }
   }
   return(count);
@@ -4328,7 +5367,7 @@ MagickExport ssize_t WriteBlob(Image *image,const size_t length,
 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   return(WriteBlobStream(image,1,&value));
 }
 \f
@@ -4384,8 +5423,8 @@ MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
-%  specified by the endian member of the image structure.
+%  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
+%  byte-order specified by the endian member of the image structure.
 %
 %  The format of the WriteBlobLong method is:
 %
@@ -4404,7 +5443,7 @@ MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
     buffer[4];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->endian == LSBEndian)
     {
       buffer[0]=(unsigned char) value;
@@ -4451,7 +5490,7 @@ MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
     buffer[2];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->endian == LSBEndian)
     {
       buffer[0]=(unsigned char) value;
@@ -4474,7 +5513,7 @@ MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
+%  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
 %  least-significant byte first order.
 %
 %  The format of the WriteBlobLSBLong method is:
@@ -4494,7 +5533,7 @@ MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
     buffer[4];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   buffer[0]=(unsigned char) value;
   buffer[1]=(unsigned char) (value >> 8);
   buffer[2]=(unsigned char) (value >> 16);
@@ -4513,7 +5552,7 @@ MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
+%  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
 %  least-significant byte first order.
 %
 %  The format of the WriteBlobLSBShort method is:
@@ -4533,7 +5572,7 @@ MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
     buffer[2];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   buffer[0]=(unsigned char) value;
   buffer[1]=(unsigned char) (value >> 8);
   return(WriteBlobStream(image,2,buffer));
@@ -4544,13 +5583,110 @@ MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
 %                                                                             %
 %                                                                             %
 %                                                                             %
++  W r i t e B l o b L S B S i g n e d L o n g                                %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
+%  least-significant byte first order.
+%
+%  The format of the WriteBlobLSBSignedLong method is:
+%
+%      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o value: Specifies the value to write.
+%
+*/
+MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
+{
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
+  unsigned char
+    buffer[4];
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  quantum.signed_value=value;
+  buffer[0]=(unsigned char) quantum.unsigned_value;
+  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
+  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
+  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
+  return(WriteBlobStream(image,4,buffer));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   W r i t e B l o b L S B S i g n e d S h o r t                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
+%  in least-significant byte first order.
+%
+%  The format of the WriteBlobLSBSignedShort method is:
+%
+%      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o value:  Specifies the value to write.
+%
+*/
+MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
+  const signed short value)
+{
+  union
+  {
+    unsigned short
+      unsigned_value;
+
+    signed short
+      signed_value;
+  } quantum;
+
+  unsigned char
+    buffer[2];
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  quantum.signed_value=value;
+  buffer[0]=(unsigned char) quantum.unsigned_value;
+  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
+  return(WriteBlobStream(image,2,buffer));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +  W r i t e B l o b M S B L o n g                                            %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
+%  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
 %  most-significant byte first order.
 %
 %  The format of the WriteBlobMSBLong method is:
@@ -4570,7 +5706,7 @@ MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
     buffer[4];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   buffer[0]=(unsigned char) (value >> 24);
   buffer[1]=(unsigned char) (value >> 16);
   buffer[2]=(unsigned char) (value >> 8);
@@ -4610,7 +5746,7 @@ MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
     buffer[8];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   buffer[0]=(unsigned char) (value >> 56);
   buffer[1]=(unsigned char) (value >> 48);
   buffer[2]=(unsigned char) (value >> 40);
@@ -4627,13 +5763,110 @@ MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
++  W r i t e B l o b M S B S i g n e d L o n g                                %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
+%  most-significant byte first order.
+%
+%  The format of the WriteBlobMSBSignedLong method is:
+%
+%      ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o value: Specifies the value to write.
+%
+*/
+MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
+{
+  union
+  {
+    unsigned int
+      unsigned_value;
+
+    signed int
+      signed_value;
+  } quantum;
+
+  unsigned char
+    buffer[4];
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  quantum.signed_value=value;
+  buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
+  buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
+  buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
+  buffer[3]=(unsigned char) quantum.unsigned_value;
+  return(WriteBlobStream(image,4,buffer));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
++   W r i t e B l o b M S B S i g n e d S h o r t                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
+%  in most-significant byte first order.
+%
+%  The format of the WriteBlobMSBSignedShort method is:
+%
+%      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
+%
+%  A description of each parameter follows.
+%
+%    o image: the image.
+%
+%    o value:  Specifies the value to write.
+%
+*/
+MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
+  const signed short value)
+{
+  union
+  {
+    unsigned short
+      unsigned_value;
+
+    signed short
+      signed_value;
+  } quantum;
+
+  unsigned char
+    buffer[2];
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  quantum.signed_value=value;
+  buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
+  buffer[1]=(unsigned char) quantum.unsigned_value;
+  return(WriteBlobStream(image,2,buffer));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +  W r i t e B l o b M S B S h o r t                                          %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
+%  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
 %  most-significant byte first order.
 %
 %  The format of the WriteBlobMSBShort method is:
@@ -4653,7 +5886,7 @@ MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
     buffer[2];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   buffer[0]=(unsigned char) (value >> 8);
   buffer[1]=(unsigned char) value;
   return(WriteBlobStream(image,2,buffer));
@@ -4687,7 +5920,7 @@ MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
 {
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(string != (const char *) NULL);
   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
 }