text: /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %                         BBBB   L       OOO   BBBB                           %
  %                         B   B  L      O   O  B   B                          %
  %                         BBBB   L      O   O  BBBB                           %
  %                         B   B  L      O   O  B   B                          %
  %                         BBBB   LLLLL   OOO   BBBB                           %
  %                                                                             %
  %                                                                             %
  %                     MagickCore Binary Large OBjectS Methods                 %
  %                                                                             %
  %                              Software Design                                %
  %                                   Cristy                                    %
  %                                 July 1999                                   %
  %                                                                             %
  %                                                                             %
  %  Copyright 1999-2019 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                                            %
  %                                                                             %
  %    https://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,          %
  %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
  %  See the License for the specific language governing permissions and        %
  %  limitations under the License.                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %
  %
  */
  
  /*
    Include declarations.
  */
  #ifdef __VMS
  #include  <types.h>
  #include  <mman.h>
  #endif
  #include "magick/studio.h"
  #include "magick/blob.h"
  #include "magick/blob-private.h"
  #include "magick/cache.h"
  #include "magick/client.h"
  #include "magick/constitute.h"
  #include "magick/delegate.h"
  #include "magick/exception.h"
  #include "magick/exception-private.h"
  #include "magick/geometry.h"
  #include "magick/image-private.h"
  #include "magick/list.h"
  #include "magick/locale_.h"
  #include "magick/log.h"
  #include "magick/magick.h"
  #include "magick/memory_.h"
  #include "magick/nt-base-private.h"
  #include "magick/option.h"
  #include "magick/policy.h"
  #include "magick/resource_.h"
  #include "magick/semaphore.h"
  #include "magick/string_.h"
  #include "magick/string-private.h"
  #include "magick/timer-private.h"
  #include "magick/token.h"
  #include "magick/utility.h"
  #include "magick/utility-private.h"
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
  #include "zlib.h"
  #endif
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
  #include "bzlib.h"
  #endif
  
  /*
    Define declarations.
  */
  #define MagickMaxBlobExtent  65541
  #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
  # define MAP_ANONYMOUS  MAP_ANON
  #endif
  #if !defined(MAP_FAILED)
  #define MAP_FAILED  ((void *) -1)
  #endif
  #if defined(__OS2__)
  #include <io.h>
  #define _O_BINARY O_BINARY
  #endif
  
  /*
    Typedef declarations.
  */
  typedef union FileInfo
  {
    FILE
      *file;
  
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
    gzFile
      gzfile;
  #endif
  
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
    BZFILE
      *bzfile;
  #endif
  } FileInfo;
  
  struct _BlobInfo
  {
    size_t
      length,
      extent,
      quantum;
  
    BlobMode
      mode;
  
    MagickBooleanType
      mapped,
      eof;
  
    int
      error;
  
    MagickOffsetType
      offset;
  
    MagickSizeType
      size;
  
    MagickBooleanType
      exempt,
      synchronize,
      status,
      temporary;
  
    StreamType
      type;
  
    FileInfo
      file_info;
  
    struct stat
      properties;
  
    StreamHandler
      stream;
  
    unsigned char
      *data;
  
    MagickBooleanType
      debug;
  
    SemaphoreInfo
      *semaphore;
  
    ssize_t
      reference_count;
  
    size_t
      signature;
  };
  
  /*
    Forward declarations.
  */
  static int
    SyncBlob(Image *);
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   A t t a c h B l o b                                                       %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  AttachBlob() attaches a blob to the BlobInfo structure.
  %
  %  The format of the AttachBlob method is:
  %
  %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
  %
  %  A description of each parameter follows:
  %
  %    o blob_info: Specifies a pointer to a BlobInfo structure.
  %
  %    o blob: the address of a character stream in one of the image formats
  %      understood by ImageMagick.
  %
  %    o length: This size_t integer reflects the length in bytes of the blob.
  %
  */
  MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
    const size_t length)
  {
    assert(blob_info != (BlobInfo *) NULL);
    if (blob_info->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    blob_info->length=length;
    blob_info->extent=length;
    blob_info->quantum=(size_t) MagickMaxBlobExtent;
    blob_info->offset=0;
    blob_info->type=BlobStream;
    blob_info->file_info.file=(FILE *) NULL;
    blob_info->data=(unsigned char *) blob;
    blob_info->mapped=MagickFalse;
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   B l o b T o F i l e                                                       %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
  %  occurs otherwise MagickTrue.
  %
  %  The format of the BlobToFile method is:
  %
  %       MagickBooleanType BlobToFile(char *filename,const void *blob,
  %         const size_t length,ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o filename: Write the blob to this file.
  %
  %    o blob: the address of a blob.
  %
  %    o length: This length in bytes of the blob.
  %
  %    o exception: return any errors or warnings in this structure.
  %
  */
  MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
    const size_t length,ExceptionInfo *exception)
  {
    int
      file;
  
    register size_t
      i;
  
    ssize_t
      count;
  
    assert(filename != (const char *) NULL);
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
    assert(blob != (const void *) NULL);
    if (*filename == '\0')
      file=AcquireUniqueFileResource(filename);
    else
      file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
    if (file == -1)
      {
        ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
        return(MagickFalse);
      }
    for (i=0; i < length; i+=count)
    {
      count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
        SSIZE_MAX));
      if (count <= 0)
        {
          count=0;
          if (errno != EINTR)
            break;
        }
    }
    file=close(file);
    if ((file == -1) || (i < length))
      {
        ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
        return(MagickFalse);
      }
    return(MagickTrue);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   B l o b T o I m a g e                                                     %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  BlobToImage() implements direct to memory image formats.  It returns the
  %  blob as an image.
  %
  %  The format of the BlobToImage method is:
  %
  %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
  %        const size_t length,ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o image_info: the image info.
  %
  %    o blob: the address of a character stream in one of the image formats
  %      understood by ImageMagick.
  %
  %    o length: This size_t integer reflects the length in bytes of the blob.
  %
  %    o exception: return any errors or warnings in this structure.
  %
  */
  MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
    const size_t length,ExceptionInfo *exception)
  {
    const MagickInfo
      *magick_info;
  
    Image
      *image;
  
    ImageInfo
      *blob_info,
      *clone_info;
  
    MagickBooleanType
      status;
  
    assert(image_info != (ImageInfo *) NULL);
    assert(image_info->signature == MagickCoreSignature);
    if (image_info->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
        image_info->filename);
    assert(exception != (ExceptionInfo *) NULL);
    if ((blob == (const void *) NULL) || (length == 0))
      {
        (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
          "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
        return((Image *) NULL);
      }
    blob_info=CloneImageInfo(image_info);
    blob_info->blob=(void *) blob;
    blob_info->length=length;
    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);
      }
    if (GetMagickBlobSupport(magick_info) != MagickFalse)
      {
        char
          filename[MagickPathExtent];
  
        /*
          Native blob support for this image format.
        */
        (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
        (void) FormatLocaleString(blob_info->filename,MaxTextExtent,"%s:%s",
          blob_info->magick,filename);
        image=ReadImage(blob_info,exception);
        if (image != (Image *) NULL)
          (void) DetachBlob(image->blob);
        blob_info=DestroyImageInfo(blob_info);
        return(image);
      }
    /*
      Write blob to a temporary file on disk.
    */
    blob_info->blob=(void *) NULL;
    blob_info->length=0;
    *blob_info->filename='\0';
    status=BlobToFile(blob_info->filename,blob,length,exception);
    if (status == MagickFalse)
      {
        (void) RelinquishUniqueFileResource(blob_info->filename);
        blob_info=DestroyImageInfo(blob_info);
        return((Image *) NULL);
      }
    clone_info=CloneImageInfo(blob_info);
    (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
      blob_info->magick,blob_info->filename);
    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,
            MaxTextExtent);
          (void) CopyMagickString(images->magick_filename,image_info->filename,
            MaxTextExtent);
          (void) CopyMagickString(images->magick,magick_info->name,MaxTextExtent);
          images=GetNextImageInList(images);
        }
      }
    clone_info=DestroyImageInfo(clone_info);
    (void) RelinquishUniqueFileResource(blob_info->filename);
    blob_info=DestroyImageInfo(blob_info);
    return(image);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   C l o n e B l o b I n f o                                                 %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
  %  blob info is NULL, a new one.
  %
  %  The format of the CloneBlobInfo method is:
  %
  %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
  %
  %  A description of each parameter follows:
  %
  %    o blob_info: the blob info.
  %
  */
  MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
  {
    BlobInfo
      *clone_info;
  
    SemaphoreInfo
      *semaphore;
  
    clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
    GetBlobInfo(clone_info);
    if (blob_info == (BlobInfo *) NULL)
      return(clone_info);
    semaphore=clone_info->semaphore;
    (void) memcpy(clone_info,blob_info,sizeof(*clone_info));
    if (blob_info->mapped != MagickFalse)
      (void) AcquireMagickResource(MapResource,blob_info->length);
    clone_info->semaphore=semaphore;
    LockSemaphoreInfo(clone_info->semaphore);
    clone_info->reference_count=1;
    UnlockSemaphoreInfo(clone_info->semaphore);
    return(clone_info);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   C l o s e B l o b                                                         %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  CloseBlob() closes a stream associated with the image.
  %
  %  The format of the CloseBlob method is:
  %
  %      MagickBooleanType CloseBlob(Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport MagickBooleanType CloseBlob(Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    int
      status;
  
    /*
      Close image file.
    */
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    blob_info=image->blob;
    if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
      return(MagickTrue);
    status=SyncBlob(image);
    switch (blob_info->type)
    {
      case UndefinedStream:
      case StandardStream:
        break;
      case FileStream:
      case PipeStream:
      {
        if (blob_info->synchronize != MagickFalse)
          status=fsync(fileno(blob_info->file_info.file));
        status=ferror(blob_info->file_info.file);
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        (void) gzerror(blob_info->file_info.gzfile,&status);
  #endif
        break;
      }
      case BZipStream:
      {
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
        (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
  #endif
        break;
      }
      case FifoStream:
        break;
      case BlobStream:
      {
        if (blob_info->file_info.file != (FILE *) NULL)
          {
            if (blob_info->synchronize != MagickFalse)
              status=fsync(fileno(blob_info->file_info.file));
            status=ferror(blob_info->file_info.file);
          }
        break;
      }
    }
    blob_info->status=status < 0 ? MagickTrue : MagickFalse;
    blob_info->size=GetBlobSize(image);
    image->extent=blob_info->size;
    blob_info->eof=MagickFalse;
    blob_info->error=0;
    if (blob_info->exempt != MagickFalse)
      {
        blob_info->type=UndefinedStream;
        return(blob_info->status);
      }
    switch (blob_info->type)
    {
      case UndefinedStream:
      case StandardStream:
        break;
      case FileStream:
      {
        if (fileno(blob_info->file_info.file) != -1)
          status=fclose(blob_info->file_info.file);
        break;
      }
      case PipeStream:
      {
  #if defined(MAGICKCORE_HAVE_PCLOSE)
        status=pclose(blob_info->file_info.file);
  #endif
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        status=gzclose(blob_info->file_info.gzfile);
  #endif
        break;
      }
      case BZipStream:
      {
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
        BZ2_bzclose(blob_info->file_info.bzfile);
  #endif
        break;
      }
      case FifoStream:
        break;
      case BlobStream:
      {
        if (blob_info->file_info.file != (FILE *) NULL)
          status=fclose(blob_info->file_info.file);
        break;
      }
    }
    (void) DetachBlob(blob_info);
    blob_info->status=status < 0 ? MagickTrue : MagickFalse;
    return(blob_info->status);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   D e s t r o y B l o b                                                     %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  DestroyBlob() deallocates memory associated with a blob.
  %
  %  The format of the DestroyBlob method is:
  %
  %      void DestroyBlob(Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport void DestroyBlob(Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    MagickBooleanType
      destroy;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->signature == MagickCoreSignature);
    blob_info=image->blob;
    destroy=MagickFalse;
    LockSemaphoreInfo(blob_info->semaphore);
    blob_info->reference_count--;
    assert(blob_info->reference_count >= 0);
    if (blob_info->reference_count == 0)
      destroy=MagickTrue;
    UnlockSemaphoreInfo(blob_info->semaphore);
    if (destroy == MagickFalse)
      {
        image->blob=(BlobInfo *) NULL;
        return;
      }
    (void) CloseBlob(image);
    if (blob_info->mapped != MagickFalse)
      {
        (void) UnmapBlob(blob_info->data,blob_info->length);
        RelinquishMagickResource(MapResource,blob_info->length);
      }
    if (blob_info->semaphore != (SemaphoreInfo *) NULL)
      DestroySemaphoreInfo(&blob_info->semaphore);
    blob_info->signature=(~MagickCoreSignature);
    image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   D e t a c h B l o b                                                       %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  DetachBlob() detaches a blob from the BlobInfo structure.
  %
  %  The format of the DetachBlob method is:
  %
  %      unsigned char *DetachBlob(BlobInfo *blob_info)
  %
  %  A description of each parameter follows:
  %
  %    o blob_info: Specifies a pointer to a BlobInfo structure.
  %
  */
  MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
  {
    unsigned char
      *data;
  
    assert(blob_info != (BlobInfo *) NULL);
    if (blob_info->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    if (blob_info->mapped != MagickFalse)
      {
        (void) UnmapBlob(blob_info->data,blob_info->length);
        blob_info->data=NULL;
        RelinquishMagickResource(MapResource,blob_info->length);
      }
    blob_info->mapped=MagickFalse;
    blob_info->length=0;
    blob_info->offset=0;
    blob_info->eof=MagickFalse;
    blob_info->error=0;
    blob_info->exempt=MagickFalse;
    blob_info->type=UndefinedStream;
    blob_info->file_info.file=(FILE *) NULL;
    data=blob_info->data;
    blob_info->data=(unsigned char *) NULL;
    blob_info->stream=(StreamHandler) NULL;
    return(data);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   D i s a s s o c i a t e B l o b                                           %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  DisassociateBlob() disassociates the image stream.  It checks if the
  %  blob of the specified image is referenced by other images. If the reference
  %  count is higher then 1 a new blob is assigned to the specified image.
  %
  %  The format of the DisassociateBlob method is:
  %
  %      void DisassociateBlob(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickPrivate void DisassociateBlob(Image *image)
  {
    BlobInfo
      *magick_restrict blob_info,
      *clone_info;
  
    MagickBooleanType
      clone;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->signature == MagickCoreSignature);
    blob_info=image->blob;
    clone=MagickFalse;
    LockSemaphoreInfo(blob_info->semaphore);
    assert(blob_info->reference_count >= 0);
    if (blob_info->reference_count > 1)
      clone=MagickTrue;
    UnlockSemaphoreInfo(blob_info->semaphore);
    if (clone == MagickFalse)
      return;
    clone_info=CloneBlobInfo(blob_info);
    DestroyBlob(image);
    image->blob=clone_info;
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  D i s c a r d B l o b B y t e s                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  DiscardBlobBytes() discards bytes in a blob.
  %
  %  The format of the DiscardBlobBytes method is:
  %
  %      MagickBooleanType DiscardBlobBytes(Image *image,
  %        const MagickSizeType length)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o length:  the number of bytes to skip.
  %
  */
  MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
    const MagickSizeType length)
  {
    register MagickOffsetType
      i;
  
    size_t
      quantum;
  
    ssize_t
      count;
  
    unsigned char
      buffer[16384];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (length != (MagickSizeType) ((MagickOffsetType) length))
      return(MagickFalse);
    count=0;
    for (i=0; i < (MagickOffsetType) length; i+=count)
    {
      quantum=(size_t) MagickMin(length-i,sizeof(buffer));
      (void) ReadBlobStream(image,quantum,buffer,&count);
      if (count <= 0)
        {
          count=0;
          if (errno != EINTR)
            break;
        }
    }
    return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   D u p l i c a t e s B l o b                                               %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  DuplicateBlob() duplicates a blob descriptor.
  %
  %  The format of the DuplicateBlob method is:
  %
  %      void DuplicateBlob(Image *image,const Image *duplicate)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o duplicate: the duplicate image.
  %
  */
  MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
  {
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(duplicate != (Image *) NULL);
    assert(duplicate->signature == MagickCoreSignature);
    DestroyBlob(image);
    image->blob=ReferenceBlob(duplicate->blob);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  E O F B l o b                                                              %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  EOFBlob() returns a non-zero value when EOF has been detected reading from
  %  a blob or file.
  %
  %  The format of the EOFBlob method is:
  %
  %      int EOFBlob(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport int EOFBlob(const Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    switch (blob_info->type)
    {
      case UndefinedStream:
      case StandardStream:
        break;
      case FileStream:
      case PipeStream:
      {
        blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
          MagickFalse;
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
          MagickFalse;
  #endif
        break;
      }
      case BZipStream:
      {
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
        int
          status;
  
        status=0;
        (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
        blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
  #endif
        break;
      }
      case FifoStream:
      {
        blob_info->eof=MagickFalse;
        break;
      }
      case BlobStream:
        break;
    }
    return((int) blob_info->eof);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  E r r o r B l o b                                                          %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ErrorBlob() returns a non-zero value when an error has been detected reading
  %  from a blob or file.
  %
  %  The format of the ErrorBlob method is:
  %
  %      int ErrorBlob(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport int ErrorBlob(const Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    switch (blob_info->type)
    {
      case UndefinedStream:
      case StandardStream:
        break;
      case FileStream:
      case PipeStream:
      {
        blob_info->error=ferror(blob_info->file_info.file);
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
  #endif
        break;
      }
      case BZipStream:
      {
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
        (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
  #endif
        break;
      }
      case FifoStream:
      {
        blob_info->error=0;
        break;
      }
      case BlobStream:
        break;
    }
    return(blob_info->error);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   F i l e T o B l o b                                                       %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  FileToBlob() returns the contents of a file as a buffer terminated with
  %  the '\0' character.  The length of the buffer (not including the extra
  %  terminating '\0' character) is returned via the 'length' parameter.  Free
  %  the buffer with RelinquishMagickMemory().
  %
  %  The format of the FileToBlob method is:
  %
  %      unsigned char *FileToBlob(const char *filename,const size_t extent,
  %        size_t *length,ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
  %      an error occurs NULL is returned.
  %
  %    o filename: the filename.
  %
  %    o extent:  The maximum length of the blob.
  %
  %    o length: On return, this reflects the actual length of the blob.
  %
  %    o exception: return any errors or warnings in this structure.
  %
  */
  MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
    size_t *length,ExceptionInfo *exception)
  {
    int
      file;
  
    MagickBooleanType
      status;
  
    MagickOffsetType
      offset;
  
    register size_t
      i;
  
    ssize_t
      count;
  
    struct stat
      attributes;
  
    unsigned char
      *blob;
  
    void
      *map;
  
    assert(filename != (const char *) NULL);
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
    assert(exception != (ExceptionInfo *) NULL);
    *length=0;
    status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
    if (status == MagickFalse)
      {
        errno=EPERM;
        (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
          "NotAuthorized","`%s'",filename);
        return(NULL);
      }
    file=fileno(stdin);
    if (LocaleCompare(filename,"-") != 0)
      {
        status=GetPathAttributes(filename,&attributes);
        if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
          {
            ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
            return(NULL);
          }
        file=open_utf8(filename,O_RDONLY | O_BINARY,0);
      }
    if (file == -1)
      {
        ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
        return((unsigned char *) NULL);
      }
    offset=(MagickOffsetType) lseek(file,0,SEEK_END);
    count=0;
    if ((file == fileno(stdin)) || (offset < 0) ||
        (offset != (MagickOffsetType) ((ssize_t) offset)))
      {
        size_t
          quantum;
  
        struct stat
          file_stats;
  
        /*
          Stream is not seekable.
        */
        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(file_stats.st_size,MagickMaxBufferExtent);
        blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
        for (i=0; blob != (unsigned char *) NULL; i+=count)
        {
          count=read(file,blob+i,quantum);
          if (count <= 0)
            {
              count=0;
              if (errno != EINTR)
                break;
            }
          if (~((size_t) i) < (quantum+1))
            {
              blob=(unsigned char *) RelinquishMagickMemory(blob);
              break;
            }
          blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
            sizeof(*blob));
          if ((size_t) (i+count) >= extent)
            break;
        }
        if (LocaleCompare(filename,"-") != 0)
          file=close(file);
        if (blob == (unsigned char *) NULL)
          {
            (void) ThrowMagickException(exception,GetMagickModule(),
              ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
            return((unsigned char *) NULL);
          }
        if (file == -1)
          {
            blob=(unsigned char *) RelinquishMagickMemory(blob);
            ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
            return((unsigned char *) NULL);
          }
        *length=(size_t) MagickMin(i+count,extent);
        blob[*length]='\0';
        return(blob);
      }
    *length=(size_t) MagickMin(offset,(MagickOffsetType)
      MagickMin(extent,SSIZE_MAX));
    blob=(unsigned char *) NULL;
    if (~(*length) >= (MaxTextExtent-1))
      blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
        sizeof(*blob));
    if (blob == (unsigned char *) NULL)
      {
        file=close(file);
        (void) ThrowMagickException(exception,GetMagickModule(),
          ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
        return((unsigned char *) NULL);
      }
    map=MapBlob(file,ReadMode,0,*length);
    if (map != (unsigned char *) NULL)
      {
        (void) memcpy(blob,map,*length);
        (void) UnmapBlob(map,*length);
      }
    else
      {
        (void) lseek(file,0,SEEK_SET);
        for (i=0; i < *length; i+=count)
        {
          count=read(file,blob+i,MagickMin(*length-i,(size_t) SSIZE_MAX));
          if (count <= 0)
            {
              count=0;
              if (errno != EINTR)
                break;
            }
        }
        if (i < *length)
          {
            file=close(file)-1;
            blob=(unsigned char *) RelinquishMagickMemory(blob);
            ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
            return((unsigned char *) NULL);
          }
      }
    blob[*length]='\0';
    if (LocaleCompare(filename,"-") != 0)
      file=close(file);
    if (file == -1)
      {
        blob=(unsigned char *) RelinquishMagickMemory(blob);
        ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
      }
    return(blob);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   F i l e T o I m a g e                                                     %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  FileToImage() write the contents of a file to an image.
  %
  %  The format of the FileToImage method is:
  %
  %      MagickBooleanType FileToImage(Image *,const char *filename)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o filename: the filename.
  %
  */
  
  static inline ssize_t WriteBlobStream(Image *image,const size_t length,
    const unsigned char *data)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    MagickSizeType
      extent;
  
    register unsigned char
      *q;
  
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    assert(data != (void *) NULL);
    blob_info=image->blob;
    if (blob_info->type != BlobStream)
      return(WriteBlob(image,length,data));
    extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
    if (extent >= blob_info->extent)
      {
        extent=blob_info->extent+blob_info->quantum+length;
        blob_info->quantum<<=1;
        if (SetBlobExtent(image,extent) == MagickFalse)
          return(0);
      }
    q=blob_info->data+blob_info->offset;
    (void) memcpy(q,data,length);
    blob_info->offset+=length;
    if (blob_info->offset >= (MagickOffsetType) blob_info->length)
      blob_info->length=(size_t) blob_info->offset;
    return((ssize_t) length);
  }
  
  MagickExport MagickBooleanType FileToImage(Image *image,const char *filename)
  {
    int
      file;
  
    MagickBooleanType
      status;
  
    size_t
      length,
      quantum;
  
    ssize_t
      count;
  
    struct stat
      file_stats;
  
    unsigned char
      *blob;
  
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(filename != (const char *) NULL);
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
    status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename);
    if (status == MagickFalse)
      {
        errno=EPERM;
        (void) ThrowMagickException(&image->exception,GetMagickModule(),
          PolicyError,"NotAuthorized","`%s'",filename);
        return(MagickFalse);
      }
    file=fileno(stdin);
    if (LocaleCompare(filename,"-") != 0)
      file=open_utf8(filename,O_RDONLY | O_BINARY,0);
    if (file == -1)
      {
        ThrowFileException(&image->exception,BlobError,"UnableToOpenBlob",
          filename);
        return(MagickFalse);
      }
    quantum=(size_t) 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));
    if (blob == (unsigned char *) NULL)
      {
        file=close(file);
        ThrowFileException(&image->exception,ResourceLimitError,
          "MemoryAllocationFailed",filename);
        return(MagickFalse);
      }
    for ( ; ; )
    {
      count=read(file,blob,quantum);
      if (count <= 0)
        {
          count=0;
          if (errno != EINTR)
            break;
        }
      length=(size_t) count;
      count=WriteBlobStream(image,length,blob);
      if (count != (ssize_t) length)
        {
          ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
            filename);
          break;
        }
    }
    file=close(file);
    if (file == -1)
      ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob",
        filename);
    blob=(unsigned char *) RelinquishMagickMemory(blob);
    return(MagickTrue);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   G e t B l o b E r r o r                                                   %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  GetBlobError() returns MagickTrue if the blob associated with the specified
  %  image encountered an error.
  %
  %  The format of the GetBlobError method is:
  %
  %       MagickBooleanType GetBlobError(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport MagickBooleanType GetBlobError(const Image *image)
  {
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    return(image->blob->status);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   G e t B l o b F i l e H a n d l e                                         %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  GetBlobFileHandle() returns the file handle associated with the image blob.
  %
  %  The format of the GetBlobFile method is:
  %
  %      FILE *GetBlobFileHandle(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport FILE *GetBlobFileHandle(const Image *image)
  {
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    return(image->blob->file_info.file);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   G e t B l o b I n f o                                                     %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  GetBlobInfo() initializes the BlobInfo structure.
  %
  %  The format of the GetBlobInfo method is:
  %
  %      void GetBlobInfo(BlobInfo *blob_info)
  %
  %  A description of each parameter follows:
  %
  %    o blob_info: Specifies a pointer to a BlobInfo structure.
  %
  */
  MagickExport void GetBlobInfo(BlobInfo *blob_info)
  {
    assert(blob_info != (BlobInfo *) NULL);
    (void) memset(blob_info,0,sizeof(*blob_info));
    blob_info->type=UndefinedStream;
    blob_info->quantum=(size_t) MagickMaxBlobExtent;
    blob_info->properties.st_mtime=GetMagickTime();
    blob_info->properties.st_ctime=blob_info->properties.st_mtime;
    blob_info->debug=IsEventLogging();
    blob_info->reference_count=1;
    blob_info->semaphore=AllocateSemaphoreInfo();
    blob_info->signature=MagickCoreSignature;
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %  G e t B l o b P r o p e r t i e s                                          %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  GetBlobProperties() returns information about an image blob.
  %
  %  The format of the GetBlobProperties method is:
  %
  %      const struct stat *GetBlobProperties(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport const struct stat *GetBlobProperties(const Image *image)
  {
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    return(&image->blob->properties);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  G e t B l o b S i z e                                                      %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  GetBlobSize() returns the current length of the image file or blob; zero is
  %  returned if the size cannot be determined.
  %
  %  The format of the GetBlobSize method is:
  %
  %      MagickSizeType GetBlobSize(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport MagickSizeType GetBlobSize(const Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    MagickSizeType
      extent;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(image->blob != (BlobInfo *) NULL);
    blob_info=image->blob;
    extent=0;
    switch (blob_info->type)
    {
      case UndefinedStream:
      case StandardStream:
      {
        extent=blob_info->size;
        break;
      }
      case FileStream:
      {
        int
          file_descriptor;
  
        extent=(MagickSizeType) blob_info->properties.st_size;
        if (extent == 0)
          extent=blob_info->size;
        file_descriptor=fileno(blob_info->file_info.file);
        if (file_descriptor == -1)
          break;
        if (fstat(file_descriptor,&blob_info->properties) == 0)
          extent=(MagickSizeType) blob_info->properties.st_size;
        break;
      }
      case PipeStream:
      {
        extent=blob_info->size;
        break;
      }
      case ZipStream:
      case BZipStream:
      {
        MagickBooleanType
          status;
  
        status=GetPathAttributes(image->filename,&blob_info->properties);
        if (status != MagickFalse)
          extent=(MagickSizeType) blob_info->properties.st_size;
        break;
      }
      case FifoStream:
        break;
      case BlobStream:
      {
        extent=(MagickSizeType) blob_info->length;
        break;
      }
    }
    return(extent);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   G e t B l o b S t r e a m D a t a                                         %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  GetBlobStreamData() returns the stream data for the image.
  %
  %  The format of the GetBlobStreamData method is:
  %
  %      unsigned char *GetBlobStreamData(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport unsigned char *GetBlobStreamData(const Image *image)
  {
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    return(image->blob->data);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   G e t B l o b S t r e a m H a n d l e r                                   %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  GetBlobStreamHandler() returns the stream handler for the image.
  %
  %  The format of the GetBlobStreamHandler method is:
  %
  %      StreamHandler GetBlobStreamHandler(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
  {
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    return(image->blob->stream);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   I m a g e T o B l o b                                                     %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ImageToBlob() implements direct to memory image formats.  It returns the
  %  image as a formatted blob and its length.  The magick member of the Image
  %  structure determines the format of the returned blob (GIF, JPEG, PNG,
  %  etc.).  This method is the equivalent of WriteImage(), but writes the
  %  formatted "file" to a memory buffer rather than to an actual file.
  %
  %  The format of the ImageToBlob method is:
  %
  %      unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
  %        size_t *length,ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o image_info: the image info.
  %
  %    o image: the image.
  %
  %    o length: return the actual length of the blob.
  %
  %    o exception: return any errors or warnings in this structure.
  %
  */
  MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
    Image *image,size_t *length,ExceptionInfo *exception)
  {
    const MagickInfo
      *magick_info;
  
    ImageInfo
      *blob_info;
  
    MagickBooleanType
      status;
  
    unsigned char
      *blob;
  
    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(exception != (ExceptionInfo *) NULL);
    *length=0;
    blob=(unsigned char *) 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,MaxTextExtent);
    magick_info=GetMagickInfo(image->magick,exception);
    if (magick_info == (const MagickInfo *) NULL)
      {
        (void) ThrowMagickException(exception,GetMagickModule(),
          MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
          image->magick);
        blob_info=DestroyImageInfo(blob_info);
        return(blob);
      }
    (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
    if (GetMagickBlobSupport(magick_info) != MagickFalse)
      {
        /*
          Native blob support for this image format.
        */
        blob_info->length=0;
        blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
          sizeof(unsigned char));
        if (blob_info->blob == (void *) NULL)
          (void) ThrowMagickException(exception,GetMagickModule(),
            ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
        else
          {
            (void) CloseBlob(image);
            image->blob->exempt=MagickTrue;
            *image->filename='\0';
            status=WriteImage(blob_info,image);
            InheritException(exception,&image->exception);
            *length=image->blob->length;
            blob=DetachBlob(image->blob);
            if (blob == (unsigned char *) NULL)
              blob_info->blob=RelinquishMagickMemory(blob_info->blob);
            else if (status == MagickFalse)
              blob=(unsigned char *) RelinquishMagickMemory(blob);
            else
              blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
                sizeof(*blob));
          }
      }
    else
      {
        char
          unique[MaxTextExtent];
  
        int
          file;
  
        /*
          Write file to disk in blob image format.
        */
        file=AcquireUniqueFileResource(unique);
        if (file == -1)
          {
            ThrowFileException(exception,BlobError,"UnableToWriteBlob",
              image_info->filename);
          }
        else
          {
            blob_info->file=fdopen(file,"wb");
            if (blob_info->file != (FILE *) NULL)
              {
                (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
                  image->magick,unique);
                status=WriteImage(blob_info,image);
                (void) CloseBlob(image);
                (void) fclose(blob_info->file);
                if (status == MagickFalse)
                  InheritException(exception,&image->exception);
                else
                  blob=FileToBlob(unique,~0UL,length,exception);
              }
            (void) RelinquishUniqueFileResource(unique);
          }
      }
    blob_info=DestroyImageInfo(blob_info);
    return(blob);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   I m a g e T o F i l e                                                     %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
  %  occurs otherwise MagickTrue.
  %
  %  The format of the ImageToFile method is:
  %
  %       MagickBooleanType ImageToFile(Image *image,char *filename,
  %         ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o filename: Write the image to this file.
  %
  %    o exception: return any errors or warnings in this structure.
  %
  */
  MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
    ExceptionInfo *exception)
  {
    int
      file;
  
    register const unsigned char
      *p;
  
    register size_t
      i;
  
    size_t
      length,
      quantum;
  
    ssize_t
      count;
  
    struct stat
      file_stats;
  
    unsigned char
      *buffer;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
    assert(filename != (const char *) NULL);
    if (*filename == '\0')
      file=AcquireUniqueFileResource(filename);
    else
      if (LocaleCompare(filename,"-") == 0)
        file=fileno(stdout);
      else
        file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
    if (file == -1)
      {
        ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
        return(MagickFalse);
      }
    quantum=(size_t) 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)
      {
        file=close(file)-1;
        (void) ThrowMagickException(exception,GetMagickModule(),
          ResourceLimitError,"MemoryAllocationError","`%s'",filename);
        return(MagickFalse);
      }
    length=0;
    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)
      {
        count=write(file,p+i,(size_t) (length-i));
        if (count <= 0)
          {
            count=0;
            if (errno != EINTR)
              break;
          }
      }
      if (i < length)
        break;
      p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
    }
    if (LocaleCompare(filename,"-") != 0)
      file=close(file);
    buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    if ((file == -1) || (i < length))
      {
        if (file != -1)
          file=close(file);
        ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
        return(MagickFalse);
      }
    return(MagickTrue);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   I m a g e s T o B l o b                                                   %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ImagesToBlob() implements direct to memory image formats.  It returns the
  %  image sequence as a blob and its length.  The magick member of the ImageInfo
  %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
  %
  %  Note, some image formats do not permit multiple images to the same image
  %  stream (e.g. JPEG).  in this instance, just the first image of the
  %  sequence is returned as a blob.
  %
  %  The format of the ImagesToBlob method is:
  %
  %      unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
  %        size_t *length,ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o image_info: the image info.
  %
  %    o images: the image list.
  %
  %    o length: return the actual length of the blob.
  %
  %    o exception: return any errors or warnings in this structure.
  %
  */
  MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
    Image *images,size_t *length,ExceptionInfo *exception)
  {
    const MagickInfo
      *magick_info;
  
    ImageInfo
      *clone_info;
  
    MagickBooleanType
      status;
  
    unsigned char
      *blob;
  
    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(exception != (ExceptionInfo *) NULL);
    *length=0;
    blob=(unsigned char *) NULL;
    clone_info=CloneImageInfo(image_info);
    (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
      exception);
    if (*clone_info->magick != '\0')
      (void) CopyMagickString(images->magick,clone_info->magick,MaxTextExtent);
    magick_info=GetMagickInfo(images->magick,exception);
    if (magick_info == (const MagickInfo *) NULL)
      {
        (void) ThrowMagickException(exception,GetMagickModule(),
          MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
          images->magick);
        clone_info=DestroyImageInfo(clone_info);
        return(blob);
      }
    if (GetMagickAdjoin(magick_info) == MagickFalse)
      {
        clone_info=DestroyImageInfo(clone_info);
        return(ImageToBlob(image_info,images,length,exception));
      }
    (void) CopyMagickString(clone_info->magick,images->magick,MaxTextExtent);
    if (GetMagickBlobSupport(magick_info) != MagickFalse)
      {
        /*
          Native blob support for this images format.
        */
        clone_info->length=0;
        clone_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
          sizeof(unsigned char));
        if (clone_info->blob == (void *) NULL)
          (void) ThrowMagickException(exception,GetMagickModule(),
            ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
        else
          {
            (void) CloseBlob(images);
            images->blob->exempt=MagickTrue;
            *images->filename='\0';
            status=WriteImages(clone_info,images,images->filename,exception);
            *length=images->blob->length;
            blob=DetachBlob(images->blob);
            if (blob == (unsigned char *) NULL)
              clone_info->blob=RelinquishMagickMemory(clone_info->blob);
            else if (status == MagickFalse)
              blob=(unsigned char *) RelinquishMagickMemory(blob);
            else
              blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
                sizeof(*blob));
          }
      }
    else
      {
        char
          filename[MaxTextExtent],
          unique[MaxTextExtent];
  
        int
          file;
  
        /*
          Write file to disk in blob images format.
        */
        file=AcquireUniqueFileResource(unique);
        if (file == -1)
          {
            ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
              image_info->filename);
          }
        else
          {
            clone_info->file=fdopen(file,"wb");
            if (clone_info->file != (FILE *) NULL)
              {
                (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
                  images->magick,unique);
                status=WriteImages(clone_info,images,filename,exception);
                (void) CloseBlob(images);
                (void) fclose(clone_info->file);
                if (status == MagickFalse)
                  InheritException(exception,&images->exception);
                else
                  blob=FileToBlob(unique,~0UL,length,exception);
              }
            (void) RelinquishUniqueFileResource(unique);
          }
      }
    clone_info=DestroyImageInfo(clone_info);
    return(blob);
  }
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   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[MaxTextExtent];
  
    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,MaxTextExtent);
        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);
    DestroyBlob(byte_image);
    byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
    write_info=CloneImageInfo(image_info);
    *write_info->magick='\0';
    SetImageInfoFile(write_info,unique_file);
    status=WriteImage(write_info,byte_image);
    write_info=DestroyImageInfo(write_info);
    byte_image=DestroyImage(byte_image);
    (void) fclose(unique_file);
    if (status == MagickFalse)
      {
        (void) RelinquishUniqueFileResource(filename);
        return(MagickFalse);
      }
    /*
      Inject into image stream.
    */
    file=open_utf8(filename,O_RDONLY | O_BINARY,0);
    if (file == -1)
      {
        (void) RelinquishUniqueFileResource(filename);
        ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
          image_info->filename);
        return(MagickFalse);
      }
    quantum=(size_t) 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)
      {
        (void) RelinquishUniqueFileResource(filename);
        file=close(file);
        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
          image->filename);
      }
    for (i=0; ; i+=count)
    {
      count=read(file,buffer,quantum);
      if (count <= 0)
        {
          count=0;
          if (errno != EINTR)
            break;
        }
      status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
        MagickFalse;
    }
    file=close(file);
    if (file == -1)
      ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
    (void) RelinquishUniqueFileResource(filename);
    buffer=(unsigned char *) RelinquishMagickMemory(buffer);
    return(status);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   I s B l o b E x e m p t                                                   %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  IsBlobExempt() returns true if the blob is exempt.
  %
  %  The format of the IsBlobExempt method is:
  %
  %       MagickBooleanType IsBlobExempt(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport MagickBooleanType IsBlobExempt(const Image *image)
  {
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    return(image->blob->exempt);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   I s B l o b S e e k a b l e                                               %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  IsBlobSeekable() returns true if the blob is seekable.
  %
  %  The format of the IsBlobSeekable method is:
  %
  %       MagickBooleanType IsBlobSeekable(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    blob_info=image->blob;
    switch (blob_info->type)
    {
      case BlobStream:
        return(MagickTrue);
      case FileStream:
      {
        int
          status;
  
        if (blob_info->file_info.file == (FILE *) NULL)
          return(MagickFalse);
        status=fseek(blob_info->file_info.file,0,SEEK_CUR);
        return(status == -1 ? MagickFalse : MagickTrue);
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        MagickOffsetType
          offset;
  
        if (blob_info->file_info.gzfile == (gzFile) NULL)
          return(MagickFalse);
        offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
        return(offset < 0 ? MagickFalse : MagickTrue);
  #else
        break;
  #endif
      }
      case UndefinedStream:
      case BZipStream:
      case FifoStream:
      case PipeStream:
      case StandardStream:
        break;
      default:
        break;
    }
    return(MagickFalse);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %   I s B l o b T e m p o r a r y                                             %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  IsBlobTemporary() returns true if the blob is temporary.
  %
  %  The format of the IsBlobTemporary method is:
  %
  %       MagickBooleanType IsBlobTemporary(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
  {
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    return(image->blob->temporary);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  M a p B l o b                                                              %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  MapBlob() creates a mapping from a file to a binary large object.
  %
  %  The format of the MapBlob method is:
  %
  %      unsigned char *MapBlob(int file,const MapMode mode,
  %        const MagickOffsetType offset,const size_t length)
  %
  %  A description of each parameter follows:
  %
  %    o file: map this file descriptor.
  %
  %    o mode: ReadMode, WriteMode, or IOMode.
  %
  %    o offset: starting at this offset within the file.
  %
  %    o length: the length of the mapping is returned in this pointer.
  %
  */
  MagickExport unsigned char *MapBlob(int file,const MapMode mode,
    const MagickOffsetType offset,const size_t length)
  {
  #if defined(MAGICKCORE_HAVE_MMAP)
    int
      flags,
      protection;
  
    unsigned char
      *map;
  
    /*
      Map file.
    */
    flags=0;
    if (file == -1)
  #if defined(MAP_ANONYMOUS)
      flags|=MAP_ANONYMOUS;
  #else
      return((unsigned char *) NULL);
  #endif
    switch (mode)
    {
      case ReadMode:
      default:
      {
        protection=PROT_READ;
        flags|=MAP_PRIVATE;
        break;
      }
      case WriteMode:
      {
        protection=PROT_WRITE;
        flags|=MAP_SHARED;
        break;
      }
      case IOMode:
      {
        protection=PROT_READ | PROT_WRITE;
        flags|=MAP_SHARED;
        break;
      }
    }
  #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
    map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,offset);
  #else
    map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
      MAP_HUGETLB,file,offset);
    if (map == (unsigned char *) MAP_FAILED)
      map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
        offset);
  #endif
    if (map == (unsigned char *) MAP_FAILED)
      return((unsigned char *) NULL);
    return(map);
  #else
    (void) file;
    (void) mode;
    (void) offset;
    (void) length;
    return((unsigned char *) NULL);
  #endif
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  M S B O r d e r L o n g                                                    %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  MSBOrderLong() converts a least-significant byte first buffer of integers to
  %  most-significant byte first.
  %
  %  The format of the MSBOrderLong method is:
  %
  %      void MSBOrderLong(unsigned char *buffer,const size_t length)
  %
  %  A description of each parameter follows.
  %
  %   o  buffer:  Specifies a pointer to a buffer of integers.
  %
  %   o  length:  Specifies the length of the buffer.
  %
  */
  MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
  {
    int
      c;
  
    register unsigned char
      *p,
      *q;
  
    assert(buffer != (unsigned char *) NULL);
    q=buffer+length;
    while (buffer < q)
    {
      p=buffer+3;
      c=(int) (*p);
      *p=(*buffer);
      *buffer++=(unsigned char) c;
      p=buffer+1;
      c=(int) (*p);
      *p=(*buffer);
      *buffer++=(unsigned char) c;
      buffer+=2;
    }
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  M S B O r d e r S h o r t                                                  %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  MSBOrderShort() converts a least-significant byte first buffer of integers
  %  to most-significant byte first.
  %
  %  The format of the MSBOrderShort method is:
  %
  %      void MSBOrderShort(unsigned char *p,const size_t length)
  %
  %  A description of each parameter follows.
  %
  %   o  p:  Specifies a pointer to a buffer of integers.
  %
  %   o  length:  Specifies the length of the buffer.
  %
  */
  MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
  {
    int
      c;
  
    register unsigned char
      *q;
  
    assert(p != (unsigned char *) NULL);
    q=p+length;
    while (p < q)
    {
      c=(int) (*p);
      *p=(*(p+1));
      p++;
      *p++=(unsigned char) c;
    }
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   O p e n B l o b                                                           %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
  %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
  %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
  %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
  %  from a system command.
  %
  %  The format of the OpenBlob method is:
  %
  %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
  %        const BlobMode mode,ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o image_info: the image info.
  %
  %    o image: the image.
  %
  %    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)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    char
      extension[MaxTextExtent],
      filename[MaxTextExtent];
  
    const char
      *type;
  
    MagickBooleanType
      status;
  
    PolicyRights
      rights;
  
    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 != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    blob_info=image->blob;
    if (image_info->blob != (void *) NULL)
      {
        if (image_info->stream != (StreamHandler) NULL)
          blob_info->stream=(StreamHandler) image_info->stream;
        AttachBlob(blob_info,image_info->blob,image_info->length);
        return(MagickTrue);
      }
    (void) DetachBlob(blob_info);
    blob_info->mode=mode;
    switch (mode)
    {
      default: type="r"; break;
      case ReadBlobMode: type="r"; break;
      case ReadBinaryBlobMode: type="rb"; break;
      case WriteBlobMode: type="w"; break;
      case WriteBinaryBlobMode: type="w+b"; break;
      case AppendBlobMode: type="a"; break;
      case AppendBinaryBlobMode: type="a+b"; break;
    }
    if (*type != 'r')
      blob_info->synchronize=image_info->synchronize;
    if (image_info->stream != (StreamHandler) NULL)
      {
        blob_info->stream=(StreamHandler) image_info->stream;
        if (*type == 'w')
          {
            blob_info->type=FifoStream;
            return(MagickTrue);
          }
      }
    /*
      Open image file.
    */
    *filename='\0';
    (void) CopyMagickString(filename,image->filename,MaxTextExtent);
    rights=ReadPolicyRights;
    if (*type == 'w')
      rights=WritePolicyRights;
    if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
      {
        errno=EPERM;
        (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
          "NotAuthorized","`%s'",filename);
        return(MagickFalse);
      }
    if ((LocaleCompare(filename,"-") == 0) ||
        ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
      {
        blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
  #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
        if (strchr(type,'b') != (char *) NULL)
          setmode(fileno(blob_info->file_info.file),_O_BINARY);
  #endif
        blob_info->type=StandardStream;
        blob_info->exempt=MagickTrue;
        return(SetStreamBuffering(image_info,image));
      }
    if ((LocaleNCompare(filename,"fd:",3) == 0) &&
        (IsGeometry(filename+3) != MagickFalse))
      {
        char
          mode[MaxTextExtent];
  
        *mode=(*type);
        mode[1]='\0';
        blob_info->file_info.file=fdopen(StringToLong(filename+3),mode);
        if (blob_info->file_info.file == (FILE *) NULL)
          {
            ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
            return(MagickFalse);
          }
  #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
        if (strchr(type,'b') != (char *) NULL)
          setmode(fileno(blob_info->file_info.file),_O_BINARY);
  #endif
        blob_info->type=FileStream;
        blob_info->exempt=MagickTrue;
        return(SetStreamBuffering(image_info,image));
      }
  #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
    if (*filename == '|')
      {
        char
          fileMode[MaxTextExtent],
          *sanitize_command;
  
        /*
          Pipe image to or from a system command.
        */
  #if defined(SIGPIPE)
        if (*type == 'w')
          (void) signal(SIGPIPE,SIG_IGN);
  #endif
        *fileMode=(*type);
        fileMode[1]='\0';
        sanitize_command=SanitizeString(filename+1);
        blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,
          fileMode);
        sanitize_command=DestroyString(sanitize_command);
        if (blob_info->file_info.file == (FILE *) NULL)
          {
            ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
            return(MagickFalse);
          }
        blob_info->type=PipeStream;
        blob_info->exempt=MagickTrue;
        return(SetStreamBuffering(image_info,image));
      }
  #endif
    status=GetPathAttributes(filename,&blob_info->properties);
  #if defined(S_ISFIFO)
    if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
      {
        blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
        if (blob_info->file_info.file == (FILE *) NULL)
          {
            ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
            return(MagickFalse);
          }
        blob_info->type=FileStream;
        blob_info->exempt=MagickTrue;
        return(SetStreamBuffering(image_info,image));
      }
  #endif
    GetPathComponent(image->filename,ExtensionPath,extension);
    if (*type == 'w')
      {
        (void) CopyMagickString(filename,image->filename,MaxTextExtent);
        if ((image_info->adjoin == MagickFalse) ||
            (strchr(filename,'%') != (char *) NULL))
          {
            /*
              Form filename for multi-part images.
            */
            (void) InterpretImageFilename(image_info,image,image->filename,(int)
              image->scene,filename);
            if ((LocaleCompare(filename,image->filename) == 0) &&
                ((GetPreviousImageInList(image) != (Image *) NULL) ||
                 (GetNextImageInList(image) != (Image *) NULL)))
              {
                char
                  path[MaxTextExtent];
  
                GetPathComponent(image->filename,RootPath,path);
                if (*extension == '\0')
                  (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
                    path,(double) image->scene);
                else
                  (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
                    path,(double) image->scene,extension);
              }
            (void) CopyMagickString(image->filename,filename,MaxTextExtent);
  #if defined(macintosh)
            SetApplicationType(filename,image_info->magick,'8BIM');
  #endif
          }
      }
    if (image_info->file != (FILE *) NULL)
      {
        blob_info->file_info.file=image_info->file;
        blob_info->type=FileStream;
        blob_info->exempt=MagickTrue;
      }
    else
      if (*type == 'r')
        {
          blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
          if (blob_info->file_info.file != (FILE *) NULL)
            {
              size_t
                count;
  
              unsigned char
                magick[3];
  
              blob_info->type=FileStream;
              (void) fstat(fileno(blob_info->file_info.file),
                &blob_info->properties);
              (void) SetStreamBuffering(image_info,image);
              (void) memset(magick,0,sizeof(magick));
              count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
              (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
  #if defined(MAGICKCORE_POSIX_SUPPORT)
              (void) fflush(blob_info->file_info.file);
  #endif
              (void) LogMagickEvent(BlobEvent,GetMagickModule(),
                 "  read %.20g magic header bytes",(double) count);
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
              if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
                  ((int) magick[2] == 0x08))
                {
                  if (blob_info->file_info.file != (FILE *) NULL)
                    (void) fclose(blob_info->file_info.file);
                  blob_info->file_info.file=(FILE *) NULL;
                  blob_info->file_info.gzfile=gzopen(filename,"rb");
                  if (blob_info->file_info.gzfile != (gzFile) NULL)
                    blob_info->type=ZipStream;
                 }
  #endif
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
              if (strncmp((char *) magick,"BZh",3) == 0)
                {
                  if (blob_info->file_info.file != (FILE *) NULL)
                    (void) fclose(blob_info->file_info.file);
                  blob_info->file_info.file=(FILE *) NULL;
                  blob_info->file_info.bzfile=BZ2_bzopen(filename,"r");
                  if (blob_info->file_info.bzfile != (BZFILE *) NULL)
                    blob_info->type=BZipStream;
                }
  #endif
              if (blob_info->type == FileStream)
                {
                  const MagickInfo
                    *magick_info;
  
                  ExceptionInfo
                    *sans_exception;
  
                  size_t
                    length;
  
                  sans_exception=AcquireExceptionInfo();
                  magick_info=GetMagickInfo(image_info->magick,sans_exception);
                  sans_exception=DestroyExceptionInfo(sans_exception);
                  length=(size_t) blob_info->properties.st_size;
                  if ((magick_info != (const MagickInfo *) NULL) &&
                      (GetMagickBlobSupport(magick_info) != MagickFalse) &&
                      (length > MagickMaxBufferExtent) &&
                      (AcquireMagickResource(MapResource,length) != MagickFalse))
                    {
                      void
                        *blob;
  
                      blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
                        length);
                      if (blob == (void *) NULL)
                        RelinquishMagickResource(MapResource,length);
                      else
                        {
                          /*
                            Format supports blobs-- use memory-mapped I/O.
                          */
                          if (image_info->file != (FILE *) NULL)
                            blob_info->exempt=MagickFalse;
                          else
                            {
                              (void) fclose(blob_info->file_info.file);
                              blob_info->file_info.file=(FILE *) NULL;
                            }
                          AttachBlob(blob_info,blob,length);
                          blob_info->mapped=MagickTrue;
                        }
                    }
                }
            }
          }
        else
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
          if ((LocaleCompare(extension,"Z") == 0) ||
              (LocaleCompare(extension,"gz") == 0) ||
              (LocaleCompare(extension,"wmz") == 0) ||
              (LocaleCompare(extension,"svgz") == 0))
            {
              blob_info->file_info.gzfile=gzopen(filename,"wb");
              if (blob_info->file_info.gzfile != (gzFile) NULL)
                blob_info->type=ZipStream;
            }
          else
  #endif
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
            if (LocaleCompare(extension,"bz2") == 0)
              {
                if (mode == WriteBinaryBlobMode)
                  type="w";
                blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
                if (blob_info->file_info.bzfile != (BZFILE *) NULL)
                  blob_info->type=BZipStream;
              }
            else
  #endif
              {
                blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
                if (blob_info->file_info.file != (FILE *) NULL)
                  {
                    blob_info->type=FileStream;
                    (void) SetStreamBuffering(image_info,image);
                  }
         }
    blob_info->status=MagickFalse;
    if (blob_info->type != UndefinedStream)
      blob_info->size=GetBlobSize(image);
    else
      {
        ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
        return(MagickFalse);
      }
    return(MagickTrue);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   P i n g B l o b                                                           %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  PingBlob() returns all the attributes of an image or image sequence except
  %  for the pixels.  It is much faster and consumes far less memory than
  %  BlobToImage().  On failure, a NULL image is returned and exception
  %  describes the reason for the failure.
  %
  %  The format of the PingBlob method is:
  %
  %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
  %        const size_t length,ExceptionInfo *exception)
  %
  %  A description of each parameter follows:
  %
  %    o image_info: the image info.
  %
  %    o blob: the address of a character stream in one of the image formats
  %      understood by ImageMagick.
  %
  %    o length: This size_t integer reflects the length in bytes of the blob.
  %
  %    o exception: return any errors or warnings in this structure.
  %
  */
  
  #if defined(__cplusplus) || defined(c_plusplus)
  extern "C" {
  #endif
  
  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);
  }
  
  #if defined(__cplusplus) || defined(c_plusplus)
  }
  #endif
  
  MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
    const size_t length,ExceptionInfo *exception)
  {
    const MagickInfo
      *magick_info;
  
    Image
      *image;
  
    ImageInfo
      *clone_info,
      *ping_info;
  
    MagickBooleanType
      status;
  
    assert(image_info != (ImageInfo *) NULL);
    assert(image_info->signature == MagickCoreSignature);
    if (image_info->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
        image_info->filename);
    assert(exception != (ExceptionInfo *) NULL);
    if ((blob == (const void *) NULL) || (length == 0))
      {
        (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
          "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
        return((Image *) NULL);
      }
    ping_info=CloneImageInfo(image_info);
    ping_info->blob=(void *) blob;
    ping_info->length=length;
    ping_info->ping=MagickTrue;
    if (*ping_info->magick == '\0')
      (void) SetImageInfo(ping_info,0,exception);
    magick_info=GetMagickInfo(ping_info->magick,exception);
    if (magick_info == (const MagickInfo *) NULL)
      {
        (void) ThrowMagickException(exception,GetMagickModule(),
          MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
          ping_info->magick);
        ping_info=DestroyImageInfo(ping_info);
        return((Image *) NULL);
      }
    if (GetMagickBlobSupport(magick_info) != MagickFalse)
      {
        char
          filename[MagickPathExtent];
  
        /*
          Native blob support for this image format.
        */
        (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
        (void) FormatLocaleString(ping_info->filename,MaxTextExtent,"%s:%s",
          ping_info->magick,filename);
        image=ReadStream(ping_info,&PingStream,exception);
        if (image != (Image *) NULL)
          (void) DetachBlob(image->blob);
        ping_info=DestroyImageInfo(ping_info);
        return(image);
      }
    /*
      Write blob to a temporary file on disk.
    */
    ping_info->blob=(void *) NULL;
    ping_info->length=0;
    *ping_info->filename='\0';
    status=BlobToFile(ping_info->filename,blob,length,exception);
    if (status == MagickFalse)
      {
        (void) RelinquishUniqueFileResource(ping_info->filename);
        ping_info=DestroyImageInfo(ping_info);
        return((Image *) NULL);
      }
    clone_info=CloneImageInfo(ping_info);
    (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
      ping_info->magick,ping_info->filename);
    image=ReadStream(clone_info,&PingStream,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,
            MaxTextExtent);
          (void) CopyMagickString(images->magick_filename,image_info->filename,
            MaxTextExtent);
          (void) CopyMagickString(images->magick,magick_info->name,MaxTextExtent);
          images=GetNextImageInList(images);
        }
      }
    clone_info=DestroyImageInfo(clone_info);
    (void) RelinquishUniqueFileResource(ping_info->filename);
    ping_info=DestroyImageInfo(ping_info);
    return(image);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b                                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlob() reads data from the blob or image file and returns it.  It
  %  returns the number of bytes read. If length is zero, ReadBlob() returns
  %  zero and has no other results. If length is greater than SSIZE_MAX, the
  %  result is unspecified.
  %
  %  The format of the ReadBlob method is:
  %
  %      ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o length:  Specifies an integer representing the number of bytes to read
  %      from the file.
  %
  %    o data:  Specifies an area to place the information requested from the
  %      file.
  %
  */
  MagickExport ssize_t ReadBlob(Image *image,const size_t length,
    unsigned char *data)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    int
      c;
  
    register unsigned char
      *q;
  
    ssize_t
      count;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    if (length == 0)
      return(0);
    assert(data != (void *) NULL);
    blob_info=image->blob;
    count=0;
    q=data;
    switch (blob_info->type)
    {
      case UndefinedStream:
        break;
      case StandardStream:
      case FileStream:
      case PipeStream:
      {
        switch (length)
        {
          default:
          {
            count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
            break;
          }
          case 4:
          {
            c=getc(blob_info->file_info.file);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 3:
          {
            c=getc(blob_info->file_info.file);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 2:
          {
            c=getc(blob_info->file_info.file);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 1:
          {
            c=getc(blob_info->file_info.file);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 0:
            break;
        }
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        switch (length)
        {
          default:
          {
            register ssize_t
              i;
  
            for (i=0; i < (ssize_t) length; i+=count)
            {
              count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
                (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
              if (count <= 0)
                {
                  count=0;
                  if (errno != EINTR)
                    break;
                }
            }
            count=i;
            break;
          }
          case 4:
          {
            c=gzgetc(blob_info->file_info.gzfile);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 3:
          {
            c=gzgetc(blob_info->file_info.gzfile);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 2:
          {
            c=gzgetc(blob_info->file_info.gzfile);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 1:
          {
            c=gzgetc(blob_info->file_info.gzfile);
            if (c == EOF)
              break;
            *q++=(unsigned char) c;
            count++;
          }
          case 0:
            break;
        }
  #endif
        break;
      }
      case BZipStream:
      {
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
       register ssize_t
          i;
  
        for (i=0; i < (ssize_t) length; i+=count)
        {
          count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
            (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
          if (count <= 0)
            {
              count=0;
              if (errno != EINTR)
                break;
            }
        }
        count=i;
  #endif
        break;
      }
      case FifoStream:
        break;
      case BlobStream:
      {
        register const unsigned char
          *p;
  
        if (blob_info->offset >= (MagickOffsetType) blob_info->length)
          {
            blob_info->eof=MagickTrue;
            break;
          }
        p=blob_info->data+blob_info->offset;
        count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
          blob_info->length-blob_info->offset);
        blob_info->offset+=count;
        if (count != (ssize_t) length)
          blob_info->eof=MagickTrue;
        (void) memcpy(q,p,(size_t) count);
        break;
      }
    }
    return(count);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b B y t e                                                    %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobByte() reads a single byte from the image file and returns it.
  %
  %  The format of the ReadBlobByte method is:
  %
  %      int ReadBlobByte(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport int ReadBlobByte(Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    register const unsigned char
      *p;
  
    unsigned char
      buffer[1];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    switch (blob_info->type)
    {
      case StandardStream:
      case FileStream:
      case PipeStream:
      {
        int
          c;
  
        p=(const unsigned char *) buffer;
        c=getc(blob_info->file_info.file);
        if (c == EOF)
          return(EOF);
        *buffer=(unsigned char) c;
        break;
      }
      default:
      {
        ssize_t
          count;
  
        p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
        if (count != 1)
          return(EOF);
        break;
      }
    }
    return((int) (*p));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b D o u b l e                                                %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
  %  specified by the endian member of the image structure.
  %
  %  The format of the ReadBlobDouble method is:
  %
  %      double ReadBlobDouble(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport double ReadBlobDouble(Image *image)
  {
    union
    {
      MagickSizeType
        unsigned_value;
  
      double
        double_value;
    } quantum;
  
    quantum.double_value=0.0;
    quantum.unsigned_value=ReadBlobLongLong(image);
    return(quantum.double_value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b F l o a t                                                  %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
  %  specified by the endian member of the image structure.
  %
  %  The format of the ReadBlobFloat method is:
  %
  %      float ReadBlobFloat(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport float ReadBlobFloat(Image *image)
  {
    union
    {
      unsigned int
        unsigned_value;
  
      float
        float_value;
    } quantum;
  
    quantum.float_value=0.0;
    quantum.unsigned_value=ReadBlobLong(image);
    return(quantum.float_value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b L o n g                                                    %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  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:
  %
  %      unsigned int ReadBlobLong(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport unsigned int ReadBlobLong(Image *image)
  {
    register const unsigned char
      *p;
  
    ssize_t
      count;
  
    unsigned char
      buffer[4];
  
    unsigned int
      value;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    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++) << 24;
    value|=(unsigned int) (*p++) << 16;
    value|=(unsigned int) (*p++) << 8;
    value|=(unsigned int) (*p++);
    return(value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b L o n g L o n g                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
  %  byte-order specified by the endian member of the image structure.
  %
  %  The format of the ReadBlobLongLong method is:
  %
  %      MagickSizeType ReadBlobLongLong(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport MagickSizeType ReadBlobLongLong(Image *image)
  {
    MagickSizeType
      value;
  
    register const unsigned char
      *p;
  
    ssize_t
      count;
  
    unsigned char
      buffer[8];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    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;
        return(value);
      }
    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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b S h o r t                                                  %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
  %  specified by the endian member of the image structure.
  %
  %  The format of the ReadBlobShort method is:
  %
  %      unsigned short ReadBlobShort(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport unsigned short ReadBlobShort(Image *image)
  {
    register const unsigned char
      *p;
  
    register unsigned short
      value;
  
    ssize_t
      count;
  
    unsigned char
      buffer[2];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
    if (count != 2)
      return((unsigned short) 0U);
    if (image->endian == LSBEndian)
      {
        value=(unsigned short) (*p++);
        value|=(unsigned short) (*p++) << 8;
        return(value);
      }
    value=(unsigned short) ((unsigned short) (*p++) << 8);
    value|=(unsigned short) (*p++);
    return(value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b L S B L o n g                                              %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
  %  least-significant byte first order.
  %
  %  The format of the ReadBlobLSBLong method is:
  %
  %      unsigned int ReadBlobLSBLong(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport unsigned int ReadBlobLSBLong(Image *image)
  {
    register const unsigned char
      *p;
  
    register unsigned int
      value;
  
    ssize_t
      count;
  
    unsigned char
      buffer[4];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b L S B S h o r t                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
  %  least-significant byte first order.
  %
  %  The format of the ReadBlobLSBShort method is:
  %
  %      unsigned short ReadBlobLSBShort(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport unsigned short ReadBlobLSBShort(Image *image)
  {
    register const unsigned char
      *p;
  
    register unsigned short
      value;
  
    ssize_t
      count;
  
    unsigned char
      buffer[2];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
    if (count != 2)
      return((unsigned short) 0U);
    value=(unsigned short) (*p++);
    value|=(unsigned short) (*p++) << 8;
    return(value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b L S B S i g n e d S h o r t                                %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
  %  least-significant byte-order.
  %
  %  The format of the ReadBlobLSBSignedShort method is:
  %
  %      signed short ReadBlobLSBSignedShort(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the 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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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;
  
    register unsigned int
      value;
  
    ssize_t
      count;
  
    unsigned char
      buffer[4];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    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++);
    return(value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b M S B L o n g L o n g                                      %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobMSBLongLong() reads a unsigned long int value as a 64-bit quantity
  %  in most-significant byte first order.
  %
  %  The format of the ReadBlobMSBLongLong method is:
  %
  %      unsigned int ReadBlobMSBLongLong(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
  {
    register const unsigned char
      *p;
  
    register MagickSizeType
      value;
  
    ssize_t
      count;
  
    unsigned char
      buffer[8];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    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++);
    return(value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b M S B S h o r t                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
  %  most-significant byte first order.
  %
  %  The format of the ReadBlobMSBShort method is:
  %
  %      unsigned short ReadBlobMSBShort(Image *image)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  */
  MagickExport unsigned short ReadBlobMSBShort(Image *image)
  {
    register const unsigned char
      *p;
  
    register unsigned short
      value;
  
    ssize_t
      count;
  
    unsigned char
      buffer[2];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    *buffer='\0';
    p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
    if (count != 2)
      return((unsigned short) 0U);
    value=(unsigned short) ((unsigned short) (*p++) << 8);
    value|=(unsigned short) (*p++);
    return(value);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  R e a d B l o b S t r e a m                                                %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobStream() reads data from the blob or image file and returns it.  It
  %  returns a pointer to the data buffer you supply or to the image memory
  %  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
  %  returns a count of zero and has no other results. If length is greater than
  %  SSIZE_MAX, the result is unspecified.
  %
  %  The format of the ReadBlobStream method is:
  %
  %      const void *ReadBlobStream(Image *image,const size_t length,void *data,
  %        ssize_t *count)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o length:  Specifies an integer representing the number of bytes to read
  %      from the file.
  %
  %    o length: returns the number of bytes read.
  %
  %    o data:  Specifies an area to place the information requested from the
  %      file.
  %
  */
  MagickExport const void *ReadBlobStream(Image *image,const size_t length,
    void *data,ssize_t *count)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    assert(count != (ssize_t *) NULL);
    blob_info=image->blob;
    if (blob_info->type != BlobStream)
      {
        assert(data != NULL);
        *count=ReadBlob(image,length,(unsigned char *) data);
        return(data);
      }
    if (blob_info->offset >= (MagickOffsetType) blob_info->length)
      {
        *count=0;
        blob_info->eof=MagickTrue;
        return(data);
      }
    data=blob_info->data+blob_info->offset;
    *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
      blob_info->length-blob_info->offset);
    blob_info->offset+=(*count);
    if (*count != (ssize_t) length)
      blob_info->eof=MagickTrue;
    return(data);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   R e a d B l o b S t r i n g                                               %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReadBlobString() reads characters from a blob or file until a newline
  %  character is read or an end-of-file condition is encountered.
  %
  %  The format of the ReadBlobString method is:
  %
  %      char *ReadBlobString(Image *image,char *string)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o string: the address of a character buffer.
  %
  */
  MagickExport char *ReadBlobString(Image *image,char *string)
  {
    int
      c;
  
    register ssize_t
      i;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    for (i=0; i < (MaxTextExtent-1L); i++)
    {
      c=ReadBlobByte(image);
      if (c == EOF)
        {
          if (i == 0)
            return((char *) NULL);
          break;
        }
      string[i]=c;
      if (c == '\n')
        {
          if ((i > 0) && (string[i-1] == '\r'))
            i--;
          break;
        }
    }
    string[i]='\0';
    return(string);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   R e f e r e n c e B l o b                                                 %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  ReferenceBlob() increments the reference count associated with the pixel
  %  blob returning a pointer to the blob.
  %
  %  The format of the ReferenceBlob method is:
  %
  %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
  %
  %  A description of each parameter follows:
  %
  %    o blob_info: the blob_info.
  %
  */
  MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
  {
    assert(blob != (BlobInfo *) NULL);
    assert(blob->signature == MagickCoreSignature);
    if (blob->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    LockSemaphoreInfo(blob->semaphore);
    blob->reference_count++;
    UnlockSemaphoreInfo(blob->semaphore);
    return(blob);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  S e e k B l o b                                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
  %  and returns the resulting offset.
  %
  %  The format of the SeekBlob method is:
  %
  %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
  %        const int whence)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o offset:  Specifies an integer representing the offset in bytes.
  %
  %    o whence:  Specifies an integer representing how the offset is
  %      treated relative to the beginning of the blob as follows:
  %
  %        SEEK_SET  Set position equal to offset bytes.
  %        SEEK_CUR  Set position to current location plus offset.
  %        SEEK_END  Set position to EOF plus offset.
  %
  */
  MagickExport MagickOffsetType SeekBlob(Image *image,
    const MagickOffsetType offset,const int whence)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    switch (blob_info->type)
    {
      case UndefinedStream:
        break;
      case StandardStream:
      case PipeStream:
        return(-1);
      case FileStream:
      {
        if ((offset < 0) && (whence == SEEK_SET))
          return(-1);
        if (fseek(blob_info->file_info.file,offset,whence) < 0)
          return(-1);
        blob_info->offset=TellBlob(image);
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        if (gzseek(blob_info->file_info.gzfile,(off_t) offset,whence) < 0)
          return(-1);
  #endif
        blob_info->offset=TellBlob(image);
        break;
      }
      case BZipStream:
        return(-1);
      case FifoStream:
        return(-1);
      case BlobStream:
      {
        switch (whence)
        {
          case SEEK_SET:
          default:
          {
            if (offset < 0)
              return(-1);
            blob_info->offset=offset;
            break;
          }
          case SEEK_CUR:
          {
            if (((offset > 0) && (blob_info->offset > (SSIZE_MAX-offset))) ||
                ((offset < 0) && (blob_info->offset < (-SSIZE_MAX-offset))))
              {
                errno=EOVERFLOW;
                return(-1);
              }
            if ((blob_info->offset+offset) < 0)
              return(-1);
            blob_info->offset+=offset;
            break;
          }
          case SEEK_END:
          {
            if (((MagickOffsetType) blob_info->length+offset) < 0)
              return(-1);
            blob_info->offset=blob_info->length+offset;
            break;
          }
        }
        if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
          {
            blob_info->eof=MagickFalse;
            break;
          }
        if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
          return(-1);
        break;
      }
    }
    return(blob_info->offset);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   S e t B l o b E x e m p t                                                 %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  SetBlobExempt() sets the blob exempt status.
  %
  %  The format of the SetBlobExempt method is:
  %
  %      MagickBooleanType SetBlobExempt(const Image *image,
  %        const MagickBooleanType exempt)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o exempt: Set to true if this blob is exempt from being closed.
  %
  */
  MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
  {
    assert(image != (const Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    image->blob->exempt=exempt;
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  S e t B l o b E x t e n t                                                  %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
  %  method is successful, subsequent writes to bytes in the specified range are
  %  guaranteed not to fail.
  %
  %  The format of the SetBlobExtent method is:
  %
  %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o extent:  the blob maximum extent.
  %
  */
  MagickExport MagickBooleanType SetBlobExtent(Image *image,
    const MagickSizeType extent)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    switch (blob_info->type)
    {
      case UndefinedStream:
        break;
      case StandardStream:
        return(MagickFalse);
      case FileStream:
      {
        MagickOffsetType
          offset;
  
        ssize_t
          count;
  
        if (extent != (MagickSizeType) ((off_t) extent))
          return(MagickFalse);
        offset=SeekBlob(image,0,SEEK_END);
        if (offset < 0)
          return(MagickFalse);
        if ((MagickSizeType) offset >= extent)
          break;
        offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
        if (offset < 0)
          break;
        count=(ssize_t) fwrite((const unsigned char *) "",1,1,
          blob_info->file_info.file);
  #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
        if (blob_info->synchronize != MagickFalse)
          {
            int
              file;
  
            file=fileno(blob_info->file_info.file);
            if ((file == -1) || (offset < 0))
              return(MagickFalse);
            (void) posix_fallocate(file,offset,extent-offset);
          }
  #endif
        offset=SeekBlob(image,offset,SEEK_SET);
        if (count != 1)
          return(MagickFalse);
        break;
      }
      case PipeStream:
      case ZipStream:
        return(MagickFalse);
      case BZipStream:
        return(MagickFalse);
      case FifoStream:
        return(MagickFalse);
      case BlobStream:
      {
        if (extent != (MagickSizeType) ((size_t) extent))
          return(MagickFalse);
        if (blob_info->mapped != MagickFalse)
          {
            MagickOffsetType
              offset;
  
            ssize_t
              count;
  
            (void) UnmapBlob(blob_info->data,blob_info->length);
            RelinquishMagickResource(MapResource,blob_info->length);
            if (extent != (MagickSizeType) ((off_t) extent))
              return(MagickFalse);
            offset=SeekBlob(image,0,SEEK_END);
            if (offset < 0)
              return(MagickFalse);
            if ((MagickSizeType) offset >= extent)
              break;
            offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
            count=(ssize_t) fwrite((const unsigned char *) "",1,1,
              blob_info->file_info.file);
  #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
            if (blob_info->synchronize != MagickFalse)
              {
                int
                  file;
  
                file=fileno(blob_info->file_info.file);
                if ((file == -1) || (offset < 0))
                  return(MagickFalse);
                (void) posix_fallocate(file,offset,extent-offset);
              }
  #endif
            offset=SeekBlob(image,offset,SEEK_SET);
            if (count != 1)
              return(MagickFalse);
            (void) AcquireMagickResource(MapResource,extent);
            blob_info->data=(unsigned char*) MapBlob(fileno(
              blob_info->file_info.file),WriteMode,0,(size_t) extent);
            blob_info->extent=(size_t) extent;
            blob_info->length=(size_t) extent;
            (void) SyncBlob(image);
            break;
          }
        blob_info->extent=(size_t) extent;
        blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
          blob_info->extent+1,sizeof(*blob_info->data));
        (void) SyncBlob(image);
        if (blob_info->data == (unsigned char *) NULL)
          {
            (void) DetachBlob(blob_info);
            return(MagickFalse);
          }
        break;
      }
    }
    return(MagickTrue);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  S y n c B l o b                                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
  %  attributes if it is an blob.
  %
  %  The format of the SyncBlob method is:
  %
  %      int SyncBlob(Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  static int SyncBlob(Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    int
      status;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    status=0;
    switch (blob_info->type)
    {
      case UndefinedStream:
      case StandardStream:
        break;
      case FileStream:
      case PipeStream:
      {
        status=fflush(blob_info->file_info.file);
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
  #endif
        break;
      }
      case BZipStream:
      {
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
        status=BZ2_bzflush(blob_info->file_info.bzfile);
  #endif
        break;
      }
      case FifoStream:
        break;
      case BlobStream:
        break;
    }
    return(status);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  T e l l B l o b                                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  TellBlob() obtains the current value of the blob or file position.
  %
  %  The format of the TellBlob method is:
  %
  %      MagickOffsetType TellBlob(const Image *image)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  */
  MagickExport MagickOffsetType TellBlob(const Image *image)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    MagickOffsetType
      offset;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    offset=(-1);
    switch (blob_info->type)
    {
      case UndefinedStream:
      case StandardStream:
        break;
      case FileStream:
      {
        offset=ftell(blob_info->file_info.file);
        break;
      }
      case PipeStream:
        break;
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
  #endif
        break;
      }
      case BZipStream:
        break;
      case FifoStream:
        break;
      case BlobStream:
      {
        offset=blob_info->offset;
        break;
      }
    }
    return(offset);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  U n m a p B l o b                                                          %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  UnmapBlob() deallocates the binary large object previously allocated with
  %  the MapBlob method.
  %
  %  The format of the UnmapBlob method is:
  %
  %       MagickBooleanType UnmapBlob(void *map,const size_t length)
  %
  %  A description of each parameter follows:
  %
  %    o map: the address  of the binary large object.
  %
  %    o length: the length of the binary large object.
  %
  */
  MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
  {
  #if defined(MAGICKCORE_HAVE_MMAP)
    int
      status;
  
    status=munmap(map,length);
    return(status == -1 ? MagickFalse : MagickTrue);
  #else
    (void) map;
    (void) length;
    return(MagickFalse);
  #endif
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b                                                          %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlob() writes data to a blob or image file.  It returns the number of
  %  bytes written.
  %
  %  The format of the WriteBlob method is:
  %
  %      ssize_t WriteBlob(Image *image,const size_t length,
  %        const unsigned char *data)
  %
  %  A description of each parameter follows:
  %
  %    o image: the image.
  %
  %    o length:  Specifies an integer representing the number of bytes to
  %      write to the file.
  %
  %    o data:  The address of the data to write to the blob or file.
  %
  */
  MagickExport ssize_t WriteBlob(Image *image,const size_t length,
    const unsigned char *data)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    int
      c;
  
    register const unsigned char
      *p;
  
    register unsigned char
      *q;
  
    ssize_t
      count;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    if (length == 0)
      return(0);
    assert(data != (const unsigned char *) NULL);
    blob_info=image->blob;
    count=0;
    p=(const unsigned char *) data;
    q=(unsigned char *) data;
    switch (blob_info->type)
    {
      case UndefinedStream:
        break;
      case StandardStream:
      case FileStream:
      case PipeStream:
      {
        switch (length)
        {
          default:
          {
            count=(ssize_t) fwrite((const char *) data,1,length,
              blob_info->file_info.file);
            break;
          }
          case 4:
          {
            c=putc((int) *p++,blob_info->file_info.file);
            if (c == EOF)
              break;
            count++;
          }
          case 3:
          {
            c=putc((int) *p++,blob_info->file_info.file);
            if (c == EOF)
              break;
            count++;
          }
          case 2:
          {
            c=putc((int) *p++,blob_info->file_info.file);
            if (c == EOF)
              break;
            count++;
          }
          case 1:
          {
            c=putc((int) *p++,blob_info->file_info.file);
            if (c == EOF)
              break;
            count++;
          }
          case 0:
            break;
        }
        break;
      }
      case ZipStream:
      {
  #if defined(MAGICKCORE_ZLIB_DELEGATE)
        switch (length)
        {
          default:
          {
            register ssize_t
              i;
  
            for (i=0; i < (ssize_t) length; i+=count)
            {
              count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
                (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
              if (count <= 0)
                {
                  count=0;
                  if (errno != EINTR)
                    break;
                }
            }
            count=i;
            break;
          }
          case 4:
          {
            c=gzputc(blob_info->file_info.gzfile,(int) *p++);
            if (c == EOF)
              break;
            count++;
          }
          case 3:
          {
            c=gzputc(blob_info->file_info.gzfile,(int) *p++);
            if (c == EOF)
              break;
            count++;
          }
          case 2:
          {
            c=gzputc(blob_info->file_info.gzfile,(int) *p++);
            if (c == EOF)
              break;
            count++;
          }
          case 1:
          {
            c=gzputc(blob_info->file_info.gzfile,(int) *p++);
            if (c == EOF)
              break;
            count++;
          }
          case 0:
            break;
        }
  #endif
        break;
      }
      case BZipStream:
      {
  #if defined(MAGICKCORE_BZLIB_DELEGATE)
        register ssize_t
          i;
  
        for (i=0; i < (ssize_t) length; i+=count)
        {
          count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
            (int) MagickMin(length-i,MagickMaxBufferExtent));
          if (count <= 0)
            {
              count=0;
              if (errno != EINTR)
                break;
            }
        }
        count=i;
  #endif
        break;
      }
      case FifoStream:
      {
        count=(ssize_t) blob_info->stream(image,data,length);
        break;
      }
      case BlobStream:
      {
        if ((blob_info->offset+(MagickOffsetType) length) >=
            (MagickOffsetType) blob_info->extent)
          {
            if (blob_info->mapped != MagickFalse)
              return(0);
            blob_info->extent+=length+blob_info->quantum;
            blob_info->quantum<<=1;
            blob_info->data=(unsigned char *) ResizeQuantumMemory(
              blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
            (void) SyncBlob(image);
            if (blob_info->data == (unsigned char *) NULL)
              {
                (void) DetachBlob(blob_info);
                return(0);
              }
          }
        q=blob_info->data+blob_info->offset;
        (void) memcpy(q,p,length);
        blob_info->offset+=length;
        if (blob_info->offset >= (MagickOffsetType) blob_info->length)
          blob_info->length=(size_t) blob_info->offset;
        count=(ssize_t) length;
      }
    }
    return(count);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b B y t e                                                  %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
  %  written (either 0 or 1);
  %
  %  The format of the WriteBlobByte method is:
  %
  %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o value: Specifies the value to write.
  %
  */
  MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
  {
    BlobInfo
      *magick_restrict blob_info;
  
    ssize_t
      count;
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(image->blob != (BlobInfo *) NULL);
    assert(image->blob->type != UndefinedStream);
    blob_info=image->blob;
    count=0;
    switch (blob_info->type)
    {
      case StandardStream:
      case FileStream:
      case PipeStream:
      {
        int
          c;
  
        c=putc((int) value,blob_info->file_info.file);
        if (c == EOF)
          break;
        count++;
        break;
      }
      default:
      {
        count=WriteBlobStream(image,1,&value);
        break;
      }
    }
    return(count);
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b F l o a t                                                %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
  %  specified by the endian member of the image structure.
  %
  %  The format of the WriteBlobFloat method is:
  %
  %      ssize_t WriteBlobFloat(Image *image,const float value)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o value: Specifies the value to write.
  %
  */
  MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
  {
    union
    {
      unsigned int
        unsigned_value;
  
      float
        float_value;
    } quantum;
  
    quantum.unsigned_value=0U;
    quantum.float_value=value;
    return(WriteBlobLong(image,quantum.unsigned_value));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b L o n g                                                  %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  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:
  %
  %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o value: Specifies the value to write.
  %
  */
  MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
  {
    unsigned char
      buffer[4];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->endian == LSBEndian)
      {
        buffer[0]=(unsigned char) value;
        buffer[1]=(unsigned char) (value >> 8);
        buffer[2]=(unsigned char) (value >> 16);
        buffer[3]=(unsigned char) (value >> 24);
        return(WriteBlobStream(image,4,buffer));
      }
    buffer[0]=(unsigned char) (value >> 24);
    buffer[1]=(unsigned char) (value >> 16);
    buffer[2]=(unsigned char) (value >> 8);
    buffer[3]=(unsigned char) value;
    return(WriteBlobStream(image,4,buffer));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   W r i t e B l o b S h o r t                                               %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobShort() writes a short value as a 16-bit quantity in the
  %  byte-order specified by the endian member of the image structure.
  %
  %  The format of the WriteBlobShort method is:
  %
  %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o value:  Specifies the value to write.
  %
  */
  MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
  {
    unsigned char
      buffer[2];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    if (image->endian == LSBEndian)
      {
        buffer[0]=(unsigned char) value;
        buffer[1]=(unsigned char) (value >> 8);
        return(WriteBlobStream(image,2,buffer));
      }
    buffer[0]=(unsigned char) (value >> 8);
    buffer[1]=(unsigned char) value;
    return(WriteBlobStream(image,2,buffer));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b L S B L o n g                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
  %  least-significant byte first order.
  %
  %  The format of the WriteBlobLSBLong method is:
  %
  %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o value: Specifies the value to write.
  %
  */
  MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
  {
    unsigned char
      buffer[4];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    buffer[0]=(unsigned char) value;
    buffer[1]=(unsigned char) (value >> 8);
    buffer[2]=(unsigned char) (value >> 16);
    buffer[3]=(unsigned char) (value >> 24);
    return(WriteBlobStream(image,4,buffer));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   W r i t e B l o b L S B S h o r t                                         %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
  %  least-significant byte first order.
  %
  %  The format of the WriteBlobLSBShort method is:
  %
  %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o value:  Specifies the value to write.
  %
  */
  MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
  {
    unsigned char
      buffer[2];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    buffer[0]=(unsigned char) value;
    buffer[1]=(unsigned char) (value >> 8);
    return(WriteBlobStream(image,2,buffer));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   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));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b M S B L o n g                                            %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
  %  most-significant byte first order.
  %
  %  The format of the WriteBlobMSBLong method is:
  %
  %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
  %
  %  A description of each parameter follows.
  %
  %    o value:  Specifies the value to write.
  %
  %    o image: the image.
  %
  */
  MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
  {
    unsigned char
      buffer[4];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    buffer[0]=(unsigned char) (value >> 24);
    buffer[1]=(unsigned char) (value >> 16);
    buffer[2]=(unsigned char) (value >> 8);
    buffer[3]=(unsigned char) value;
    return(WriteBlobStream(image,4,buffer));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b M S B L o n g L o n g                                    %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
  %  most-significant byte first order.
  %
  %  The format of the WriteBlobMSBLongLong method is:
  %
  %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
  %
  %  A description of each parameter follows.
  %
  %    o value:  Specifies the value to write.
  %
  %    o image: the image.
  %
  */
  MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
    const MagickSizeType value)
  {
    unsigned char
      buffer[8];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    buffer[0]=(unsigned char) (value >> 56);
    buffer[1]=(unsigned char) (value >> 48);
    buffer[2]=(unsigned char) (value >> 40);
    buffer[3]=(unsigned char) (value >> 32);
    buffer[4]=(unsigned char) (value >> 24);
    buffer[5]=(unsigned char) (value >> 16);
    buffer[6]=(unsigned char) (value >> 8);
    buffer[7]=(unsigned char) value;
    return(WriteBlobStream(image,8,buffer));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b M S B S h o r t                                          %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
  %  most-significant byte first order.
  %
  %  The format of the WriteBlobMSBShort method is:
  %
  %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
  %
  %  A description of each parameter follows.
  %
  %   o  value:  Specifies the value to write.
  %
  %   o  file:  Specifies the file to write the data to.
  %
  */
  MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
  {
    unsigned char
      buffer[2];
  
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    buffer[0]=(unsigned char) (value >> 8);
    buffer[1]=(unsigned char) value;
    return(WriteBlobStream(image,2,buffer));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  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));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +   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));
  }
  
  /*
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                                                             %
  %                                                                             %
  %                                                                             %
  +  W r i t e B l o b S t r i n g                                              %
  %                                                                             %
  %                                                                             %
  %                                                                             %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  %  WriteBlobString() write a string to a blob.  It returns the number of
  %  characters written.
  %
  %  The format of the WriteBlobString method is:
  %
  %      ssize_t WriteBlobString(Image *image,const char *string)
  %
  %  A description of each parameter follows.
  %
  %    o image: the image.
  %
  %    o string: Specifies the string to write.
  %
  */
  MagickExport ssize_t WriteBlobString(Image *image,const char *string)
  {
    assert(image != (Image *) NULL);
    assert(image->signature == MagickCoreSignature);
    assert(string != (const char *) NULL);
    return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
  }
  