Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                         BBBB   L       OOO   BBBB                           %
      7 %                         B   B  L      O   O  B   B                          %
      8 %                         BBBB   L      O   O  BBBB                           %
      9 %                         B   B  L      O   O  B   B                          %
     10 %                         BBBB   LLLLL   OOO   BBBB                           %
     11 %                                                                             %
     12 %                                                                             %
     13 %                     MagickCore Binary Large OBjectS Methods                 %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                 July 1999                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %
     37 %
     38 */
     39 
     40 /*
     42   Include declarations.
     43 */
     44 #ifdef __VMS
     45 #include  <types.h>
     46 #include  <mman.h>
     47 #endif
     48 #include "MagickCore/studio.h"
     49 #include "MagickCore/blob.h"
     50 #include "MagickCore/blob-private.h"
     51 #include "MagickCore/cache.h"
     52 #include "MagickCore/client.h"
     53 #include "MagickCore/constitute.h"
     54 #include "MagickCore/delegate.h"
     55 #include "MagickCore/exception.h"
     56 #include "MagickCore/exception-private.h"
     57 #include "MagickCore/image-private.h"
     58 #include "MagickCore/list.h"
     59 #include "MagickCore/locale_.h"
     60 #include "MagickCore/log.h"
     61 #include "MagickCore/magick.h"
     62 #include "MagickCore/memory_.h"
     63 #include "MagickCore/nt-base-private.h"
     64 #include "MagickCore/option.h"
     65 #include "MagickCore/policy.h"
     66 #include "MagickCore/resource_.h"
     67 #include "MagickCore/semaphore.h"
     68 #include "MagickCore/string_.h"
     69 #include "MagickCore/string-private.h"
     70 #include "MagickCore/token.h"
     71 #include "MagickCore/utility.h"
     72 #include "MagickCore/utility-private.h"
     73 #if defined(MAGICKCORE_ZLIB_DELEGATE)
     74 #include "zlib.h"
     75 #endif
     76 #if defined(MAGICKCORE_BZLIB_DELEGATE)
     77 #include "bzlib.h"
     78 #endif
     79 
     80 /*
     82   Define declarations.
     83 */
     84 #define MagickMaxBlobExtent  (8*8192)
     85 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
     86 # define MAP_ANONYMOUS  MAP_ANON
     87 #endif
     88 #if !defined(MAP_FAILED)
     89 #define MAP_FAILED  ((void *) -1)
     90 #endif
     91 #if defined(__OS2__)
     92 #include <io.h>
     93 #define _O_BINARY O_BINARY
     94 #endif
     95 
     96 /*
     98   Typedef declarations.
     99 */
    100 typedef union FileInfo
    101 {
    102   FILE
    103     *file;
    104 
    105 #if defined(MAGICKCORE_ZLIB_DELEGATE)
    106   gzFile
    107     gzfile;
    108 #endif
    109 
    110 #if defined(MAGICKCORE_BZLIB_DELEGATE)
    111   BZFILE
    112     *bzfile;
    113 #endif
    114 } FileInfo;
    115 
    116 struct _BlobInfo
    117 {
    118   size_t
    119     length,
    120     extent,
    121     quantum;
    122 
    123   MagickBooleanType
    124     mapped,
    125     eof;
    126 
    127   MagickOffsetType
    128     offset;
    129 
    130   MagickSizeType
    131     size;
    132 
    133   MagickBooleanType
    134     exempt,
    135     immutable,
    136     synchronize,
    137     status,
    138     temporary;
    139 
    140   StreamType
    141     type;
    142 
    143   FileInfo
    144     file_info;
    145 
    146   struct stat
    147     properties;
    148 
    149   StreamHandler
    150     stream;
    151 
    152   unsigned char
    153     *data;
    154 
    155   MagickBooleanType
    156     debug;
    157 
    158   SemaphoreInfo
    159     *semaphore;
    160 
    161   ssize_t
    162     reference_count;
    163 
    164   size_t
    165     signature;
    166 };
    167 
    168 /*
    170   Forward declarations.
    171 */
    172 static int
    173   SyncBlob(Image *);
    174 
    175 /*
    177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    178 %                                                                             %
    179 %                                                                             %
    180 %                                                                             %
    181 +   A t t a c h B l o b                                                       %
    182 %                                                                             %
    183 %                                                                             %
    184 %                                                                             %
    185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    186 %
    187 %  AttachBlob() attaches a blob to the BlobInfo structure.
    188 %
    189 %  The format of the AttachBlob method is:
    190 %
    191 %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
    192 %
    193 %  A description of each parameter follows:
    194 %
    195 %    o blob_info: Specifies a pointer to a BlobInfo structure.
    196 %
    197 %    o blob: the address of a character stream in one of the image formats
    198 %      understood by ImageMagick.
    199 %
    200 %    o length: This size_t integer reflects the length in bytes of the blob.
    201 %
    202 */
    203 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
    204   const size_t length)
    205 {
    206   assert(blob_info != (BlobInfo *) NULL);
    207   if (blob_info->debug != MagickFalse)
    208     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    209   blob_info->length=length;
    210   blob_info->extent=length;
    211   blob_info->quantum=(size_t) MagickMaxBlobExtent;
    212   blob_info->offset=0;
    213   blob_info->type=BlobStream;
    214   blob_info->file_info.file=(FILE *) NULL;
    215   blob_info->data=(unsigned char *) blob;
    216   blob_info->mapped=MagickFalse;
    217   blob_info->immutable=MagickTrue;
    218 }
    219 
    220 /*
    222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    223 %                                                                             %
    224 %                                                                             %
    225 %                                                                             %
    226 +   B l o b T o F i l e                                                       %
    227 %                                                                             %
    228 %                                                                             %
    229 %                                                                             %
    230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    231 %
    232 %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
    233 %  occurs otherwise MagickTrue.
    234 %
    235 %  The format of the BlobToFile method is:
    236 %
    237 %       MagickBooleanType BlobToFile(char *filename,const void *blob,
    238 %         const size_t length,ExceptionInfo *exception)
    239 %
    240 %  A description of each parameter follows:
    241 %
    242 %    o filename: Write the blob to this file.
    243 %
    244 %    o blob: the address of a blob.
    245 %
    246 %    o length: This length in bytes of the blob.
    247 %
    248 %    o exception: return any errors or warnings in this structure.
    249 %
    250 */
    251 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
    252   const size_t length,ExceptionInfo *exception)
    253 {
    254   int
    255     file;
    256 
    257   register size_t
    258     i;
    259 
    260   ssize_t
    261     count;
    262 
    263   assert(filename != (const char *) NULL);
    264   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
    265   assert(blob != (const void *) NULL);
    266   if (*filename == '\0')
    267     file=AcquireUniqueFileResource(filename);
    268   else
    269     file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
    270   if (file == -1)
    271     {
    272       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
    273       return(MagickFalse);
    274     }
    275   for (i=0; i < length; i+=count)
    276   {
    277     count=write(file,(const char *) blob+i,MagickMin(length-i,SSIZE_MAX));
    278     if (count <= 0)
    279       {
    280         count=0;
    281         if (errno != EINTR)
    282           break;
    283       }
    284   }
    285   file=close(file);
    286   if ((file == -1) || (i < length))
    287     {
    288       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
    289       return(MagickFalse);
    290     }
    291   return(MagickTrue);
    292 }
    293 
    294 /*
    296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    297 %                                                                             %
    298 %                                                                             %
    299 %                                                                             %
    300 %   B l o b T o I m a g e                                                     %
    301 %                                                                             %
    302 %                                                                             %
    303 %                                                                             %
    304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    305 %
    306 %  BlobToImage() implements direct to memory image formats.  It returns the
    307 %  blob as an image.
    308 %
    309 %  The format of the BlobToImage method is:
    310 %
    311 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
    312 %        const size_t length,ExceptionInfo *exception)
    313 %
    314 %  A description of each parameter follows:
    315 %
    316 %    o image_info: the image info.
    317 %
    318 %    o blob: the address of a character stream in one of the image formats
    319 %      understood by ImageMagick.
    320 %
    321 %    o length: This size_t integer reflects the length in bytes of the blob.
    322 %
    323 %    o exception: return any errors or warnings in this structure.
    324 %
    325 */
    326 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
    327   const size_t length,ExceptionInfo *exception)
    328 {
    329   const MagickInfo
    330     *magick_info;
    331 
    332   Image
    333     *image;
    334 
    335   ImageInfo
    336     *blob_info,
    337     *clone_info;
    338 
    339   MagickBooleanType
    340     status;
    341 
    342   assert(image_info != (ImageInfo *) NULL);
    343   assert(image_info->signature == MagickCoreSignature);
    344   if (image_info->debug != MagickFalse)
    345     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    346       image_info->filename);
    347   assert(exception != (ExceptionInfo *) NULL);
    348   if ((blob == (const void *) NULL) || (length == 0))
    349     {
    350       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
    351         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
    352       return((Image *) NULL);
    353     }
    354   blob_info=CloneImageInfo(image_info);
    355   blob_info->blob=(void *) blob;
    356   blob_info->length=length;
    357   if (*blob_info->magick == '\0')
    358     (void) SetImageInfo(blob_info,0,exception);
    359   magick_info=GetMagickInfo(blob_info->magick,exception);
    360   if (magick_info == (const MagickInfo *) NULL)
    361     {
    362       (void) ThrowMagickException(exception,GetMagickModule(),
    363         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
    364         blob_info->magick);
    365       blob_info=DestroyImageInfo(blob_info);
    366       return((Image *) NULL);
    367     }
    368   if (GetMagickBlobSupport(magick_info) != MagickFalse)
    369     {
    370       /*
    371         Native blob support for this image format.
    372       */
    373       (void) CopyMagickString(blob_info->filename,image_info->filename,
    374         MagickPathExtent);
    375       (void) CopyMagickString(blob_info->magick,image_info->magick,
    376         MagickPathExtent);
    377       image=ReadImage(blob_info,exception);
    378       if (image != (Image *) NULL)
    379         (void) DetachBlob(image->blob);
    380       blob_info=DestroyImageInfo(blob_info);
    381       return(image);
    382     }
    383   /*
    384     Write blob to a temporary file on disk.
    385   */
    386   blob_info->blob=(void *) NULL;
    387   blob_info->length=0;
    388   *blob_info->filename='\0';
    389   status=BlobToFile(blob_info->filename,blob,length,exception);
    390   if (status == MagickFalse)
    391     {
    392       (void) RelinquishUniqueFileResource(blob_info->filename);
    393       blob_info=DestroyImageInfo(blob_info);
    394       return((Image *) NULL);
    395     }
    396   clone_info=CloneImageInfo(blob_info);
    397   (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
    398     blob_info->magick,blob_info->filename);
    399   image=ReadImage(clone_info,exception);
    400   if (image != (Image *) NULL)
    401     {
    402       Image
    403         *images;
    404 
    405       /*
    406         Restore original filenames and image format.
    407       */
    408       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
    409       {
    410         (void) CopyMagickString(images->filename,image_info->filename,
    411           MagickPathExtent);
    412         (void) CopyMagickString(images->magick_filename,image_info->filename,
    413           MagickPathExtent);
    414         (void) CopyMagickString(images->magick,magick_info->name,
    415           MagickPathExtent);
    416         images=GetNextImageInList(images);
    417       }
    418     }
    419   clone_info=DestroyImageInfo(clone_info);
    420   (void) RelinquishUniqueFileResource(blob_info->filename);
    421   blob_info=DestroyImageInfo(blob_info);
    422   return(image);
    423 }
    424 
    425 /*
    427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    428 %                                                                             %
    429 %                                                                             %
    430 %                                                                             %
    431 +   C l o n e B l o b I n f o                                                 %
    432 %                                                                             %
    433 %                                                                             %
    434 %                                                                             %
    435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    436 %
    437 %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
    438 %  blob info is NULL, a new one.
    439 %
    440 %  The format of the CloneBlobInfo method is:
    441 %
    442 %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
    443 %
    444 %  A description of each parameter follows:
    445 %
    446 %    o blob_info: the blob info.
    447 %
    448 */
    449 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
    450 {
    451   BlobInfo
    452     *clone_info;
    453 
    454   clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
    455   if (clone_info == (BlobInfo *) NULL)
    456     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    457   GetBlobInfo(clone_info);
    458   if (blob_info == (BlobInfo *) NULL)
    459     return(clone_info);
    460   clone_info->length=blob_info->length;
    461   clone_info->extent=blob_info->extent;
    462   clone_info->synchronize=blob_info->synchronize;
    463   clone_info->quantum=blob_info->quantum;
    464   clone_info->mapped=blob_info->mapped;
    465   clone_info->eof=blob_info->eof;
    466   clone_info->offset=blob_info->offset;
    467   clone_info->size=blob_info->size;
    468   clone_info->exempt=blob_info->exempt;
    469   clone_info->immutable=blob_info->immutable;
    470   clone_info->status=blob_info->status;
    471   clone_info->temporary=blob_info->temporary;
    472   clone_info->type=blob_info->type;
    473   clone_info->file_info.file=blob_info->file_info.file;
    474   clone_info->properties=blob_info->properties;
    475   clone_info->stream=blob_info->stream;
    476   clone_info->data=blob_info->data;
    477   clone_info->debug=IsEventLogging();
    478   clone_info->reference_count=1;
    479   return(clone_info);
    480 }
    481 
    482 /*
    484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    485 %                                                                             %
    486 %                                                                             %
    487 %                                                                             %
    488 +   C l o s e B l o b                                                         %
    489 %                                                                             %
    490 %                                                                             %
    491 %                                                                             %
    492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    493 %
    494 %  CloseBlob() closes a stream associated with the image.
    495 %
    496 %  The format of the CloseBlob method is:
    497 %
    498 %      MagickBooleanType CloseBlob(Image *image)
    499 %
    500 %  A description of each parameter follows:
    501 %
    502 %    o image: the image.
    503 %
    504 */
    505 MagickExport MagickBooleanType CloseBlob(Image *image)
    506 {
    507   int
    508     status;
    509 
    510   /*
    511     Close image file.
    512   */
    513   assert(image != (Image *) NULL);
    514   assert(image->signature == MagickCoreSignature);
    515   if (image->debug != MagickFalse)
    516     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    517   assert(image->blob != (BlobInfo *) NULL);
    518   if (image->blob->type == UndefinedStream)
    519     return(MagickTrue);
    520   status=SyncBlob(image);
    521   switch (image->blob->type)
    522   {
    523     case UndefinedStream:
    524     case StandardStream:
    525       break;
    526     case FileStream:
    527     case PipeStream:
    528     {
    529       if (image->blob->synchronize != MagickFalse)
    530         status=fsync(fileno(image->blob->file_info.file));
    531       status=ferror(image->blob->file_info.file);
    532       break;
    533     }
    534     case ZipStream:
    535     {
    536 #if defined(MAGICKCORE_ZLIB_DELEGATE)
    537       (void) gzerror(image->blob->file_info.gzfile,&status);
    538 #endif
    539       break;
    540     }
    541     case BZipStream:
    542     {
    543 #if defined(MAGICKCORE_BZLIB_DELEGATE)
    544       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
    545 #endif
    546       break;
    547     }
    548     case FifoStream:
    549       break;
    550     case BlobStream:
    551     {
    552       if ((image->blob->file_info.file != (FILE *) NULL) &&
    553           (image->blob->synchronize != MagickFalse))
    554         {
    555           (void) fsync(fileno(image->blob->file_info.file));
    556           status=ferror(image->blob->file_info.file);
    557         }
    558       break;
    559     }
    560   }
    561   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
    562   image->blob->size=GetBlobSize(image);
    563   image->extent=image->blob->size;
    564   image->blob->eof=MagickFalse;
    565   if (image->blob->exempt != MagickFalse)
    566     {
    567       image->blob->type=UndefinedStream;
    568       return(image->blob->status);
    569     }
    570   switch (image->blob->type)
    571   {
    572     case UndefinedStream:
    573     case StandardStream:
    574       break;
    575     case FileStream:
    576     {
    577       status=fclose(image->blob->file_info.file);
    578       break;
    579     }
    580     case PipeStream:
    581     {
    582 #if defined(MAGICKCORE_HAVE_PCLOSE)
    583       status=pclose(image->blob->file_info.file);
    584 #endif
    585       break;
    586     }
    587     case ZipStream:
    588     {
    589 #if defined(MAGICKCORE_ZLIB_DELEGATE)
    590       status=gzclose(image->blob->file_info.gzfile);
    591 #endif
    592       break;
    593     }
    594     case BZipStream:
    595     {
    596 #if defined(MAGICKCORE_BZLIB_DELEGATE)
    597       BZ2_bzclose(image->blob->file_info.bzfile);
    598 #endif
    599       break;
    600     }
    601     case FifoStream:
    602       break;
    603     case BlobStream:
    604     {
    605       if (image->blob->file_info.file != (FILE *) NULL)
    606         status=fclose(image->blob->file_info.file);
    607       break;
    608     }
    609   }
    610   (void) DetachBlob(image->blob);
    611   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
    612   return(image->blob->status);
    613 }
    614 
    615 /*
    617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    618 %                                                                             %
    619 %                                                                             %
    620 %                                                                             %
    621 +   D e s t r o y B l o b                                                     %
    622 %                                                                             %
    623 %                                                                             %
    624 %                                                                             %
    625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    626 %
    627 %  DestroyBlob() deallocates memory associated with a blob.
    628 %
    629 %  The format of the DestroyBlob method is:
    630 %
    631 %      void DestroyBlob(Image *image)
    632 %
    633 %  A description of each parameter follows:
    634 %
    635 %    o image: the image.
    636 %
    637 */
    638 MagickExport void DestroyBlob(Image *image)
    639 {
    640   MagickBooleanType
    641     destroy;
    642 
    643   assert(image != (Image *) NULL);
    644   assert(image->signature == MagickCoreSignature);
    645   if (image->debug != MagickFalse)
    646     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    647   assert(image->blob != (BlobInfo *) NULL);
    648   assert(image->blob->signature == MagickCoreSignature);
    649   destroy=MagickFalse;
    650   LockSemaphoreInfo(image->blob->semaphore);
    651   image->blob->reference_count--;
    652   assert(image->blob->reference_count >= 0);
    653   if (image->blob->reference_count == 0)
    654     destroy=MagickTrue;
    655   UnlockSemaphoreInfo(image->blob->semaphore);
    656   if (destroy == MagickFalse)
    657     return;
    658   (void) CloseBlob(image);
    659   if (image->blob->mapped != MagickFalse)
    660     {
    661       (void) UnmapBlob(image->blob->data,image->blob->length);
    662       RelinquishMagickResource(MapResource,image->blob->length);
    663     }
    664   if (image->blob->semaphore != (SemaphoreInfo *) NULL)
    665     RelinquishSemaphoreInfo(&image->blob->semaphore);
    666   image->blob->signature=(~MagickCoreSignature);
    667   image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
    668 }
    669 
    670 /*
    672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    673 %                                                                             %
    674 %                                                                             %
    675 %                                                                             %
    676 +   D e t a c h B l o b                                                       %
    677 %                                                                             %
    678 %                                                                             %
    679 %                                                                             %
    680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    681 %
    682 %  DetachBlob() detaches a blob from the BlobInfo structure.
    683 %
    684 %  The format of the DetachBlob method is:
    685 %
    686 %      void *DetachBlob(BlobInfo *blob_info)
    687 %
    688 %  A description of each parameter follows:
    689 %
    690 %    o blob_info: Specifies a pointer to a BlobInfo structure.
    691 %
    692 */
    693 MagickExport void *DetachBlob(BlobInfo *blob_info)
    694 {
    695   void
    696     *data;
    697 
    698   assert(blob_info != (BlobInfo *) NULL);
    699   if (blob_info->debug != MagickFalse)
    700     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    701   if (blob_info->mapped != MagickFalse)
    702     {
    703       (void) UnmapBlob(blob_info->data,blob_info->length);
    704       blob_info->data=(unsigned char *) NULL;
    705       RelinquishMagickResource(MapResource,blob_info->length);
    706     }
    707   blob_info->mapped=MagickFalse;
    708   blob_info->length=0;
    709   blob_info->offset=0;
    710   blob_info->eof=MagickFalse;
    711   blob_info->exempt=MagickFalse;
    712   blob_info->immutable=MagickFalse;
    713   blob_info->type=UndefinedStream;
    714   blob_info->file_info.file=(FILE *) NULL;
    715   data=blob_info->data;
    716   blob_info->data=(unsigned char *) NULL;
    717   blob_info->stream=(StreamHandler) NULL;
    718   return(data);
    719 }
    720 
    721 /*
    723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    724 %                                                                             %
    725 %                                                                             %
    726 %                                                                             %
    727 +   D i s a s s o c i a t e B l o b                                           %
    728 %                                                                             %
    729 %                                                                             %
    730 %                                                                             %
    731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    732 %
    733 %  DisassociateBlob() disassociates the image stream.  It checks if the
    734 %  blob of the specified image is referenced by other images. If the reference
    735 %  count is higher then 1 a new blob is assigned to the specified image.
    736 %
    737 %  The format of the DisassociateBlob method is:
    738 %
    739 %      void DisassociateBlob(const Image *image)
    740 %
    741 %  A description of each parameter follows:
    742 %
    743 %    o image: the image.
    744 %
    745 */
    746 MagickExport void DisassociateBlob(Image *image)
    747 {
    748   BlobInfo
    749     *blob;
    750 
    751   MagickBooleanType
    752     clone;
    753 
    754   assert(image != (Image *) NULL);
    755   assert(image->signature == MagickCoreSignature);
    756   if (image->debug != MagickFalse)
    757     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    758   assert(image->blob != (BlobInfo *) NULL);
    759   assert(image->blob->signature == MagickCoreSignature);
    760   clone=MagickFalse;
    761   LockSemaphoreInfo(image->blob->semaphore);
    762   assert(image->blob->reference_count >= 0);
    763   if (image->blob->reference_count > 1)
    764     clone=MagickTrue;
    765   UnlockSemaphoreInfo(image->blob->semaphore);
    766   if (clone == MagickFalse)
    767     return;
    768   blob=CloneBlobInfo(image->blob);
    769   DestroyBlob(image);
    770   image->blob=blob;
    771 }
    772 
    773 /*
    775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    776 %                                                                             %
    777 %                                                                             %
    778 %                                                                             %
    779 +  D i s c a r d B l o b B y t e s                                            %
    780 %                                                                             %
    781 %                                                                             %
    782 %                                                                             %
    783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    784 %
    785 %  DiscardBlobBytes() discards bytes in a blob.
    786 %
    787 %  The format of the DiscardBlobBytes method is:
    788 %
    789 %      MagickBooleanType DiscardBlobBytes(Image *image,
    790 %        const MagickSizeType length)
    791 %
    792 %  A description of each parameter follows.
    793 %
    794 %    o image: the image.
    795 %
    796 %    o length:  the number of bytes to skip.
    797 %
    798 */
    799 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
    800   const MagickSizeType length)
    801 {
    802   register MagickOffsetType
    803     i;
    804 
    805   size_t
    806     quantum;
    807 
    808   ssize_t
    809     count;
    810 
    811   unsigned char
    812     buffer[16384];
    813 
    814   assert(image != (Image *) NULL);
    815   assert(image->signature == MagickCoreSignature);
    816   if (length != (MagickSizeType) ((MagickOffsetType) length))
    817     return(MagickFalse);
    818   count=0;
    819   for (i=0; i < (MagickOffsetType) length; i+=count)
    820   {
    821     quantum=(size_t) MagickMin(length-i,sizeof(buffer));
    822     (void) ReadBlobStream(image,quantum,buffer,&count);
    823     if (count <= 0)
    824       {
    825         count=0;
    826         if (errno != EINTR)
    827           break;
    828       }
    829   }
    830   return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
    831 }
    832 
    833 /*
    835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    836 %                                                                             %
    837 %                                                                             %
    838 %                                                                             %
    839 +   D u p l i c a t e s B l o b                                               %
    840 %                                                                             %
    841 %                                                                             %
    842 %                                                                             %
    843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    844 %
    845 %  DuplicateBlob() duplicates a blob descriptor.
    846 %
    847 %  The format of the DuplicateBlob method is:
    848 %
    849 %      void DuplicateBlob(Image *image,const Image *duplicate)
    850 %
    851 %  A description of each parameter follows:
    852 %
    853 %    o image: the image.
    854 %
    855 %    o duplicate: the duplicate image.
    856 %
    857 */
    858 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
    859 {
    860   assert(image != (Image *) NULL);
    861   assert(image->signature == MagickCoreSignature);
    862   if (image->debug != MagickFalse)
    863     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    864   assert(duplicate != (Image *) NULL);
    865   assert(duplicate->signature == MagickCoreSignature);
    866   DestroyBlob(image);
    867   image->blob=ReferenceBlob(duplicate->blob);
    868 }
    869 
    870 /*
    872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    873 %                                                                             %
    874 %                                                                             %
    875 %                                                                             %
    876 +  E O F B l o b                                                              %
    877 %                                                                             %
    878 %                                                                             %
    879 %                                                                             %
    880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    881 %
    882 %  EOFBlob() returns a non-zero value when EOF has been detected reading from
    883 %  a blob or file.
    884 %
    885 %  The format of the EOFBlob method is:
    886 %
    887 %      int EOFBlob(const Image *image)
    888 %
    889 %  A description of each parameter follows:
    890 %
    891 %    o image: the image.
    892 %
    893 */
    894 MagickExport int EOFBlob(const Image *image)
    895 {
    896   assert(image != (Image *) NULL);
    897   assert(image->signature == MagickCoreSignature);
    898   if (image->debug != MagickFalse)
    899     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
    900   assert(image->blob != (BlobInfo *) NULL);
    901   assert(image->blob->type != UndefinedStream);
    902   switch (image->blob->type)
    903   {
    904     case UndefinedStream:
    905     case StandardStream:
    906       break;
    907     case FileStream:
    908     case PipeStream:
    909     {
    910       image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
    911         MagickFalse;
    912       break;
    913     }
    914     case ZipStream:
    915     {
    916       image->blob->eof=MagickFalse;
    917       break;
    918     }
    919     case BZipStream:
    920     {
    921 #if defined(MAGICKCORE_BZLIB_DELEGATE)
    922       int
    923         status;
    924 
    925       status=0;
    926       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
    927       image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
    928 #endif
    929       break;
    930     }
    931     case FifoStream:
    932     {
    933       image->blob->eof=MagickFalse;
    934       break;
    935     }
    936     case BlobStream:
    937       break;
    938   }
    939   return((int) image->blob->eof);
    940 }
    941 
    942 /*
    944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    945 %                                                                             %
    946 %                                                                             %
    947 %                                                                             %
    948 %   F i l e T o B l o b                                                       %
    949 %                                                                             %
    950 %                                                                             %
    951 %                                                                             %
    952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    953 %
    954 %  FileToBlob() returns the contents of a file as a buffer terminated with
    955 %  the '\0' character.  The length of the buffer (not including the extra
    956 %  terminating '\0' character) is returned via the 'length' parameter.  Free
    957 %  the buffer with RelinquishMagickMemory().
    958 %
    959 %  The format of the FileToBlob method is:
    960 %
    961 %      void *FileToBlob(const char *filename,const size_t extent,
    962 %        size_t *length,ExceptionInfo *exception)
    963 %
    964 %  A description of each parameter follows:
    965 %
    966 %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
    967 %      an error occurs NULL is returned.
    968 %
    969 %    o filename: the filename.
    970 %
    971 %    o extent:  The maximum length of the blob.
    972 %
    973 %    o length: On return, this reflects the actual length of the blob.
    974 %
    975 %    o exception: return any errors or warnings in this structure.
    976 %
    977 */
    978 MagickExport void *FileToBlob(const char *filename,const size_t extent,
    979   size_t *length,ExceptionInfo *exception)
    980 {
    981   int
    982     file;
    983 
    984   MagickOffsetType
    985     offset;
    986 
    987   register size_t
    988     i;
    989 
    990   ssize_t
    991     count;
    992 
    993   unsigned char
    994     *blob;
    995 
    996   void
    997     *map;
    998 
    999   assert(filename != (const char *) NULL);
   1000   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
   1001   assert(exception != (ExceptionInfo *) NULL);
   1002   *length=0;
   1003   file=fileno(stdin);
   1004   if (LocaleCompare(filename,"-") != 0)
   1005     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
   1006   if (file == -1)
   1007     {
   1008       ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
   1009       return(NULL);
   1010     }
   1011   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
   1012   count=0;
   1013   if ((file == fileno(stdin)) || (offset < 0) ||
   1014       (offset != (MagickOffsetType) ((ssize_t) offset)))
   1015     {
   1016       size_t
   1017         quantum;
   1018 
   1019       struct stat
   1020         file_stats;
   1021 
   1022       /*
   1023         Stream is not seekable.
   1024       */
   1025       offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
   1026       quantum=(size_t) MagickMaxBufferExtent;
   1027       if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
   1028         quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   1029       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
   1030       for (i=0; blob != (unsigned char *) NULL; i+=count)
   1031       {
   1032         count=read(file,blob+i,quantum);
   1033         if (count <= 0)
   1034           {
   1035             count=0;
   1036             if (errno != EINTR)
   1037               break;
   1038           }
   1039         if (~((size_t) i) < (quantum+1))
   1040           {
   1041             blob=(unsigned char *) RelinquishMagickMemory(blob);
   1042             break;
   1043           }
   1044         blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
   1045           sizeof(*blob));
   1046         if ((size_t) (i+count) >= extent)
   1047           break;
   1048       }
   1049       if (LocaleCompare(filename,"-") != 0)
   1050         file=close(file);
   1051       if (blob == (unsigned char *) NULL)
   1052         {
   1053           (void) ThrowMagickException(exception,GetMagickModule(),
   1054             ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
   1055           return(NULL);
   1056         }
   1057       if (file == -1)
   1058         {
   1059           blob=(unsigned char *) RelinquishMagickMemory(blob);
   1060           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
   1061           return(NULL);
   1062         }
   1063       *length=(size_t) MagickMin(i+count,extent);
   1064       blob[*length]='\0';
   1065       return(blob);
   1066     }
   1067   *length=(size_t) MagickMin(offset,(MagickOffsetType)
   1068     MagickMin(extent,SSIZE_MAX));
   1069   blob=(unsigned char *) NULL;
   1070   if (~(*length) >= (MagickPathExtent-1))
   1071     blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
   1072       sizeof(*blob));
   1073   if (blob == (unsigned char *) NULL)
   1074     {
   1075       file=close(file);
   1076       (void) ThrowMagickException(exception,GetMagickModule(),
   1077         ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
   1078       return(NULL);
   1079     }
   1080   map=MapBlob(file,ReadMode,0,*length);
   1081   if (map != (unsigned char *) NULL)
   1082     {
   1083       (void) memcpy(blob,map,*length);
   1084       (void) UnmapBlob(map,*length);
   1085     }
   1086   else
   1087     {
   1088       (void) lseek(file,0,SEEK_SET);
   1089       for (i=0; i < *length; i+=count)
   1090       {
   1091         count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
   1092         if (count <= 0)
   1093           {
   1094             count=0;
   1095             if (errno != EINTR)
   1096               break;
   1097           }
   1098       }
   1099       if (i < *length)
   1100         {
   1101           file=close(file)-1;
   1102           blob=(unsigned char *) RelinquishMagickMemory(blob);
   1103           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
   1104           return(NULL);
   1105         }
   1106     }
   1107   blob[*length]='\0';
   1108   if (LocaleCompare(filename,"-") != 0)
   1109     file=close(file);
   1110   if (file == -1)
   1111     {
   1112       blob=(unsigned char *) RelinquishMagickMemory(blob);
   1113       ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
   1114     }
   1115   return(blob);
   1116 }
   1117 
   1118 /*
   1120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1121 %                                                                             %
   1122 %                                                                             %
   1123 %                                                                             %
   1124 %   F i l e T o I m a g e                                                     %
   1125 %                                                                             %
   1126 %                                                                             %
   1127 %                                                                             %
   1128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1129 %
   1130 %  FileToImage() write the contents of a file to an image.
   1131 %
   1132 %  The format of the FileToImage method is:
   1133 %
   1134 %      MagickBooleanType FileToImage(Image *,const char *filename)
   1135 %
   1136 %  A description of each parameter follows:
   1137 %
   1138 %    o image: the image.
   1139 %
   1140 %    o filename: the filename.
   1141 %
   1142 */
   1143 
   1144 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
   1145   const void *data)
   1146 {
   1147   MagickSizeType
   1148     extent;
   1149 
   1150   register unsigned char
   1151     *q;
   1152 
   1153   assert(image->blob != (BlobInfo *) NULL);
   1154   assert(image->blob->type != UndefinedStream);
   1155   assert(data != NULL);
   1156   if (image->blob->type != BlobStream)
   1157     return(WriteBlob(image,length,(const unsigned char *) data));
   1158   extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
   1159   if (extent >= image->blob->extent)
   1160     {
   1161       extent=image->blob->extent+image->blob->quantum+length;
   1162       image->blob->quantum<<=1;
   1163       if (SetBlobExtent(image,extent) == MagickFalse)
   1164         return(0);
   1165     }
   1166   q=image->blob->data+image->blob->offset;
   1167   (void) memcpy(q,data,length);
   1168   image->blob->offset+=length;
   1169   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
   1170     image->blob->length=(size_t) image->blob->offset;
   1171   return((ssize_t) length);
   1172 }
   1173 
   1174 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
   1175   ExceptionInfo *exception)
   1176 {
   1177   int
   1178     file;
   1179 
   1180   size_t
   1181     length,
   1182     quantum;
   1183 
   1184   ssize_t
   1185     count;
   1186 
   1187   struct stat
   1188     file_stats;
   1189 
   1190   unsigned char
   1191     *blob;
   1192 
   1193   assert(image != (const Image *) NULL);
   1194   assert(image->signature == MagickCoreSignature);
   1195   assert(filename != (const char *) NULL);
   1196   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
   1197   file=fileno(stdin);
   1198   if (LocaleCompare(filename,"-") != 0)
   1199     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
   1200   if (file == -1)
   1201     {
   1202       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
   1203       return(MagickFalse);
   1204     }
   1205   quantum=(size_t) MagickMaxBufferExtent;
   1206   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
   1207     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   1208   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
   1209   if (blob == (unsigned char *) NULL)
   1210     {
   1211       file=close(file);
   1212       ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
   1213         filename);
   1214       return(MagickFalse);
   1215     }
   1216   for ( ; ; )
   1217   {
   1218     count=read(file,blob,quantum);
   1219     if (count <= 0)
   1220       {
   1221         count=0;
   1222         if (errno != EINTR)
   1223           break;
   1224       }
   1225     length=(size_t) count;
   1226     count=WriteBlobStream(image,length,blob);
   1227     if (count != (ssize_t) length)
   1228       {
   1229         ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
   1230         break;
   1231       }
   1232   }
   1233   file=close(file);
   1234   if (file == -1)
   1235     ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
   1236   blob=(unsigned char *) RelinquishMagickMemory(blob);
   1237   return(MagickTrue);
   1238 }
   1239 
   1240 /*
   1242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1243 %                                                                             %
   1244 %                                                                             %
   1245 %                                                                             %
   1246 +   G e t B l o b E r r o r                                                   %
   1247 %                                                                             %
   1248 %                                                                             %
   1249 %                                                                             %
   1250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1251 %
   1252 %  GetBlobError() returns MagickTrue if the blob associated with the specified
   1253 %  image encountered an error.
   1254 %
   1255 %  The format of the GetBlobError method is:
   1256 %
   1257 %       MagickBooleanType GetBlobError(const Image *image)
   1258 %
   1259 %  A description of each parameter follows:
   1260 %
   1261 %    o image: the image.
   1262 %
   1263 */
   1264 MagickExport MagickBooleanType GetBlobError(const Image *image)
   1265 {
   1266   assert(image != (const Image *) NULL);
   1267   assert(image->signature == MagickCoreSignature);
   1268   if (image->debug != MagickFalse)
   1269     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1270   return(image->blob->status);
   1271 }
   1272 
   1273 /*
   1275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1276 %                                                                             %
   1277 %                                                                             %
   1278 %                                                                             %
   1279 +   G e t B l o b F i l e H a n d l e                                         %
   1280 %                                                                             %
   1281 %                                                                             %
   1282 %                                                                             %
   1283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1284 %
   1285 %  GetBlobFileHandle() returns the file handle associated with the image blob.
   1286 %
   1287 %  The format of the GetBlobFile method is:
   1288 %
   1289 %      FILE *GetBlobFileHandle(const Image *image)
   1290 %
   1291 %  A description of each parameter follows:
   1292 %
   1293 %    o image: the image.
   1294 %
   1295 */
   1296 MagickExport FILE *GetBlobFileHandle(const Image *image)
   1297 {
   1298   assert(image != (const Image *) NULL);
   1299   assert(image->signature == MagickCoreSignature);
   1300   return(image->blob->file_info.file);
   1301 }
   1302 
   1303 /*
   1305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1306 %                                                                             %
   1307 %                                                                             %
   1308 %                                                                             %
   1309 +   G e t B l o b I n f o                                                     %
   1310 %                                                                             %
   1311 %                                                                             %
   1312 %                                                                             %
   1313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1314 %
   1315 %  GetBlobInfo() initializes the BlobInfo structure.
   1316 %
   1317 %  The format of the GetBlobInfo method is:
   1318 %
   1319 %      void GetBlobInfo(BlobInfo *blob_info)
   1320 %
   1321 %  A description of each parameter follows:
   1322 %
   1323 %    o blob_info: Specifies a pointer to a BlobInfo structure.
   1324 %
   1325 */
   1326 MagickExport void GetBlobInfo(BlobInfo *blob_info)
   1327 {
   1328   assert(blob_info != (BlobInfo *) NULL);
   1329   (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
   1330   blob_info->type=UndefinedStream;
   1331   blob_info->quantum=(size_t) MagickMaxBlobExtent;
   1332   blob_info->properties.st_mtime=time((time_t *) NULL);
   1333   blob_info->properties.st_ctime=time((time_t *) NULL);
   1334   blob_info->debug=IsEventLogging();
   1335   blob_info->reference_count=1;
   1336   blob_info->semaphore=AcquireSemaphoreInfo();
   1337   blob_info->signature=MagickCoreSignature;
   1338 }
   1339 
   1340 /*
   1342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1343 %                                                                             %
   1344 %                                                                             %
   1345 %                                                                             %
   1346 %  G e t B l o b P r o p e r t i e s                                          %
   1347 %                                                                             %
   1348 %                                                                             %
   1349 %                                                                             %
   1350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1351 %
   1352 %  GetBlobProperties() returns information about an image blob.
   1353 %
   1354 %  The format of the GetBlobProperties method is:
   1355 %
   1356 %      const struct stat *GetBlobProperties(const Image *image)
   1357 %
   1358 %  A description of each parameter follows:
   1359 %
   1360 %    o image: the image.
   1361 %
   1362 */
   1363 MagickExport const struct stat *GetBlobProperties(const Image *image)
   1364 {
   1365   assert(image != (Image *) NULL);
   1366   assert(image->signature == MagickCoreSignature);
   1367   if (image->debug != MagickFalse)
   1368     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1369   return(&image->blob->properties);
   1370 }
   1371 
   1372 /*
   1374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1375 %                                                                             %
   1376 %                                                                             %
   1377 %                                                                             %
   1378 +  G e t B l o b S i z e                                                      %
   1379 %                                                                             %
   1380 %                                                                             %
   1381 %                                                                             %
   1382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1383 %
   1384 %  GetBlobSize() returns the current length of the image file or blob; zero is
   1385 %  returned if the size cannot be determined.
   1386 %
   1387 %  The format of the GetBlobSize method is:
   1388 %
   1389 %      MagickSizeType GetBlobSize(const Image *image)
   1390 %
   1391 %  A description of each parameter follows:
   1392 %
   1393 %    o image: the image.
   1394 %
   1395 */
   1396 MagickExport MagickSizeType GetBlobSize(const Image *image)
   1397 {
   1398   MagickSizeType
   1399     extent;
   1400 
   1401   assert(image != (Image *) NULL);
   1402   assert(image->signature == MagickCoreSignature);
   1403   if (image->debug != MagickFalse)
   1404     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1405   assert(image->blob != (BlobInfo *) NULL);
   1406   extent=0;
   1407   switch (image->blob->type)
   1408   {
   1409     case UndefinedStream:
   1410     {
   1411       extent=image->blob->size;
   1412       break;
   1413     }
   1414     case StandardStream:
   1415     {
   1416       extent=image->blob->size;
   1417       break;
   1418     }
   1419     case FileStream:
   1420     {
   1421       if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
   1422         extent=(MagickSizeType) image->blob->properties.st_size;
   1423       break;
   1424     }
   1425     case PipeStream:
   1426     {
   1427       extent=image->blob->size;
   1428       break;
   1429     }
   1430     case ZipStream:
   1431     case BZipStream:
   1432     {
   1433       MagickBooleanType
   1434         status;
   1435 
   1436       status=GetPathAttributes(image->filename,&image->blob->properties);
   1437       if (status != MagickFalse)
   1438         extent=(MagickSizeType) image->blob->properties.st_size;
   1439       break;
   1440     }
   1441     case FifoStream:
   1442       break;
   1443     case BlobStream:
   1444     {
   1445       extent=(MagickSizeType) image->blob->length;
   1446       break;
   1447     }
   1448   }
   1449   return(extent);
   1450 }
   1451 
   1452 /*
   1454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1455 %                                                                             %
   1456 %                                                                             %
   1457 %                                                                             %
   1458 +   G e t B l o b S t r e a m D a t a                                         %
   1459 %                                                                             %
   1460 %                                                                             %
   1461 %                                                                             %
   1462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1463 %
   1464 %  GetBlobStreamData() returns the stream data for the image.
   1465 %
   1466 %  The format of the GetBlobStreamData method is:
   1467 %
   1468 %      void *GetBlobStreamData(const Image *image)
   1469 %
   1470 %  A description of each parameter follows:
   1471 %
   1472 %    o image: the image.
   1473 %
   1474 */
   1475 MagickExport void *GetBlobStreamData(const Image *image)
   1476 {
   1477   assert(image != (const Image *) NULL);
   1478   assert(image->signature == MagickCoreSignature);
   1479   return(image->blob->data);
   1480 }
   1481 
   1482 /*
   1484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1485 %                                                                             %
   1486 %                                                                             %
   1487 %                                                                             %
   1488 +   G e t B l o b S t r e a m H a n d l e r                                   %
   1489 %                                                                             %
   1490 %                                                                             %
   1491 %                                                                             %
   1492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1493 %
   1494 %  GetBlobStreamHandler() returns the stream handler for the image.
   1495 %
   1496 %  The format of the GetBlobStreamHandler method is:
   1497 %
   1498 %      StreamHandler GetBlobStreamHandler(const Image *image)
   1499 %
   1500 %  A description of each parameter follows:
   1501 %
   1502 %    o image: the image.
   1503 %
   1504 */
   1505 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
   1506 {
   1507   assert(image != (const Image *) NULL);
   1508   assert(image->signature == MagickCoreSignature);
   1509   if (image->debug != MagickFalse)
   1510     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1511   return(image->blob->stream);
   1512 }
   1513 
   1514 /*
   1516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1517 %                                                                             %
   1518 %                                                                             %
   1519 %                                                                             %
   1520 %   I m a g e T o B l o b                                                     %
   1521 %                                                                             %
   1522 %                                                                             %
   1523 %                                                                             %
   1524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1525 %
   1526 %  ImageToBlob() implements direct to memory image formats.  It returns the
   1527 %  image as a formatted blob and its length.  The magick member of the Image
   1528 %  structure determines the format of the returned blob (GIF, JPEG, PNG,
   1529 %  etc.).  This method is the equivalent of WriteImage(), but writes the
   1530 %  formatted "file" to a memory buffer rather than to an actual file.
   1531 %
   1532 %  The format of the ImageToBlob method is:
   1533 %
   1534 %      void *ImageToBlob(const ImageInfo *image_info,Image *image,
   1535 %        size_t *length,ExceptionInfo *exception)
   1536 %
   1537 %  A description of each parameter follows:
   1538 %
   1539 %    o image_info: the image info.
   1540 %
   1541 %    o image: the image.
   1542 %
   1543 %    o length: return the actual length of the blob.
   1544 %
   1545 %    o exception: return any errors or warnings in this structure.
   1546 %
   1547 */
   1548 MagickExport void *ImageToBlob(const ImageInfo *image_info,
   1549   Image *image,size_t *length,ExceptionInfo *exception)
   1550 {
   1551   const MagickInfo
   1552     *magick_info;
   1553 
   1554   ImageInfo
   1555     *blob_info;
   1556 
   1557   MagickBooleanType
   1558     status;
   1559 
   1560   void
   1561     *blob;
   1562 
   1563   assert(image_info != (const ImageInfo *) NULL);
   1564   assert(image_info->signature == MagickCoreSignature);
   1565   if (image_info->debug != MagickFalse)
   1566     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   1567       image_info->filename);
   1568   assert(image != (Image *) NULL);
   1569   assert(image->signature == MagickCoreSignature);
   1570   assert(exception != (ExceptionInfo *) NULL);
   1571   *length=0;
   1572   blob=(unsigned char *) NULL;
   1573   blob_info=CloneImageInfo(image_info);
   1574   blob_info->adjoin=MagickFalse;
   1575   (void) SetImageInfo(blob_info,1,exception);
   1576   if (*blob_info->magick != '\0')
   1577     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
   1578   magick_info=GetMagickInfo(image->magick,exception);
   1579   if (magick_info == (const MagickInfo *) NULL)
   1580     {
   1581       (void) ThrowMagickException(exception,GetMagickModule(),
   1582         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
   1583         image->magick);
   1584       blob_info=DestroyImageInfo(blob_info);
   1585       return(blob);
   1586     }
   1587   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
   1588   if (GetMagickBlobSupport(magick_info) != MagickFalse)
   1589     {
   1590       /*
   1591         Native blob support for this image format.
   1592       */
   1593       blob_info->length=0;
   1594       blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
   1595         sizeof(unsigned char));
   1596       if (blob_info->blob == NULL)
   1597         (void) ThrowMagickException(exception,GetMagickModule(),
   1598           ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
   1599       else
   1600         {
   1601           (void) CloseBlob(image);
   1602           image->blob->exempt=MagickTrue;
   1603           *image->filename='\0';
   1604           status=WriteImage(blob_info,image,exception);
   1605           *length=image->blob->length;
   1606           blob=DetachBlob(image->blob);
   1607           if (status == MagickFalse)
   1608             blob=RelinquishMagickMemory(blob);
   1609           else
   1610             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
   1611         }
   1612     }
   1613   else
   1614     {
   1615       char
   1616         unique[MagickPathExtent];
   1617 
   1618       int
   1619         file;
   1620 
   1621       /*
   1622         Write file to disk in blob image format.
   1623       */
   1624       file=AcquireUniqueFileResource(unique);
   1625       if (file == -1)
   1626         {
   1627           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
   1628             image_info->filename);
   1629         }
   1630       else
   1631         {
   1632           blob_info->file=fdopen(file,"wb");
   1633           if (blob_info->file != (FILE *) NULL)
   1634             {
   1635               (void) FormatLocaleString(image->filename,MagickPathExtent,
   1636                 "%s:%s",image->magick,unique);
   1637               status=WriteImage(blob_info,image,exception);
   1638               (void) CloseBlob(image);
   1639               (void) fclose(blob_info->file);
   1640               if (status != MagickFalse)
   1641                 blob=FileToBlob(unique,~0UL,length,exception);
   1642             }
   1643           (void) RelinquishUniqueFileResource(unique);
   1644         }
   1645     }
   1646   blob_info=DestroyImageInfo(blob_info);
   1647   return(blob);
   1648 }
   1649 
   1650 /*
   1652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1653 %                                                                             %
   1654 %                                                                             %
   1655 %                                                                             %
   1656 %   I m a g e T o F i l e                                                     %
   1657 %                                                                             %
   1658 %                                                                             %
   1659 %                                                                             %
   1660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1661 %
   1662 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
   1663 %  occurs otherwise MagickTrue.
   1664 %
   1665 %  The format of the ImageToFile method is:
   1666 %
   1667 %       MagickBooleanType ImageToFile(Image *image,char *filename,
   1668 %         ExceptionInfo *exception)
   1669 %
   1670 %  A description of each parameter follows:
   1671 %
   1672 %    o image: the image.
   1673 %
   1674 %    o filename: Write the image to this file.
   1675 %
   1676 %    o exception: return any errors or warnings in this structure.
   1677 %
   1678 */
   1679 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
   1680   ExceptionInfo *exception)
   1681 {
   1682   int
   1683     file;
   1684 
   1685   register const unsigned char
   1686     *p;
   1687 
   1688   register size_t
   1689     i;
   1690 
   1691   size_t
   1692     length,
   1693     quantum;
   1694 
   1695   ssize_t
   1696     count;
   1697 
   1698   struct stat
   1699     file_stats;
   1700 
   1701   unsigned char
   1702     *buffer;
   1703 
   1704   assert(image != (Image *) NULL);
   1705   assert(image->signature == MagickCoreSignature);
   1706   assert(image->blob != (BlobInfo *) NULL);
   1707   assert(image->blob->type != UndefinedStream);
   1708   if (image->debug != MagickFalse)
   1709     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
   1710   assert(filename != (const char *) NULL);
   1711   if (*filename == '\0')
   1712     file=AcquireUniqueFileResource(filename);
   1713   else
   1714     if (LocaleCompare(filename,"-") == 0)
   1715       file=fileno(stdout);
   1716     else
   1717       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
   1718   if (file == -1)
   1719     {
   1720       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
   1721       return(MagickFalse);
   1722     }
   1723   quantum=(size_t) MagickMaxBufferExtent;
   1724   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
   1725     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   1726   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
   1727   if (buffer == (unsigned char *) NULL)
   1728     {
   1729       file=close(file)-1;
   1730       (void) ThrowMagickException(exception,GetMagickModule(),
   1731         ResourceLimitError,"MemoryAllocationError","`%s'",filename);
   1732       return(MagickFalse);
   1733     }
   1734   length=0;
   1735   p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
   1736   for (i=0; count > 0; )
   1737   {
   1738     length=(size_t) count;
   1739     for (i=0; i < length; i+=count)
   1740     {
   1741       count=write(file,p+i,(size_t) (length-i));
   1742       if (count <= 0)
   1743         {
   1744           count=0;
   1745           if (errno != EINTR)
   1746             break;
   1747         }
   1748     }
   1749     if (i < length)
   1750       break;
   1751     p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
   1752   }
   1753   if (LocaleCompare(filename,"-") != 0)
   1754     file=close(file);
   1755   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
   1756   if ((file == -1) || (i < length))
   1757     {
   1758       if (file != -1)
   1759         file=close(file);
   1760       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
   1761       return(MagickFalse);
   1762     }
   1763   return(MagickTrue);
   1764 }
   1765 
   1766 /*
   1768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1769 %                                                                             %
   1770 %                                                                             %
   1771 %                                                                             %
   1772 %   I m a g e s T o B l o b                                                   %
   1773 %                                                                             %
   1774 %                                                                             %
   1775 %                                                                             %
   1776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1777 %
   1778 %  ImagesToBlob() implements direct to memory image formats.  It returns the
   1779 %  image sequence as a blob and its length.  The magick member of the ImageInfo
   1780 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
   1781 %
   1782 %  Note, some image formats do not permit multiple images to the same image
   1783 %  stream (e.g. JPEG).  in this instance, just the first image of the
   1784 %  sequence is returned as a blob.
   1785 %
   1786 %  The format of the ImagesToBlob method is:
   1787 %
   1788 %      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
   1789 %        size_t *length,ExceptionInfo *exception)
   1790 %
   1791 %  A description of each parameter follows:
   1792 %
   1793 %    o image_info: the image info.
   1794 %
   1795 %    o images: the image list.
   1796 %
   1797 %    o length: return the actual length of the blob.
   1798 %
   1799 %    o exception: return any errors or warnings in this structure.
   1800 %
   1801 */
   1802 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
   1803   size_t *length,ExceptionInfo *exception)
   1804 {
   1805   const MagickInfo
   1806     *magick_info;
   1807 
   1808   ImageInfo
   1809     *blob_info;
   1810 
   1811   MagickBooleanType
   1812     status;
   1813 
   1814   void
   1815     *blob;
   1816 
   1817   assert(image_info != (const ImageInfo *) NULL);
   1818   assert(image_info->signature == MagickCoreSignature);
   1819   if (image_info->debug != MagickFalse)
   1820     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   1821       image_info->filename);
   1822   assert(images != (Image *) NULL);
   1823   assert(images->signature == MagickCoreSignature);
   1824   assert(exception != (ExceptionInfo *) NULL);
   1825   *length=0;
   1826   blob=(unsigned char *) NULL;
   1827   blob_info=CloneImageInfo(image_info);
   1828   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
   1829     exception);
   1830   if (*blob_info->magick != '\0')
   1831     (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
   1832   magick_info=GetMagickInfo(images->magick,exception);
   1833   if (magick_info == (const MagickInfo *) NULL)
   1834     {
   1835       (void) ThrowMagickException(exception,GetMagickModule(),
   1836         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
   1837         images->magick);
   1838       blob_info=DestroyImageInfo(blob_info);
   1839       return(blob);
   1840     }
   1841   if (GetMagickAdjoin(magick_info) == MagickFalse)
   1842     {
   1843       blob_info=DestroyImageInfo(blob_info);
   1844       return(ImageToBlob(image_info,images,length,exception));
   1845     }
   1846   (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
   1847   if (GetMagickBlobSupport(magick_info) != MagickFalse)
   1848     {
   1849       /*
   1850         Native blob support for this images format.
   1851       */
   1852       blob_info->length=0;
   1853       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
   1854         sizeof(unsigned char));
   1855       if (blob_info->blob == (void *) NULL)
   1856         (void) ThrowMagickException(exception,GetMagickModule(),
   1857           ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
   1858       else
   1859         {
   1860           (void) CloseBlob(images);
   1861           images->blob->exempt=MagickTrue;
   1862           *images->filename='\0';
   1863           status=WriteImages(blob_info,images,images->filename,exception);
   1864           *length=images->blob->length;
   1865           blob=DetachBlob(images->blob);
   1866           if (status == MagickFalse)
   1867             blob=RelinquishMagickMemory(blob);
   1868           else
   1869             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
   1870         }
   1871     }
   1872   else
   1873     {
   1874       char
   1875         filename[MagickPathExtent],
   1876         unique[MagickPathExtent];
   1877 
   1878       int
   1879         file;
   1880 
   1881       /*
   1882         Write file to disk in blob images format.
   1883       */
   1884       file=AcquireUniqueFileResource(unique);
   1885       if (file == -1)
   1886         {
   1887           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
   1888             image_info->filename);
   1889         }
   1890       else
   1891         {
   1892           blob_info->file=fdopen(file,"wb");
   1893           if (blob_info->file != (FILE *) NULL)
   1894             {
   1895               (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
   1896                 images->magick,unique);
   1897               status=WriteImages(blob_info,images,filename,exception);
   1898               (void) CloseBlob(images);
   1899               (void) fclose(blob_info->file);
   1900               if (status != MagickFalse)
   1901                 blob=FileToBlob(unique,~0UL,length,exception);
   1902             }
   1903           (void) RelinquishUniqueFileResource(unique);
   1904         }
   1905     }
   1906   blob_info=DestroyImageInfo(blob_info);
   1907   return(blob);
   1908 }
   1909 /*
   1910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1911 %                                                                             %
   1912 %                                                                             %
   1913 %                                                                             %
   1914 %   I n j e c t I m a g e B l o b                                             %
   1915 %                                                                             %
   1916 %                                                                             %
   1917 %                                                                             %
   1918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1919 %
   1920 %  InjectImageBlob() injects the image with a copy of itself in the specified
   1921 %  format (e.g. inject JPEG into a PDF image).
   1922 %
   1923 %  The format of the InjectImageBlob method is:
   1924 %
   1925 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
   1926 %        Image *image,Image *inject_image,const char *format,
   1927 %        ExceptionInfo *exception)
   1928 %
   1929 %  A description of each parameter follows:
   1930 %
   1931 %    o image_info: the image info..
   1932 %
   1933 %    o image: the image.
   1934 %
   1935 %    o inject_image: inject into the image stream.
   1936 %
   1937 %    o format: the image format.
   1938 %
   1939 %    o exception: return any errors or warnings in this structure.
   1940 %
   1941 */
   1942 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
   1943   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
   1944 {
   1945   char
   1946     filename[MagickPathExtent];
   1947 
   1948   FILE
   1949     *unique_file;
   1950 
   1951   Image
   1952     *byte_image;
   1953 
   1954   ImageInfo
   1955     *write_info;
   1956 
   1957   int
   1958     file;
   1959 
   1960   MagickBooleanType
   1961     status;
   1962 
   1963   register ssize_t
   1964     i;
   1965 
   1966   size_t
   1967     quantum;
   1968 
   1969   ssize_t
   1970     count;
   1971 
   1972   struct stat
   1973     file_stats;
   1974 
   1975   unsigned char
   1976     *buffer;
   1977 
   1978   /*
   1979     Write inject image to a temporary file.
   1980   */
   1981   assert(image_info != (ImageInfo *) NULL);
   1982   assert(image_info->signature == MagickCoreSignature);
   1983   assert(image != (Image *) NULL);
   1984   assert(image->signature == MagickCoreSignature);
   1985   if (image->debug != MagickFalse)
   1986     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1987   assert(inject_image != (Image *) NULL);
   1988   assert(inject_image->signature == MagickCoreSignature);
   1989   assert(exception != (ExceptionInfo *) NULL);
   1990   unique_file=(FILE *) NULL;
   1991   file=AcquireUniqueFileResource(filename);
   1992   if (file != -1)
   1993     unique_file=fdopen(file,"wb");
   1994   if ((file == -1) || (unique_file == (FILE *) NULL))
   1995     {
   1996       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
   1997       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
   1998         image->filename);
   1999       return(MagickFalse);
   2000     }
   2001   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
   2002   if (byte_image == (Image *) NULL)
   2003     {
   2004       (void) fclose(unique_file);
   2005       (void) RelinquishUniqueFileResource(filename);
   2006       return(MagickFalse);
   2007     }
   2008   (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",format,
   2009     filename);
   2010   DestroyBlob(byte_image);
   2011   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
   2012   write_info=CloneImageInfo(image_info);
   2013   SetImageInfoFile(write_info,unique_file);
   2014   status=WriteImage(write_info,byte_image,exception);
   2015   write_info=DestroyImageInfo(write_info);
   2016   byte_image=DestroyImage(byte_image);
   2017   (void) fclose(unique_file);
   2018   if (status == MagickFalse)
   2019     {
   2020       (void) RelinquishUniqueFileResource(filename);
   2021       return(MagickFalse);
   2022     }
   2023   /*
   2024     Inject into image stream.
   2025   */
   2026   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
   2027   if (file == -1)
   2028     {
   2029       (void) RelinquishUniqueFileResource(filename);
   2030       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
   2031         image_info->filename);
   2032       return(MagickFalse);
   2033     }
   2034   quantum=(size_t) MagickMaxBufferExtent;
   2035   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
   2036     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
   2037   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
   2038   if (buffer == (unsigned char *) NULL)
   2039     {
   2040       (void) RelinquishUniqueFileResource(filename);
   2041       file=close(file);
   2042       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   2043         image->filename);
   2044     }
   2045   for (i=0; ; i+=count)
   2046   {
   2047     count=read(file,buffer,quantum);
   2048     if (count <= 0)
   2049       {
   2050         count=0;
   2051         if (errno != EINTR)
   2052           break;
   2053       }
   2054     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
   2055       MagickFalse;
   2056   }
   2057   file=close(file);
   2058   if (file == -1)
   2059     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
   2060   (void) RelinquishUniqueFileResource(filename);
   2061   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
   2062   return(status);
   2063 }
   2064 
   2065 /*
   2067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2068 %                                                                             %
   2069 %                                                                             %
   2070 %                                                                             %
   2071 %   I s B l o b E x e m p t                                                   %
   2072 %                                                                             %
   2073 %                                                                             %
   2074 %                                                                             %
   2075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2076 %
   2077 %  IsBlobExempt() returns true if the blob is exempt.
   2078 %
   2079 %  The format of the IsBlobExempt method is:
   2080 %
   2081 %       MagickBooleanType IsBlobExempt(const Image *image)
   2082 %
   2083 %  A description of each parameter follows:
   2084 %
   2085 %    o image: the image.
   2086 %
   2087 */
   2088 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
   2089 {
   2090   assert(image != (const Image *) NULL);
   2091   assert(image->signature == MagickCoreSignature);
   2092   if (image->debug != MagickFalse)
   2093     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2094   return(image->blob->exempt);
   2095 }
   2096 
   2097 /*
   2099 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2100 %                                                                             %
   2101 %                                                                             %
   2102 %                                                                             %
   2103 %   I s B l o b S e e k a b l e                                               %
   2104 %                                                                             %
   2105 %                                                                             %
   2106 %                                                                             %
   2107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2108 %
   2109 %  IsBlobSeekable() returns true if the blob is seekable.
   2110 %
   2111 %  The format of the IsBlobSeekable method is:
   2112 %
   2113 %       MagickBooleanType IsBlobSeekable(const Image *image)
   2114 %
   2115 %  A description of each parameter follows:
   2116 %
   2117 %    o image: the image.
   2118 %
   2119 */
   2120 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
   2121 {
   2122   MagickBooleanType
   2123     seekable;
   2124 
   2125   assert(image != (const Image *) NULL);
   2126   assert(image->signature == MagickCoreSignature);
   2127   if (image->debug != MagickFalse)
   2128     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2129   switch (image->blob->type)
   2130   {
   2131     case FileStream:
   2132     case BlobStream:
   2133     case ZipStream:
   2134     {
   2135       seekable=MagickTrue;
   2136       break;
   2137     }
   2138     default:
   2139     {
   2140       seekable=MagickFalse;
   2141       break;
   2142     }
   2143   }
   2144   return(seekable);
   2145 }
   2146 
   2147 /*
   2149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2150 %                                                                             %
   2151 %                                                                             %
   2152 %                                                                             %
   2153 %   I s B l o b T e m p o r a r y                                             %
   2154 %                                                                             %
   2155 %                                                                             %
   2156 %                                                                             %
   2157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2158 %
   2159 %  IsBlobTemporary() returns true if the blob is temporary.
   2160 %
   2161 %  The format of the IsBlobTemporary method is:
   2162 %
   2163 %       MagickBooleanType IsBlobTemporary(const Image *image)
   2164 %
   2165 %  A description of each parameter follows:
   2166 %
   2167 %    o image: the image.
   2168 %
   2169 */
   2170 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
   2171 {
   2172   assert(image != (const Image *) NULL);
   2173   assert(image->signature == MagickCoreSignature);
   2174   if (image->debug != MagickFalse)
   2175     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2176   return(image->blob->temporary);
   2177 }
   2178 
   2179 /*
   2181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2182 %                                                                             %
   2183 %                                                                             %
   2184 %                                                                             %
   2185 +  M a p B l o b                                                              %
   2186 %                                                                             %
   2187 %                                                                             %
   2188 %                                                                             %
   2189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2190 %
   2191 %  MapBlob() creates a mapping from a file to a binary large object.
   2192 %
   2193 %  The format of the MapBlob method is:
   2194 %
   2195 %      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
   2196 %        const size_t length)
   2197 %
   2198 %  A description of each parameter follows:
   2199 %
   2200 %    o file: map this file descriptor.
   2201 %
   2202 %    o mode: ReadMode, WriteMode, or IOMode.
   2203 %
   2204 %    o offset: starting at this offset within the file.
   2205 %
   2206 %    o length: the length of the mapping is returned in this pointer.
   2207 %
   2208 */
   2209 MagickExport void *MapBlob(int file,const MapMode mode,
   2210   const MagickOffsetType offset,const size_t length)
   2211 {
   2212 #if defined(MAGICKCORE_HAVE_MMAP)
   2213   int
   2214     flags,
   2215     protection;
   2216 
   2217   void
   2218     *map;
   2219 
   2220   /*
   2221     Map file.
   2222   */
   2223   flags=0;
   2224   if (file == -1)
   2225 #if defined(MAP_ANONYMOUS)
   2226     flags|=MAP_ANONYMOUS;
   2227 #else
   2228     return(NULL);
   2229 #endif
   2230   switch (mode)
   2231   {
   2232     case ReadMode:
   2233     default:
   2234     {
   2235       protection=PROT_READ;
   2236       flags|=MAP_PRIVATE;
   2237       break;
   2238     }
   2239     case WriteMode:
   2240     {
   2241       protection=PROT_WRITE;
   2242       flags|=MAP_SHARED;
   2243       break;
   2244     }
   2245     case IOMode:
   2246     {
   2247       protection=PROT_READ | PROT_WRITE;
   2248       flags|=MAP_SHARED;
   2249       break;
   2250     }
   2251   }
   2252 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
   2253   map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
   2254 #else
   2255   map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
   2256     offset);
   2257   if (map == MAP_FAILED)
   2258     map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
   2259 #endif
   2260   if (map == MAP_FAILED)
   2261     return(NULL);
   2262   return(map);
   2263 #else
   2264   (void) file;
   2265   (void) mode;
   2266   (void) offset;
   2267   (void) length;
   2268   return(NULL);
   2269 #endif
   2270 }
   2271 
   2272 /*
   2274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2275 %                                                                             %
   2276 %                                                                             %
   2277 %                                                                             %
   2278 +  M S B O r d e r L o n g                                                    %
   2279 %                                                                             %
   2280 %                                                                             %
   2281 %                                                                             %
   2282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2283 %
   2284 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
   2285 %  most-significant byte first.
   2286 %
   2287 %  The format of the MSBOrderLong method is:
   2288 %
   2289 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
   2290 %
   2291 %  A description of each parameter follows.
   2292 %
   2293 %   o  buffer:  Specifies a pointer to a buffer of integers.
   2294 %
   2295 %   o  length:  Specifies the length of the buffer.
   2296 %
   2297 */
   2298 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
   2299 {
   2300   int
   2301     c;
   2302 
   2303   register unsigned char
   2304     *p,
   2305     *q;
   2306 
   2307   assert(buffer != (unsigned char *) NULL);
   2308   q=buffer+length;
   2309   while (buffer < q)
   2310   {
   2311     p=buffer+3;
   2312     c=(int) (*p);
   2313     *p=(*buffer);
   2314     *buffer++=(unsigned char) c;
   2315     p=buffer+1;
   2316     c=(int) (*p);
   2317     *p=(*buffer);
   2318     *buffer++=(unsigned char) c;
   2319     buffer+=2;
   2320   }
   2321 }
   2322 
   2323 /*
   2325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2326 %                                                                             %
   2327 %                                                                             %
   2328 %                                                                             %
   2329 +  M S B O r d e r S h o r t                                                  %
   2330 %                                                                             %
   2331 %                                                                             %
   2332 %                                                                             %
   2333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2334 %
   2335 %  MSBOrderShort() converts a least-significant byte first buffer of integers
   2336 %  to most-significant byte first.
   2337 %
   2338 %  The format of the MSBOrderShort method is:
   2339 %
   2340 %      void MSBOrderShort(unsigned char *p,const size_t length)
   2341 %
   2342 %  A description of each parameter follows.
   2343 %
   2344 %   o  p:  Specifies a pointer to a buffer of integers.
   2345 %
   2346 %   o  length:  Specifies the length of the buffer.
   2347 %
   2348 */
   2349 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
   2350 {
   2351   int
   2352     c;
   2353 
   2354   register unsigned char
   2355     *q;
   2356 
   2357   assert(p != (unsigned char *) NULL);
   2358   q=p+length;
   2359   while (p < q)
   2360   {
   2361     c=(int) (*p);
   2362     *p=(*(p+1));
   2363     p++;
   2364     *p++=(unsigned char) c;
   2365   }
   2366 }
   2367 
   2368 /*
   2370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2371 %                                                                             %
   2372 %                                                                             %
   2373 %                                                                             %
   2374 +   O p e n B l o b                                                           %
   2375 %                                                                             %
   2376 %                                                                             %
   2377 %                                                                             %
   2378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2379 %
   2380 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
   2381 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
   2382 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
   2383 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
   2384 %  from a system command.
   2385 %
   2386 %  The format of the OpenBlob method is:
   2387 %
   2388 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
   2389 %        const BlobMode mode,ExceptionInfo *exception)
   2390 %
   2391 %  A description of each parameter follows:
   2392 %
   2393 %    o image_info: the image info.
   2394 %
   2395 %    o image: the image.
   2396 %
   2397 %    o mode: the mode for opening the file.
   2398 %
   2399 */
   2400 
   2401 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
   2402   Image *image)
   2403 {
   2404   const char
   2405     *option;
   2406 
   2407   int
   2408     status;
   2409 
   2410   size_t
   2411     size;
   2412 
   2413   size=16384;
   2414   option=GetImageOption(image_info,"stream:buffer-size");
   2415   if (option != (const char *) NULL)
   2416     size=StringToUnsignedLong(option);
   2417   status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
   2418     _IONBF : _IOFBF,size);
   2419   return(status == 0 ? MagickTrue : MagickFalse);
   2420 }
   2421 
   2422 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
   2423   Image *image,const BlobMode mode,ExceptionInfo *exception)
   2424 {
   2425   char
   2426     extension[MagickPathExtent],
   2427     filename[MagickPathExtent];
   2428 
   2429   const char
   2430     *type;
   2431 
   2432   MagickBooleanType
   2433     status;
   2434 
   2435   PolicyRights
   2436     rights;
   2437 
   2438   assert(image_info != (ImageInfo *) NULL);
   2439   assert(image_info->signature == MagickCoreSignature);
   2440   if (image_info->debug != MagickFalse)
   2441     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   2442       image_info->filename);
   2443   assert(image != (Image *) NULL);
   2444   assert(image->signature == MagickCoreSignature);
   2445   if (image_info->blob != (void *) NULL)
   2446     {
   2447       if (image_info->stream != (StreamHandler) NULL)
   2448         image->blob->stream=(StreamHandler) image_info->stream;
   2449       AttachBlob(image->blob,image_info->blob,image_info->length);
   2450       return(MagickTrue);
   2451     }
   2452   (void) DetachBlob(image->blob);
   2453   switch (mode)
   2454   {
   2455     default: type="r"; break;
   2456     case ReadBlobMode: type="r"; break;
   2457     case ReadBinaryBlobMode: type="rb"; break;
   2458     case WriteBlobMode: type="w"; break;
   2459     case WriteBinaryBlobMode: type="w+b"; break;
   2460     case AppendBlobMode: type="a"; break;
   2461     case AppendBinaryBlobMode: type="a+b"; break;
   2462   }
   2463   if (*type != 'r')
   2464     image->blob->synchronize=image_info->synchronize;
   2465   if (image_info->stream != (StreamHandler) NULL)
   2466     {
   2467       image->blob->stream=(StreamHandler) image_info->stream;
   2468       if (*type == 'w')
   2469         {
   2470           image->blob->type=FifoStream;
   2471           return(MagickTrue);
   2472         }
   2473     }
   2474   /*
   2475     Open image file.
   2476   */
   2477   *filename='\0';
   2478   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
   2479   rights=ReadPolicyRights;
   2480   if (*type == 'w')
   2481     rights=WritePolicyRights;
   2482   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
   2483     {
   2484       errno=EPERM;
   2485       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
   2486         "NotAuthorized","`%s'",filename);
   2487       return(MagickFalse);
   2488     }
   2489   if ((LocaleCompare(filename,"-") == 0) ||
   2490       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
   2491     {
   2492       image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
   2493 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
   2494       if (strchr(type,'b') != (char *) NULL)
   2495         setmode(fileno(image->blob->file_info.file),_O_BINARY);
   2496 #endif
   2497       image->blob->type=StandardStream;
   2498       image->blob->exempt=MagickTrue;
   2499       return(SetStreamBuffering(image_info,image));
   2500     }
   2501   if (LocaleNCompare(filename,"fd:",3) == 0)
   2502     {
   2503       char
   2504         fileMode[MagickPathExtent];
   2505 
   2506       *fileMode =(*type);
   2507       fileMode[1]='\0';
   2508       image->blob->file_info.file=fdopen(StringToLong(filename+3),fileMode);
   2509 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
   2510       if (strchr(type,'b') != (char *) NULL)
   2511         setmode(fileno(image->blob->file_info.file),_O_BINARY);
   2512 #endif
   2513       image->blob->type=StandardStream;
   2514       image->blob->exempt=MagickTrue;
   2515       return(SetStreamBuffering(image_info,image));
   2516     }
   2517 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
   2518   if (*filename == '|')
   2519     {
   2520       char
   2521         fileMode[MagickPathExtent],
   2522         *sanitize_command;
   2523 
   2524       /*
   2525         Pipe image to or from a system command.
   2526       */
   2527 #if defined(SIGPIPE)
   2528       if (*type == 'w')
   2529         (void) signal(SIGPIPE,SIG_IGN);
   2530 #endif
   2531       *fileMode =(*type);
   2532       fileMode[1]='\0';
   2533       sanitize_command=SanitizeString(filename+1);
   2534       image->blob->file_info.file=(FILE *) popen_utf8(sanitize_command,
   2535         fileMode);
   2536       sanitize_command=DestroyString(sanitize_command);
   2537       if (image->blob->file_info.file == (FILE *) NULL)
   2538         {
   2539           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
   2540           return(MagickFalse);
   2541         }
   2542       image->blob->type=PipeStream;
   2543       image->blob->exempt=MagickTrue;
   2544       return(SetStreamBuffering(image_info,image));
   2545     }
   2546 #endif
   2547   status=GetPathAttributes(filename,&image->blob->properties);
   2548 #if defined(S_ISFIFO)
   2549   if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
   2550     {
   2551       image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
   2552       if (image->blob->file_info.file == (FILE *) NULL)
   2553         {
   2554           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
   2555           return(MagickFalse);
   2556         }
   2557       image->blob->type=FileStream;
   2558       image->blob->exempt=MagickTrue;
   2559       return(SetStreamBuffering(image_info,image));
   2560     }
   2561 #endif
   2562   GetPathComponent(image->filename,ExtensionPath,extension);
   2563   if (*type == 'w')
   2564     {
   2565       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
   2566       if ((image_info->adjoin == MagickFalse) ||
   2567           (strchr(filename,'%') != (char *) NULL))
   2568         {
   2569           /*
   2570             Form filename for multi-part images.
   2571           */
   2572           (void) InterpretImageFilename(image_info,image,image->filename,(int)
   2573             image->scene,filename,exception);
   2574           if ((LocaleCompare(filename,image->filename) == 0) &&
   2575               ((GetPreviousImageInList(image) != (Image *) NULL) ||
   2576                (GetNextImageInList(image) != (Image *) NULL)))
   2577             {
   2578               char
   2579                 path[MagickPathExtent];
   2580 
   2581               GetPathComponent(image->filename,RootPath,path);
   2582               if (*extension == '\0')
   2583                 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
   2584                   path,(double) image->scene);
   2585               else
   2586                 (void) FormatLocaleString(filename,MagickPathExtent,
   2587                   "%s-%.20g.%s",path,(double) image->scene,extension);
   2588             }
   2589           (void) CopyMagickString(image->filename,filename,MagickPathExtent);
   2590 #if defined(macintosh)
   2591           SetApplicationType(filename,image_info->magick,'8BIM');
   2592 #endif
   2593         }
   2594     }
   2595   if (image_info->file != (FILE *) NULL)
   2596     {
   2597       image->blob->file_info.file=image_info->file;
   2598       image->blob->type=FileStream;
   2599       image->blob->exempt=MagickTrue;
   2600     }
   2601   else
   2602     if (*type == 'r')
   2603       {
   2604         image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
   2605         if (image->blob->file_info.file != (FILE *) NULL)
   2606           {
   2607             size_t
   2608               count;
   2609 
   2610             unsigned char
   2611               magick[3];
   2612 
   2613             image->blob->type=FileStream;
   2614             (void) SetStreamBuffering(image_info,image);
   2615             (void) ResetMagickMemory(magick,0,sizeof(magick));
   2616             count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
   2617             (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
   2618 #if defined(MAGICKCORE_POSIX_SUPPORT)
   2619             (void) fflush(image->blob->file_info.file);
   2620 #endif
   2621             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
   2622                "  read %.20g magic header bytes",(double) count);
   2623 #if defined(MAGICKCORE_ZLIB_DELEGATE)
   2624             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
   2625                 ((int) magick[2] == 0x08))
   2626               {
   2627                 if (image->blob->file_info.file != (FILE *) NULL)
   2628                   (void) fclose(image->blob->file_info.file);
   2629                 image->blob->file_info.file=(FILE *) NULL;
   2630                 image->blob->file_info.gzfile=gzopen(filename,type);
   2631                 if (image->blob->file_info.gzfile != (gzFile) NULL)
   2632                   image->blob->type=ZipStream;
   2633                }
   2634 #endif
   2635 #if defined(MAGICKCORE_BZLIB_DELEGATE)
   2636             if (strncmp((char *) magick,"BZh",3) == 0)
   2637               {
   2638                 if (image->blob->file_info.file != (FILE *) NULL)
   2639                   (void) fclose(image->blob->file_info.file);
   2640                 image->blob->file_info.file=(FILE *) NULL;
   2641                 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
   2642                 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
   2643                   image->blob->type=BZipStream;
   2644               }
   2645 #endif
   2646             if (image->blob->type == FileStream)
   2647               {
   2648                 const MagickInfo
   2649                   *magick_info;
   2650 
   2651                 ExceptionInfo
   2652                   *sans_exception;
   2653 
   2654                 size_t
   2655                   length;
   2656 
   2657                 sans_exception=AcquireExceptionInfo();
   2658                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
   2659                 sans_exception=DestroyExceptionInfo(sans_exception);
   2660                 length=(size_t) image->blob->properties.st_size;
   2661                 if ((magick_info != (const MagickInfo *) NULL) &&
   2662                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
   2663                     (length > MagickMaxBufferExtent) &&
   2664                     (AcquireMagickResource(MapResource,length) != MagickFalse))
   2665                   {
   2666                     void
   2667                       *blob;
   2668 
   2669                     blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
   2670                       length);
   2671                     if (blob == (void *) NULL)
   2672                       RelinquishMagickResource(MapResource,length);
   2673                     else
   2674                       {
   2675                         /*
   2676                           Format supports blobs-- use memory-mapped I/O.
   2677                         */
   2678                         if (image_info->file != (FILE *) NULL)
   2679                           image->blob->exempt=MagickFalse;
   2680                         else
   2681                           {
   2682                             (void) fclose(image->blob->file_info.file);
   2683                             image->blob->file_info.file=(FILE *) NULL;
   2684                           }
   2685                         AttachBlob(image->blob,blob,length);
   2686                         image->blob->mapped=MagickTrue;
   2687                       }
   2688                   }
   2689               }
   2690           }
   2691         }
   2692       else
   2693 #if defined(MAGICKCORE_ZLIB_DELEGATE)
   2694         if ((LocaleCompare(extension,"Z") == 0) ||
   2695             (LocaleCompare(extension,"gz") == 0) ||
   2696             (LocaleCompare(extension,"wmz") == 0) ||
   2697             (LocaleCompare(extension,"svgz") == 0))
   2698           {
   2699             if (mode == WriteBinaryBlobMode)
   2700               type="wb";
   2701             image->blob->file_info.gzfile=gzopen(filename,type);
   2702             if (image->blob->file_info.gzfile != (gzFile) NULL)
   2703               image->blob->type=ZipStream;
   2704           }
   2705         else
   2706 #endif
   2707 #if defined(MAGICKCORE_BZLIB_DELEGATE)
   2708           if (LocaleCompare(extension,"bz2") == 0)
   2709             {
   2710               image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
   2711               if (image->blob->file_info.bzfile != (BZFILE *) NULL)
   2712                 image->blob->type=BZipStream;
   2713             }
   2714           else
   2715 #endif
   2716             {
   2717               image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
   2718               if (image->blob->file_info.file != (FILE *) NULL)
   2719                 {
   2720                   image->blob->type=FileStream;
   2721                   (void) SetStreamBuffering(image_info,image);
   2722                 }
   2723        }
   2724   image->blob->status=MagickFalse;
   2725   if (image->blob->type != UndefinedStream)
   2726     image->blob->size=GetBlobSize(image);
   2727   else
   2728     {
   2729       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
   2730       return(MagickFalse);
   2731     }
   2732   return(MagickTrue);
   2733 }
   2734 
   2735 /*
   2737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2738 %                                                                             %
   2739 %                                                                             %
   2740 %                                                                             %
   2741 +   P i n g B l o b                                                           %
   2742 %                                                                             %
   2743 %                                                                             %
   2744 %                                                                             %
   2745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2746 %
   2747 %  PingBlob() returns all the attributes of an image or image sequence except
   2748 %  for the pixels.  It is much faster and consumes far less memory than
   2749 %  BlobToImage().  On failure, a NULL image is returned and exception
   2750 %  describes the reason for the failure.
   2751 %
   2752 %  The format of the PingBlob method is:
   2753 %
   2754 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
   2755 %        const size_t length,ExceptionInfo *exception)
   2756 %
   2757 %  A description of each parameter follows:
   2758 %
   2759 %    o image_info: the image info.
   2760 %
   2761 %    o blob: the address of a character stream in one of the image formats
   2762 %      understood by ImageMagick.
   2763 %
   2764 %    o length: This size_t integer reflects the length in bytes of the blob.
   2765 %
   2766 %    o exception: return any errors or warnings in this structure.
   2767 %
   2768 */
   2769 
   2770 #if defined(__cplusplus) || defined(c_plusplus)
   2771 extern "C" {
   2772 #endif
   2773 
   2774 static size_t PingStream(const Image *magick_unused(image),
   2775   const void *magick_unused(pixels),const size_t columns)
   2776 {
   2777   magick_unreferenced(image);
   2778   magick_unreferenced(pixels);
   2779   return(columns);
   2780 }
   2781 
   2782 #if defined(__cplusplus) || defined(c_plusplus)
   2783 }
   2784 #endif
   2785 
   2786 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
   2787   const size_t length,ExceptionInfo *exception)
   2788 {
   2789   Image
   2790     *image;
   2791 
   2792   ImageInfo
   2793     *ping_info;
   2794 
   2795   assert(image_info != (ImageInfo *) NULL);
   2796   assert(image_info->signature == MagickCoreSignature);
   2797   if (image_info->debug != MagickFalse)
   2798     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   2799       image_info->filename);
   2800   assert(exception != (ExceptionInfo *) NULL);
   2801   if ((blob == (const void *) NULL) || (length == 0))
   2802     {
   2803       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
   2804         "UnrecognizedImageFormat","`%s'",image_info->magick);
   2805       return((Image *) NULL);
   2806     }
   2807   ping_info=CloneImageInfo(image_info);
   2808   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
   2809   if (ping_info->blob == (const void *) NULL)
   2810     {
   2811       (void) ThrowMagickException(exception,GetMagickModule(),
   2812         ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
   2813       return((Image *) NULL);
   2814     }
   2815   (void) memcpy(ping_info->blob,blob,length);
   2816   ping_info->length=length;
   2817   ping_info->ping=MagickTrue;
   2818   image=ReadStream(ping_info,&PingStream,exception);
   2819   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
   2820   ping_info=DestroyImageInfo(ping_info);
   2821   return(image);
   2822 }
   2823 
   2824 /*
   2826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2827 %                                                                             %
   2828 %                                                                             %
   2829 %                                                                             %
   2830 +  R e a d B l o b                                                            %
   2831 %                                                                             %
   2832 %                                                                             %
   2833 %                                                                             %
   2834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2835 %
   2836 %  ReadBlob() reads data from the blob or image file and returns it.  It
   2837 %  returns the number of bytes read. If length is zero, ReadBlob() returns
   2838 %  zero and has no other results. If length is greater than SSIZE_MAX, the
   2839 %  result is unspecified.
   2840 %
   2841 %  The format of the ReadBlob method is:
   2842 %
   2843 %      ssize_t ReadBlob(Image *image,const size_t length,void *data)
   2844 %
   2845 %  A description of each parameter follows:
   2846 %
   2847 %    o image: the image.
   2848 %
   2849 %    o length:  Specifies an integer representing the number of bytes to read
   2850 %      from the file.
   2851 %
   2852 %    o data:  Specifies an area to place the information requested from the
   2853 %      file.
   2854 %
   2855 */
   2856 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
   2857 {
   2858   int
   2859     c;
   2860 
   2861   register unsigned char
   2862     *q;
   2863 
   2864   ssize_t
   2865     count;
   2866 
   2867   assert(image != (Image *) NULL);
   2868   assert(image->signature == MagickCoreSignature);
   2869   assert(image->blob != (BlobInfo *) NULL);
   2870   assert(image->blob->type != UndefinedStream);
   2871   if (length == 0)
   2872     return(0);
   2873   assert(data != (void *) NULL);
   2874   count=0;
   2875   q=(unsigned char *) data;
   2876   switch (image->blob->type)
   2877   {
   2878     case UndefinedStream:
   2879       break;
   2880     case StandardStream:
   2881     case FileStream:
   2882     case PipeStream:
   2883     {
   2884       switch (length)
   2885       {
   2886         default:
   2887         {
   2888           count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
   2889           break;
   2890         }
   2891         case 4:
   2892         {
   2893           c=getc(image->blob->file_info.file);
   2894           if (c == EOF)
   2895             break;
   2896           *q++=(unsigned char) c;
   2897           count++;
   2898         }
   2899         case 3:
   2900         {
   2901           c=getc(image->blob->file_info.file);
   2902           if (c == EOF)
   2903             break;
   2904           *q++=(unsigned char) c;
   2905           count++;
   2906         }
   2907         case 2:
   2908         {
   2909           c=getc(image->blob->file_info.file);
   2910           if (c == EOF)
   2911             break;
   2912           *q++=(unsigned char) c;
   2913           count++;
   2914         }
   2915         case 1:
   2916         {
   2917           c=getc(image->blob->file_info.file);
   2918           if (c == EOF)
   2919             break;
   2920           *q++=(unsigned char) c;
   2921           count++;
   2922         }
   2923         case 0:
   2924           break;
   2925       }
   2926       break;
   2927     }
   2928     case ZipStream:
   2929     {
   2930 #if defined(MAGICKCORE_ZLIB_DELEGATE)
   2931       switch (length)
   2932       {
   2933         default:
   2934         {
   2935           count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
   2936             (unsigned int) length);
   2937           break;
   2938         }
   2939         case 4:
   2940         {
   2941           c=gzgetc(image->blob->file_info.gzfile);
   2942           if (c == EOF)
   2943             break;
   2944           *q++=(unsigned char) c;
   2945           count++;
   2946         }
   2947         case 3:
   2948         {
   2949           c=gzgetc(image->blob->file_info.gzfile);
   2950           if (c == EOF)
   2951             break;
   2952           *q++=(unsigned char) c;
   2953           count++;
   2954         }
   2955         case 2:
   2956         {
   2957           c=gzgetc(image->blob->file_info.gzfile);
   2958           if (c == EOF)
   2959             break;
   2960           *q++=(unsigned char) c;
   2961           count++;
   2962         }
   2963         case 1:
   2964         {
   2965           c=gzgetc(image->blob->file_info.gzfile);
   2966           if (c == EOF)
   2967             break;
   2968           *q++=(unsigned char) c;
   2969           count++;
   2970         }
   2971         case 0:
   2972           break;
   2973       }
   2974 #endif
   2975       break;
   2976     }
   2977     case BZipStream:
   2978     {
   2979 #if defined(MAGICKCORE_BZLIB_DELEGATE)
   2980       count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
   2981 #endif
   2982       break;
   2983     }
   2984     case FifoStream:
   2985       break;
   2986     case BlobStream:
   2987     {
   2988       register const unsigned char
   2989         *p;
   2990 
   2991       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
   2992         {
   2993           image->blob->eof=MagickTrue;
   2994           break;
   2995         }
   2996       p=image->blob->data+image->blob->offset;
   2997       count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
   2998       image->blob->offset+=count;
   2999       if (count != (ssize_t) length)
   3000         image->blob->eof=MagickTrue;
   3001       (void) memcpy(q,p,(size_t) count);
   3002       break;
   3003     }
   3004   }
   3005   return(count);
   3006 }
   3007 
   3008 /*
   3010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3011 %                                                                             %
   3012 %                                                                             %
   3013 %                                                                             %
   3014 +  R e a d B l o b B y t e                                                    %
   3015 %                                                                             %
   3016 %                                                                             %
   3017 %                                                                             %
   3018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3019 %
   3020 %  ReadBlobByte() reads a single byte from the image file and returns it.
   3021 %
   3022 %  The format of the ReadBlobByte method is:
   3023 %
   3024 %      int ReadBlobByte(Image *image)
   3025 %
   3026 %  A description of each parameter follows.
   3027 %
   3028 %    o image: the image.
   3029 %
   3030 */
   3031 MagickExport int ReadBlobByte(Image *image)
   3032 {
   3033   register const unsigned char
   3034     *p;
   3035 
   3036   ssize_t
   3037     count;
   3038 
   3039   unsigned char
   3040     buffer[1];
   3041 
   3042   assert(image != (Image *) NULL);
   3043   assert(image->signature == MagickCoreSignature);
   3044   p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
   3045   if (count != 1)
   3046     return(EOF);
   3047   return((int) (*p));
   3048 }
   3049 
   3050 /*
   3052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3053 %                                                                             %
   3054 %                                                                             %
   3055 %                                                                             %
   3056 +  R e a d B l o b D o u b l e                                                %
   3057 %                                                                             %
   3058 %                                                                             %
   3059 %                                                                             %
   3060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3061 %
   3062 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
   3063 %  specified by the endian member of the image structure.
   3064 %
   3065 %  The format of the ReadBlobDouble method is:
   3066 %
   3067 %      double ReadBlobDouble(Image *image)
   3068 %
   3069 %  A description of each parameter follows.
   3070 %
   3071 %    o image: the image.
   3072 %
   3073 */
   3074 MagickExport double ReadBlobDouble(Image *image)
   3075 {
   3076   union
   3077   {
   3078     MagickSizeType
   3079       unsigned_value;
   3080 
   3081     double
   3082       double_value;
   3083   } quantum;
   3084 
   3085   quantum.double_value=0.0;
   3086   quantum.unsigned_value=ReadBlobLongLong(image);
   3087   return(quantum.double_value);
   3088 }
   3089 
   3090 /*
   3092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3093 %                                                                             %
   3094 %                                                                             %
   3095 %                                                                             %
   3096 +  R e a d B l o b F l o a t                                                  %
   3097 %                                                                             %
   3098 %                                                                             %
   3099 %                                                                             %
   3100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3101 %
   3102 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
   3103 %  specified by the endian member of the image structure.
   3104 %
   3105 %  The format of the ReadBlobFloat method is:
   3106 %
   3107 %      float ReadBlobFloat(Image *image)
   3108 %
   3109 %  A description of each parameter follows.
   3110 %
   3111 %    o image: the image.
   3112 %
   3113 */
   3114 MagickExport float ReadBlobFloat(Image *image)
   3115 {
   3116   union
   3117   {
   3118     unsigned int
   3119       unsigned_value;
   3120 
   3121     float
   3122       float_value;
   3123   } quantum;
   3124 
   3125   quantum.float_value=0.0;
   3126   quantum.unsigned_value=ReadBlobLong(image);
   3127   return(quantum.float_value);
   3128 }
   3129 
   3130 /*
   3132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3133 %                                                                             %
   3134 %                                                                             %
   3135 %                                                                             %
   3136 +  R e a d B l o b L o n g                                                    %
   3137 %                                                                             %
   3138 %                                                                             %
   3139 %                                                                             %
   3140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3141 %
   3142 %  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
   3143 %  byte-order specified by the endian member of the image structure.
   3144 %
   3145 %  The format of the ReadBlobLong method is:
   3146 %
   3147 %      unsigned int ReadBlobLong(Image *image)
   3148 %
   3149 %  A description of each parameter follows.
   3150 %
   3151 %    o image: the image.
   3152 %
   3153 */
   3154 MagickExport unsigned int ReadBlobLong(Image *image)
   3155 {
   3156   register const unsigned char
   3157     *p;
   3158 
   3159   ssize_t
   3160     count;
   3161 
   3162   unsigned char
   3163     buffer[4];
   3164 
   3165   unsigned int
   3166     value;
   3167 
   3168   assert(image != (Image *) NULL);
   3169   assert(image->signature == MagickCoreSignature);
   3170   *buffer='\0';
   3171   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
   3172   if (count != 4)
   3173     return(0UL);
   3174   if (image->endian == LSBEndian)
   3175     {
   3176       value=(unsigned int) (*p++);
   3177       value|=(unsigned int) (*p++) << 8;
   3178       value|=(unsigned int) (*p++) << 16;
   3179       value|=(unsigned int) (*p++) << 24;
   3180       return(value & 0xffffffff);
   3181     }
   3182   value=(unsigned int) (*p++) << 24;
   3183   value|=(unsigned int) (*p++) << 16;
   3184   value|=(unsigned int) (*p++) << 8;
   3185   value|=(unsigned int) (*p++);
   3186   return(value & 0xffffffff);
   3187 }
   3188 
   3189 /*
   3191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3192 %                                                                             %
   3193 %                                                                             %
   3194 %                                                                             %
   3195 +  R e a d B l o b L o n g L o n g                                            %
   3196 %                                                                             %
   3197 %                                                                             %
   3198 %                                                                             %
   3199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3200 %
   3201 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
   3202 %  byte-order specified by the endian member of the image structure.
   3203 %
   3204 %  The format of the ReadBlobLongLong method is:
   3205 %
   3206 %      MagickSizeType ReadBlobLongLong(Image *image)
   3207 %
   3208 %  A description of each parameter follows.
   3209 %
   3210 %    o image: the image.
   3211 %
   3212 */
   3213 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
   3214 {
   3215   MagickSizeType
   3216     value;
   3217 
   3218   register const unsigned char
   3219     *p;
   3220 
   3221   ssize_t
   3222     count;
   3223 
   3224   unsigned char
   3225     buffer[8];
   3226 
   3227   assert(image != (Image *) NULL);
   3228   assert(image->signature == MagickCoreSignature);
   3229   *buffer='\0';
   3230   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
   3231   if (count != 8)
   3232     return(MagickULLConstant(0));
   3233   if (image->endian == LSBEndian)
   3234     {
   3235       value=(MagickSizeType) (*p++);
   3236       value|=(MagickSizeType) (*p++) << 8;
   3237       value|=(MagickSizeType) (*p++) << 16;
   3238       value|=(MagickSizeType) (*p++) << 24;
   3239       value|=(MagickSizeType) (*p++) << 32;
   3240       value|=(MagickSizeType) (*p++) << 40;
   3241       value|=(MagickSizeType) (*p++) << 48;
   3242       value|=(MagickSizeType) (*p++) << 56;
   3243       return(value & MagickULLConstant(0xffffffffffffffff));
   3244     }
   3245   value=(MagickSizeType) (*p++) << 56;
   3246   value|=(MagickSizeType) (*p++) << 48;
   3247   value|=(MagickSizeType) (*p++) << 40;
   3248   value|=(MagickSizeType) (*p++) << 32;
   3249   value|=(MagickSizeType) (*p++) << 24;
   3250   value|=(MagickSizeType) (*p++) << 16;
   3251   value|=(MagickSizeType) (*p++) << 8;
   3252   value|=(MagickSizeType) (*p++);
   3253   return(value & MagickULLConstant(0xffffffffffffffff));
   3254 }
   3255 
   3256 /*
   3258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3259 %                                                                             %
   3260 %                                                                             %
   3261 %                                                                             %
   3262 +  R e a d B l o b S h o r t                                                  %
   3263 %                                                                             %
   3264 %                                                                             %
   3265 %                                                                             %
   3266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3267 %
   3268 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
   3269 %  specified by the endian member of the image structure.
   3270 %
   3271 %  The format of the ReadBlobShort method is:
   3272 %
   3273 %      unsigned short ReadBlobShort(Image *image)
   3274 %
   3275 %  A description of each parameter follows.
   3276 %
   3277 %    o image: the image.
   3278 %
   3279 */
   3280 MagickExport unsigned short ReadBlobShort(Image *image)
   3281 {
   3282   register const unsigned char
   3283     *p;
   3284 
   3285   register unsigned short
   3286     value;
   3287 
   3288   ssize_t
   3289     count;
   3290 
   3291   unsigned char
   3292     buffer[2];
   3293 
   3294   assert(image != (Image *) NULL);
   3295   assert(image->signature == MagickCoreSignature);
   3296   *buffer='\0';
   3297   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
   3298   if (count != 2)
   3299     return((unsigned short) 0U);
   3300   if (image->endian == LSBEndian)
   3301     {
   3302       value=(unsigned short) (*p++);
   3303       value|=(unsigned short) (*p++) << 8;
   3304       return(value);
   3305     }
   3306   value=(unsigned short) (*p++) << 8;
   3307   value|=(unsigned short) (*p++);
   3308   return(value);
   3309 }
   3310 
   3311 /*
   3313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3314 %                                                                             %
   3315 %                                                                             %
   3316 %                                                                             %
   3317 +  R e a d B l o b L S B L o n g                                              %
   3318 %                                                                             %
   3319 %                                                                             %
   3320 %                                                                             %
   3321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3322 %
   3323 %  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
   3324 %  least-significant byte first order.
   3325 %
   3326 %  The format of the ReadBlobLSBLong method is:
   3327 %
   3328 %      unsigned int ReadBlobLSBLong(Image *image)
   3329 %
   3330 %  A description of each parameter follows.
   3331 %
   3332 %    o image: the image.
   3333 %
   3334 */
   3335 MagickExport unsigned int ReadBlobLSBLong(Image *image)
   3336 {
   3337   register const unsigned char
   3338     *p;
   3339 
   3340   register unsigned int
   3341     value;
   3342 
   3343   ssize_t
   3344     count;
   3345 
   3346   unsigned char
   3347     buffer[4];
   3348 
   3349   assert(image != (Image *) NULL);
   3350   assert(image->signature == MagickCoreSignature);
   3351   *buffer='\0';
   3352   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
   3353   if (count != 4)
   3354     return(0U);
   3355   value=(unsigned int) (*p++);
   3356   value|=(unsigned int) (*p++) << 8;
   3357   value|=(unsigned int) (*p++) << 16;
   3358   value|=(unsigned int) (*p++) << 24;
   3359   return(value & 0xffffffff);
   3360 }
   3361 
   3362 /*
   3364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3365 %                                                                             %
   3366 %                                                                             %
   3367 %                                                                             %
   3368 +  R e a d B l o b L S B S i g n e d L o n g                                  %
   3369 %                                                                             %
   3370 %                                                                             %
   3371 %                                                                             %
   3372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3373 %
   3374 %  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
   3375 %  least-significant byte first order.
   3376 %
   3377 %  The format of the ReadBlobLSBSignedLong method is:
   3378 %
   3379 %      signed int ReadBlobLSBSignedLong(Image *image)
   3380 %
   3381 %  A description of each parameter follows.
   3382 %
   3383 %    o image: the image.
   3384 %
   3385 */
   3386 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
   3387 {
   3388   union
   3389   {
   3390     unsigned int
   3391       unsigned_value;
   3392 
   3393     signed int
   3394       signed_value;
   3395   } quantum;
   3396 
   3397   quantum.unsigned_value=ReadBlobLSBLong(image);
   3398   return(quantum.signed_value);
   3399 }
   3400 
   3401 /*
   3403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3404 %                                                                             %
   3405 %                                                                             %
   3406 %                                                                             %
   3407 +  R e a d B l o b L S B S h o r t                                            %
   3408 %                                                                             %
   3409 %                                                                             %
   3410 %                                                                             %
   3411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3412 %
   3413 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
   3414 %  least-significant byte first order.
   3415 %
   3416 %  The format of the ReadBlobLSBShort method is:
   3417 %
   3418 %      unsigned short ReadBlobLSBShort(Image *image)
   3419 %
   3420 %  A description of each parameter follows.
   3421 %
   3422 %    o image: the image.
   3423 %
   3424 */
   3425 MagickExport unsigned short ReadBlobLSBShort(Image *image)
   3426 {
   3427   register const unsigned char
   3428     *p;
   3429 
   3430   register unsigned short
   3431     value;
   3432 
   3433   ssize_t
   3434     count;
   3435 
   3436   unsigned char
   3437     buffer[2];
   3438 
   3439   assert(image != (Image *) NULL);
   3440   assert(image->signature == MagickCoreSignature);
   3441   *buffer='\0';
   3442   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
   3443   if (count != 2)
   3444     return((unsigned short) 0U);
   3445   value=(unsigned int) (*p++);
   3446   value|=(unsigned int) (*p++) << 8;
   3447   return(value & 0xffff);
   3448 }
   3449 
   3450 /*
   3452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3453 %                                                                             %
   3454 %                                                                             %
   3455 %                                                                             %
   3456 +  R e a d B l o b L S B S i g n e d S h o r t                                %
   3457 %                                                                             %
   3458 %                                                                             %
   3459 %                                                                             %
   3460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3461 %
   3462 %  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
   3463 %  least-significant byte-order.
   3464 %
   3465 %  The format of the ReadBlobLSBSignedShort method is:
   3466 %
   3467 %      signed short ReadBlobLSBSignedShort(Image *image)
   3468 %
   3469 %  A description of each parameter follows.
   3470 %
   3471 %    o image: the image.
   3472 %
   3473 */
   3474 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
   3475 {
   3476   union
   3477   {
   3478     unsigned short
   3479       unsigned_value;
   3480 
   3481     signed short
   3482       signed_value;
   3483   } quantum;
   3484 
   3485   quantum.unsigned_value=ReadBlobLSBShort(image);
   3486   return(quantum.signed_value);
   3487 }
   3488 
   3489 /*
   3491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3492 %                                                                             %
   3493 %                                                                             %
   3494 %                                                                             %
   3495 +  R e a d B l o b M S B L o n g                                              %
   3496 %                                                                             %
   3497 %                                                                             %
   3498 %                                                                             %
   3499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3500 %
   3501 %  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
   3502 %  most-significant byte first order.
   3503 %
   3504 %  The format of the ReadBlobMSBLong method is:
   3505 %
   3506 %      unsigned int ReadBlobMSBLong(Image *image)
   3507 %
   3508 %  A description of each parameter follows.
   3509 %
   3510 %    o image: the image.
   3511 %
   3512 */
   3513 MagickExport unsigned int ReadBlobMSBLong(Image *image)
   3514 {
   3515   register const unsigned char
   3516     *p;
   3517 
   3518   register unsigned int
   3519     value;
   3520 
   3521   ssize_t
   3522     count;
   3523 
   3524   unsigned char
   3525     buffer[4];
   3526 
   3527   assert(image != (Image *) NULL);
   3528   assert(image->signature == MagickCoreSignature);
   3529   *buffer='\0';
   3530   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
   3531   if (count != 4)
   3532     return(0UL);
   3533   value=(unsigned int) (*p++) << 24;
   3534   value|=(unsigned int) (*p++) << 16;
   3535   value|=(unsigned int) (*p++) << 8;
   3536   value|=(unsigned int) (*p++);
   3537   return(value);
   3538 }
   3539 
   3540 /*
   3542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3543 %                                                                             %
   3544 %                                                                             %
   3545 %                                                                             %
   3546 +  R e a d B l o b M S B L o n g L o n g                                      %
   3547 %                                                                             %
   3548 %                                                                             %
   3549 %                                                                             %
   3550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3551 %
   3552 %  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
   3553 %  in most-significant byte first order.
   3554 %
   3555 %  The format of the ReadBlobMSBLongLong method is:
   3556 %
   3557 %      unsigned int ReadBlobMSBLongLong(Image *image)
   3558 %
   3559 %  A description of each parameter follows.
   3560 %
   3561 %    o image: the image.
   3562 %
   3563 */
   3564 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
   3565 {
   3566   register const unsigned char
   3567     *p;
   3568 
   3569   register MagickSizeType
   3570     value;
   3571 
   3572   ssize_t
   3573     count;
   3574 
   3575   unsigned char
   3576     buffer[8];
   3577 
   3578   assert(image != (Image *) NULL);
   3579   assert(image->signature == MagickCoreSignature);
   3580   *buffer='\0';
   3581   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
   3582   if (count != 8)
   3583     return(MagickULLConstant(0));
   3584   value=(MagickSizeType) (*p++) << 56;
   3585   value|=(MagickSizeType) (*p++) << 48;
   3586   value|=(MagickSizeType) (*p++) << 40;
   3587   value|=(MagickSizeType) (*p++) << 32;
   3588   value|=(MagickSizeType) (*p++) << 24;
   3589   value|=(MagickSizeType) (*p++) << 16;
   3590   value|=(MagickSizeType) (*p++) << 8;
   3591   value|=(MagickSizeType) (*p++);
   3592   return(value & MagickULLConstant(0xffffffffffffffff));
   3593 }
   3594 
   3595 /*
   3597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3598 %                                                                             %
   3599 %                                                                             %
   3600 %                                                                             %
   3601 +  R e a d B l o b M S B S h o r t                                            %
   3602 %                                                                             %
   3603 %                                                                             %
   3604 %                                                                             %
   3605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3606 %
   3607 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
   3608 %  most-significant byte first order.
   3609 %
   3610 %  The format of the ReadBlobMSBShort method is:
   3611 %
   3612 %      unsigned short ReadBlobMSBShort(Image *image)
   3613 %
   3614 %  A description of each parameter follows.
   3615 %
   3616 %    o image: the image.
   3617 %
   3618 */
   3619 MagickExport unsigned short ReadBlobMSBShort(Image *image)
   3620 {
   3621   register const unsigned char
   3622     *p;
   3623 
   3624   register unsigned short
   3625     value;
   3626 
   3627   ssize_t
   3628     count;
   3629 
   3630   unsigned char
   3631     buffer[2];
   3632 
   3633   assert(image != (Image *) NULL);
   3634   assert(image->signature == MagickCoreSignature);
   3635   *buffer='\0';
   3636   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
   3637   if (count != 2)
   3638     return((unsigned short) 0U);
   3639   value=(unsigned short) (*p++) << 8;
   3640   value|=(unsigned short) (*p++);
   3641   return(value & 0xffff);
   3642 }
   3643 
   3644 /*
   3646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3647 %                                                                             %
   3648 %                                                                             %
   3649 %                                                                             %
   3650 +  R e a d B l o b M S B S i g n e d L o n g                                  %
   3651 %                                                                             %
   3652 %                                                                             %
   3653 %                                                                             %
   3654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3655 %
   3656 %  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
   3657 %  most-significant byte-order.
   3658 %
   3659 %  The format of the ReadBlobMSBSignedLong method is:
   3660 %
   3661 %      signed int ReadBlobMSBSignedLong(Image *image)
   3662 %
   3663 %  A description of each parameter follows.
   3664 %
   3665 %    o image: the image.
   3666 %
   3667 */
   3668 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
   3669 {
   3670   union
   3671   {
   3672     unsigned int
   3673       unsigned_value;
   3674 
   3675     signed int
   3676       signed_value;
   3677   } quantum;
   3678 
   3679   quantum.unsigned_value=ReadBlobMSBLong(image);
   3680   return(quantum.signed_value);
   3681 }
   3682 
   3683 /*
   3685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3686 %                                                                             %
   3687 %                                                                             %
   3688 %                                                                             %
   3689 +  R e a d B l o b M S B S i g n e d S h o r t                                %
   3690 %                                                                             %
   3691 %                                                                             %
   3692 %                                                                             %
   3693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3694 %
   3695 %  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
   3696 %  most-significant byte-order.
   3697 %
   3698 %  The format of the ReadBlobMSBSignedShort method is:
   3699 %
   3700 %      signed short ReadBlobMSBSignedShort(Image *image)
   3701 %
   3702 %  A description of each parameter follows.
   3703 %
   3704 %    o image: the image.
   3705 %
   3706 */
   3707 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
   3708 {
   3709   union
   3710   {
   3711     unsigned short
   3712       unsigned_value;
   3713 
   3714     signed short
   3715       signed_value;
   3716   } quantum;
   3717 
   3718   quantum.unsigned_value=ReadBlobMSBShort(image);
   3719   return(quantum.signed_value);
   3720 }
   3721 
   3722 /*
   3724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3725 %                                                                             %
   3726 %                                                                             %
   3727 %                                                                             %
   3728 +  R e a d B l o b S i g n e d L o n g                                        %
   3729 %                                                                             %
   3730 %                                                                             %
   3731 %                                                                             %
   3732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3733 %
   3734 %  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
   3735 %  byte-order specified by the endian member of the image structure.
   3736 %
   3737 %  The format of the ReadBlobSignedLong method is:
   3738 %
   3739 %      signed int ReadBlobSignedLong(Image *image)
   3740 %
   3741 %  A description of each parameter follows.
   3742 %
   3743 %    o image: the image.
   3744 %
   3745 */
   3746 MagickExport signed int ReadBlobSignedLong(Image *image)
   3747 {
   3748   union
   3749   {
   3750     unsigned int
   3751       unsigned_value;
   3752 
   3753     signed int
   3754       signed_value;
   3755   } quantum;
   3756 
   3757   quantum.unsigned_value=ReadBlobLong(image);
   3758   return(quantum.signed_value);
   3759 }
   3760 
   3761 /*
   3763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3764 %                                                                             %
   3765 %                                                                             %
   3766 %                                                                             %
   3767 +  R e a d B l o b S i g n e d S h o r t                                      %
   3768 %                                                                             %
   3769 %                                                                             %
   3770 %                                                                             %
   3771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3772 %
   3773 %  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
   3774 %  byte-order specified by the endian member of the image structure.
   3775 %
   3776 %  The format of the ReadBlobSignedShort method is:
   3777 %
   3778 %      signed short ReadBlobSignedShort(Image *image)
   3779 %
   3780 %  A description of each parameter follows.
   3781 %
   3782 %    o image: the image.
   3783 %
   3784 */
   3785 MagickExport signed short ReadBlobSignedShort(Image *image)
   3786 {
   3787   union
   3788   {
   3789     unsigned short
   3790       unsigned_value;
   3791 
   3792     signed short
   3793       signed_value;
   3794   } quantum;
   3795 
   3796   quantum.unsigned_value=ReadBlobShort(image);
   3797   return(quantum.signed_value);
   3798 }
   3799 
   3800 /*
   3802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3803 %                                                                             %
   3804 %                                                                             %
   3805 %                                                                             %
   3806 +  R e a d B l o b S t r e a m                                                %
   3807 %                                                                             %
   3808 %                                                                             %
   3809 %                                                                             %
   3810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3811 %
   3812 %  ReadBlobStream() reads data from the blob or image file and returns it.  It
   3813 %  returns a pointer to the data buffer you supply or to the image memory
   3814 %  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
   3815 %  returns a count of zero and has no other results. If length is greater than
   3816 %  SSIZE_MAX, the result is unspecified.
   3817 %
   3818 %  The format of the ReadBlobStream method is:
   3819 %
   3820 %      const void *ReadBlobStream(Image *image,const size_t length,void *data,
   3821 %        ssize_t *count)
   3822 %
   3823 %  A description of each parameter follows:
   3824 %
   3825 %    o image: the image.
   3826 %
   3827 %    o length:  Specifies an integer representing the number of bytes to read
   3828 %      from the file.
   3829 %
   3830 %    o count: returns the number of bytes read.
   3831 %
   3832 %    o data:  Specifies an area to place the information requested from the
   3833 %      file.
   3834 %
   3835 */
   3836 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
   3837   void *data,ssize_t *count)
   3838 {
   3839   assert(image != (Image *) NULL);
   3840   assert(image->signature == MagickCoreSignature);
   3841   assert(image->blob != (BlobInfo *) NULL);
   3842   assert(image->blob->type != UndefinedStream);
   3843   assert(count != (ssize_t *) NULL);
   3844   if (image->blob->type != BlobStream)
   3845     {
   3846       assert(data != NULL);
   3847       *count=ReadBlob(image,length,(unsigned char *) data);
   3848       return(data);
   3849     }
   3850   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
   3851     {
   3852       *count=0;
   3853       image->blob->eof=MagickTrue;
   3854       return(data);
   3855     }
   3856   data=image->blob->data+image->blob->offset;
   3857   *count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
   3858   image->blob->offset+=(*count);
   3859   if (*count != (ssize_t) length)
   3860     image->blob->eof=MagickTrue;
   3861   return(data);
   3862 }
   3863 
   3864 /*
   3866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3867 %                                                                             %
   3868 %                                                                             %
   3869 %                                                                             %
   3870 +   R e a d B l o b S t r i n g                                               %
   3871 %                                                                             %
   3872 %                                                                             %
   3873 %                                                                             %
   3874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3875 %
   3876 %  ReadBlobString() reads characters from a blob or file until a newline
   3877 %  character is read or an end-of-file condition is encountered.
   3878 %
   3879 %  The format of the ReadBlobString method is:
   3880 %
   3881 %      char *ReadBlobString(Image *image,char *string)
   3882 %
   3883 %  A description of each parameter follows:
   3884 %
   3885 %    o image: the image.
   3886 %
   3887 %    o string: the address of a character buffer.
   3888 %
   3889 */
   3890 MagickExport char *ReadBlobString(Image *image,char *string)
   3891 {
   3892   register const unsigned char
   3893     *p;
   3894 
   3895   register ssize_t
   3896     i;
   3897 
   3898   ssize_t
   3899     count;
   3900 
   3901   unsigned char
   3902     buffer[1];
   3903 
   3904   assert(image != (Image *) NULL);
   3905   assert(image->signature == MagickCoreSignature);
   3906   for (i=0; i < (MagickPathExtent-1L); i++)
   3907   {
   3908     p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
   3909     if (count != 1)
   3910       {
   3911         if (i == 0)
   3912           return((char *) NULL);
   3913         break;
   3914       }
   3915     string[i]=(char) (*p);
   3916     if ((string[i] == '\r') || (string[i] == '\n'))
   3917       break;
   3918   }
   3919   if (string[i] == '\r')
   3920     (void) ReadBlobStream(image,1,buffer,&count);
   3921   string[i]='\0';
   3922   return(string);
   3923 }
   3924 
   3925 /*
   3927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3928 %                                                                             %
   3929 %                                                                             %
   3930 %                                                                             %
   3931 +   R e f e r e n c e B l o b                                                 %
   3932 %                                                                             %
   3933 %                                                                             %
   3934 %                                                                             %
   3935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3936 %
   3937 %  ReferenceBlob() increments the reference count associated with the pixel
   3938 %  blob returning a pointer to the blob.
   3939 %
   3940 %  The format of the ReferenceBlob method is:
   3941 %
   3942 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
   3943 %
   3944 %  A description of each parameter follows:
   3945 %
   3946 %    o blob_info: the blob_info.
   3947 %
   3948 */
   3949 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
   3950 {
   3951   assert(blob != (BlobInfo *) NULL);
   3952   assert(blob->signature == MagickCoreSignature);
   3953   if (blob->debug != MagickFalse)
   3954     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   3955   LockSemaphoreInfo(blob->semaphore);
   3956   blob->reference_count++;
   3957   UnlockSemaphoreInfo(blob->semaphore);
   3958   return(blob);
   3959 }
   3960 
   3961 /*
   3963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3964 %                                                                             %
   3965 %                                                                             %
   3966 %                                                                             %
   3967 +  S e e k B l o b                                                            %
   3968 %                                                                             %
   3969 %                                                                             %
   3970 %                                                                             %
   3971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   3972 %
   3973 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
   3974 %  and returns the resulting offset.
   3975 %
   3976 %  The format of the SeekBlob method is:
   3977 %
   3978 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
   3979 %        const int whence)
   3980 %
   3981 %  A description of each parameter follows:
   3982 %
   3983 %    o image: the image.
   3984 %
   3985 %    o offset:  Specifies an integer representing the offset in bytes.
   3986 %
   3987 %    o whence:  Specifies an integer representing how the offset is
   3988 %      treated relative to the beginning of the blob as follows:
   3989 %
   3990 %        SEEK_SET  Set position equal to offset bytes.
   3991 %        SEEK_CUR  Set position to current location plus offset.
   3992 %        SEEK_END  Set position to EOF plus offset.
   3993 %
   3994 */
   3995 MagickExport MagickOffsetType SeekBlob(Image *image,
   3996   const MagickOffsetType offset,const int whence)
   3997 {
   3998   assert(image != (Image *) NULL);
   3999   assert(image->signature == MagickCoreSignature);
   4000   if (image->debug != MagickFalse)
   4001     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   4002   assert(image->blob != (BlobInfo *) NULL);
   4003   assert(image->blob->type != UndefinedStream);
   4004   switch (image->blob->type)
   4005   {
   4006     case UndefinedStream:
   4007       break;
   4008     case StandardStream:
   4009       return(-1);
   4010     case FileStream:
   4011     {
   4012       if ((offset < 0) && (whence == SEEK_SET))
   4013         return(-1);
   4014       if (fseek(image->blob->file_info.file,offset,whence) < 0)
   4015         return(-1);
   4016       image->blob->offset=TellBlob(image);
   4017       break;
   4018     }
   4019     case PipeStream:
   4020     case ZipStream:
   4021     {
   4022 #if defined(MAGICKCORE_ZLIB_DELEGATE)
   4023       if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
   4024         return(-1);
   4025 #endif
   4026       image->blob->offset=TellBlob(image);
   4027       break;
   4028     }
   4029     case BZipStream:
   4030       return(-1);
   4031     case FifoStream:
   4032       return(-1);
   4033     case BlobStream:
   4034     {
   4035       switch (whence)
   4036       {
   4037         case SEEK_SET:
   4038         default:
   4039         {
   4040           if (offset < 0)
   4041             return(-1);
   4042           image->blob->offset=offset;
   4043           break;
   4044         }
   4045         case SEEK_CUR:
   4046         {
   4047           if ((image->blob->offset+offset) < 0)
   4048             return(-1);
   4049           image->blob->offset+=offset;
   4050           break;
   4051         }
   4052         case SEEK_END:
   4053         {
   4054           if (((MagickOffsetType) image->blob->length+offset) < 0)
   4055             return(-1);
   4056           image->blob->offset=image->blob->length+offset;
   4057           break;
   4058         }
   4059       }
   4060       if (image->blob->offset < (MagickOffsetType)
   4061           ((off_t) image->blob->length))
   4062         {
   4063           image->blob->eof=MagickFalse;
   4064           break;
   4065         }
   4066       if (image->blob->offset < (MagickOffsetType)
   4067           ((off_t) image->blob->extent))
   4068         break;
   4069       if (image->blob->immutable != MagickFalse)
   4070         {
   4071           image->blob->eof=MagickTrue;
   4072           return(-1);
   4073         }
   4074       image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
   4075       image->blob->quantum<<=1;
   4076       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
   4077         image->blob->extent+1,sizeof(*image->blob->data));
   4078       (void) SyncBlob(image);
   4079       if (image->blob->data == NULL)
   4080         {
   4081           (void) DetachBlob(image->blob);
   4082           return(-1);
   4083         }
   4084       break;
   4085     }
   4086   }
   4087   return(image->blob->offset);
   4088 }
   4089 
   4090 /*
   4092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4093 %                                                                             %
   4094 %                                                                             %
   4095 %                                                                             %
   4096 +   S e t B l o b E x e m p t                                                 %
   4097 %                                                                             %
   4098 %                                                                             %
   4099 %                                                                             %
   4100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4101 %
   4102 %  SetBlobExempt() sets the blob exempt status.
   4103 %
   4104 %  The format of the SetBlobExempt method is:
   4105 %
   4106 %      MagickBooleanType SetBlobExempt(const Image *image,
   4107 %        const MagickBooleanType exempt)
   4108 %
   4109 %  A description of each parameter follows:
   4110 %
   4111 %    o image: the image.
   4112 %
   4113 %    o exempt: Set to true if this blob is exempt from being closed.
   4114 %
   4115 */
   4116 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
   4117 {
   4118   assert(image != (const Image *) NULL);
   4119   assert(image->signature == MagickCoreSignature);
   4120   if (image->debug != MagickFalse)
   4121     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   4122   image->blob->exempt=exempt;
   4123 }
   4124 
   4125 /*
   4127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4128 %                                                                             %
   4129 %                                                                             %
   4130 %                                                                             %
   4131 +  S e t B l o b E x t e n t                                                  %
   4132 %                                                                             %
   4133 %                                                                             %
   4134 %                                                                             %
   4135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4136 %
   4137 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
   4138 %  method is successful, subsequent writes to bytes in the specified range are
   4139 %  guaranteed not to fail.
   4140 %
   4141 %  The format of the SetBlobExtent method is:
   4142 %
   4143 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
   4144 %
   4145 %  A description of each parameter follows:
   4146 %
   4147 %    o image: the image.
   4148 %
   4149 %    o extent:  the blob maximum extent.
   4150 %
   4151 */
   4152 MagickExport MagickBooleanType SetBlobExtent(Image *image,
   4153   const MagickSizeType extent)
   4154 {
   4155   assert(image != (Image *) NULL);
   4156   assert(image->signature == MagickCoreSignature);
   4157   if (image->debug != MagickFalse)
   4158     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   4159   assert(image->blob != (BlobInfo *) NULL);
   4160   assert(image->blob->type != UndefinedStream);
   4161   switch (image->blob->type)
   4162   {
   4163     case UndefinedStream:
   4164       break;
   4165     case StandardStream:
   4166       return(MagickFalse);
   4167     case FileStream:
   4168     {
   4169       MagickOffsetType
   4170         offset;
   4171 
   4172       ssize_t
   4173         count;
   4174 
   4175       if (extent != (MagickSizeType) ((off_t) extent))
   4176         return(MagickFalse);
   4177       offset=SeekBlob(image,0,SEEK_END);
   4178       if (offset < 0)
   4179         return(MagickFalse);
   4180       if ((MagickSizeType) offset >= extent)
   4181         break;
   4182       offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
   4183       if (offset < 0)
   4184         break;
   4185       count=(ssize_t) fwrite((const unsigned char *) "",1,1,
   4186         image->blob->file_info.file);
   4187 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
   4188       if (image->blob->synchronize != MagickFalse)
   4189         {
   4190           int
   4191             file;
   4192 
   4193           file=fileno(image->blob->file_info.file);
   4194           if ((file == -1) || (offset < 0))
   4195             return(MagickFalse);
   4196           (void) posix_fallocate(file,offset,extent-offset);
   4197         }
   4198 #endif
   4199       offset=SeekBlob(image,offset,SEEK_SET);
   4200       if (count != 1)
   4201         return(MagickFalse);
   4202       break;
   4203     }
   4204     case PipeStream:
   4205     case ZipStream:
   4206       return(MagickFalse);
   4207     case BZipStream:
   4208       return(MagickFalse);
   4209     case FifoStream:
   4210       return(MagickFalse);
   4211     case BlobStream:
   4212     {
   4213       if (extent != (MagickSizeType) ((size_t) extent))
   4214         return(MagickFalse);
   4215       if (image->blob->mapped != MagickFalse)
   4216         {
   4217           MagickOffsetType
   4218             offset;
   4219 
   4220           ssize_t
   4221             count;
   4222 
   4223           (void) UnmapBlob(image->blob->data,image->blob->length);
   4224           RelinquishMagickResource(MapResource,image->blob->length);
   4225           if (extent != (MagickSizeType) ((off_t) extent))
   4226             return(MagickFalse);
   4227           offset=SeekBlob(image,0,SEEK_END);
   4228           if (offset < 0)
   4229             return(MagickFalse);
   4230           if ((MagickSizeType) offset >= extent)
   4231             break;
   4232           offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
   4233           count=(ssize_t) fwrite((const unsigned char *) "",1,1,
   4234             image->blob->file_info.file);
   4235 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
   4236           if (image->blob->synchronize != MagickFalse)
   4237             {
   4238               int
   4239                 file;
   4240 
   4241               file=fileno(image->blob->file_info.file);
   4242               if ((file == -1) || (offset < 0))
   4243                 return(MagickFalse);
   4244               (void) posix_fallocate(file,offset,extent-offset);
   4245             }
   4246 #endif
   4247           offset=SeekBlob(image,offset,SEEK_SET);
   4248           if (count != 1)
   4249             return(MagickFalse);
   4250           (void) AcquireMagickResource(MapResource,extent);
   4251           image->blob->data=(unsigned char*) MapBlob(fileno(
   4252             image->blob->file_info.file),WriteMode,0,(size_t) extent);
   4253           image->blob->extent=(size_t) extent;
   4254           image->blob->length=(size_t) extent;
   4255           (void) SyncBlob(image);
   4256           break;
   4257         }
   4258       image->blob->extent=(size_t) extent;
   4259       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
   4260         image->blob->extent+1,sizeof(*image->blob->data));
   4261       (void) SyncBlob(image);
   4262       if (image->blob->data == (unsigned char *) NULL)
   4263         {
   4264           (void) DetachBlob(image->blob);
   4265           return(MagickFalse);
   4266         }
   4267       break;
   4268     }
   4269   }
   4270   return(MagickTrue);
   4271 }
   4272 
   4273 /*
   4275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4276 %                                                                             %
   4277 %                                                                             %
   4278 %                                                                             %
   4279 +  S y n c B l o b                                                            %
   4280 %                                                                             %
   4281 %                                                                             %
   4282 %                                                                             %
   4283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4284 %
   4285 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
   4286 %  attributes if it is an blob.
   4287 %
   4288 %  The format of the SyncBlob method is:
   4289 %
   4290 %      int SyncBlob(Image *image)
   4291 %
   4292 %  A description of each parameter follows:
   4293 %
   4294 %    o image: the image.
   4295 %
   4296 */
   4297 static int SyncBlob(Image *image)
   4298 {
   4299   int
   4300     status;
   4301 
   4302   assert(image != (Image *) NULL);
   4303   assert(image->signature == MagickCoreSignature);
   4304   if (image->debug != MagickFalse)
   4305     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   4306   assert(image->blob != (BlobInfo *) NULL);
   4307   assert(image->blob->type != UndefinedStream);
   4308   status=0;
   4309   switch (image->blob->type)
   4310   {
   4311     case UndefinedStream:
   4312     case StandardStream:
   4313       break;
   4314     case FileStream:
   4315     case PipeStream:
   4316     {
   4317       status=fflush(image->blob->file_info.file);
   4318       break;
   4319     }
   4320     case ZipStream:
   4321     {
   4322 #if defined(MAGICKCORE_ZLIB_DELEGATE)
   4323       status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
   4324 #endif
   4325       break;
   4326     }
   4327     case BZipStream:
   4328     {
   4329 #if defined(MAGICKCORE_BZLIB_DELEGATE)
   4330       status=BZ2_bzflush(image->blob->file_info.bzfile);
   4331 #endif
   4332       break;
   4333     }
   4334     case FifoStream:
   4335       break;
   4336     case BlobStream:
   4337       break;
   4338   }
   4339   return(status);
   4340 }
   4341 
   4342 /*
   4344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4345 %                                                                             %
   4346 %                                                                             %
   4347 %                                                                             %
   4348 +  T e l l B l o b                                                            %
   4349 %                                                                             %
   4350 %                                                                             %
   4351 %                                                                             %
   4352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4353 %
   4354 %  TellBlob() obtains the current value of the blob or file position.
   4355 %
   4356 %  The format of the TellBlob method is:
   4357 %
   4358 %      MagickOffsetType TellBlob(const Image *image)
   4359 %
   4360 %  A description of each parameter follows:
   4361 %
   4362 %    o image: the image.
   4363 %
   4364 */
   4365 MagickExport MagickOffsetType TellBlob(const Image *image)
   4366 {
   4367   MagickOffsetType
   4368     offset;
   4369 
   4370   assert(image != (Image *) NULL);
   4371   assert(image->signature == MagickCoreSignature);
   4372   if (image->debug != MagickFalse)
   4373     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   4374   assert(image->blob != (BlobInfo *) NULL);
   4375   assert(image->blob->type != UndefinedStream);
   4376   offset=(-1);
   4377   switch (image->blob->type)
   4378   {
   4379     case UndefinedStream:
   4380     case StandardStream:
   4381       break;
   4382     case FileStream:
   4383     {
   4384       offset=ftell(image->blob->file_info.file);
   4385       break;
   4386     }
   4387     case PipeStream:
   4388       break;
   4389     case ZipStream:
   4390     {
   4391 #if defined(MAGICKCORE_ZLIB_DELEGATE)
   4392       offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
   4393 #endif
   4394       break;
   4395     }
   4396     case BZipStream:
   4397       break;
   4398     case FifoStream:
   4399       break;
   4400     case BlobStream:
   4401     {
   4402       offset=image->blob->offset;
   4403       break;
   4404     }
   4405   }
   4406   return(offset);
   4407 }
   4408 
   4409 /*
   4411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4412 %                                                                             %
   4413 %                                                                             %
   4414 %                                                                             %
   4415 +  U n m a p B l o b                                                          %
   4416 %                                                                             %
   4417 %                                                                             %
   4418 %                                                                             %
   4419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4420 %
   4421 %  UnmapBlob() deallocates the binary large object previously allocated with
   4422 %  the MapBlob method.
   4423 %
   4424 %  The format of the UnmapBlob method is:
   4425 %
   4426 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
   4427 %
   4428 %  A description of each parameter follows:
   4429 %
   4430 %    o map: the address  of the binary large object.
   4431 %
   4432 %    o length: the length of the binary large object.
   4433 %
   4434 */
   4435 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
   4436 {
   4437 #if defined(MAGICKCORE_HAVE_MMAP)
   4438   int
   4439     status;
   4440 
   4441   status=munmap(map,length);
   4442   return(status == -1 ? MagickFalse : MagickTrue);
   4443 #else
   4444   (void) map;
   4445   (void) length;
   4446   return(MagickFalse);
   4447 #endif
   4448 }
   4449 
   4450 /*
   4452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4453 %                                                                             %
   4454 %                                                                             %
   4455 %                                                                             %
   4456 +  W r i t e B l o b                                                          %
   4457 %                                                                             %
   4458 %                                                                             %
   4459 %                                                                             %
   4460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4461 %
   4462 %  WriteBlob() writes data to a blob or image file.  It returns the number of
   4463 %  bytes written.
   4464 %
   4465 %  The format of the WriteBlob method is:
   4466 %
   4467 %      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
   4468 %
   4469 %  A description of each parameter follows:
   4470 %
   4471 %    o image: the image.
   4472 %
   4473 %    o length:  Specifies an integer representing the number of bytes to
   4474 %      write to the file.
   4475 %
   4476 %    o data:  The address of the data to write to the blob or file.
   4477 %
   4478 */
   4479 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
   4480   const void *data)
   4481 {
   4482   int
   4483     c;
   4484 
   4485   register const unsigned char
   4486     *p;
   4487 
   4488   ssize_t
   4489     count;
   4490 
   4491   assert(image != (Image *) NULL);
   4492   assert(image->signature == MagickCoreSignature);
   4493   assert(data != (const void *) NULL);
   4494   assert(image->blob != (BlobInfo *) NULL);
   4495   assert(image->blob->type != UndefinedStream);
   4496   if (length == 0)
   4497     return(0);
   4498   count=0;
   4499   p=(const unsigned char *) data;
   4500   switch (image->blob->type)
   4501   {
   4502     case UndefinedStream:
   4503       break;
   4504     case StandardStream:
   4505     case FileStream:
   4506     case PipeStream:
   4507     {
   4508       switch (length)
   4509       {
   4510         default:
   4511         {
   4512           count=(ssize_t) fwrite((const char *) data,1,length,
   4513             image->blob->file_info.file);
   4514           break;
   4515         }
   4516         case 4:
   4517         {
   4518           c=putc((int) *p++,image->blob->file_info.file);
   4519           if (c == EOF)
   4520             break;
   4521           count++;
   4522         }
   4523         case 3:
   4524         {
   4525           c=putc((int) *p++,image->blob->file_info.file);
   4526           if (c == EOF)
   4527             break;
   4528           count++;
   4529         }
   4530         case 2:
   4531         {
   4532           c=putc((int) *p++,image->blob->file_info.file);
   4533           if (c == EOF)
   4534             break;
   4535           count++;
   4536         }
   4537         case 1:
   4538         {
   4539           c=putc((int) *p++,image->blob->file_info.file);
   4540           if (c == EOF)
   4541             break;
   4542           count++;
   4543         }
   4544         case 0:
   4545           break;
   4546       }
   4547       break;
   4548     }
   4549     case ZipStream:
   4550     {
   4551 #if defined(MAGICKCORE_ZLIB_DELEGATE)
   4552       switch (length)
   4553       {
   4554         default:
   4555         {
   4556           count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
   4557             (unsigned int) length);
   4558           break;
   4559         }
   4560         case 4:
   4561         {
   4562           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
   4563           if (c == EOF)
   4564             break;
   4565           count++;
   4566         }
   4567         case 3:
   4568         {
   4569           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
   4570           if (c == EOF)
   4571             break;
   4572           count++;
   4573         }
   4574         case 2:
   4575         {
   4576           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
   4577           if (c == EOF)
   4578             break;
   4579           count++;
   4580         }
   4581         case 1:
   4582         {
   4583           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
   4584           if (c == EOF)
   4585             break;
   4586           count++;
   4587         }
   4588         case 0:
   4589           break;
   4590       }
   4591 #endif
   4592       break;
   4593     }
   4594     case BZipStream:
   4595     {
   4596 #if defined(MAGICKCORE_BZLIB_DELEGATE)
   4597       count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
   4598         (int) length);
   4599 #endif
   4600       break;
   4601     }
   4602     case FifoStream:
   4603     {
   4604       count=(ssize_t) image->blob->stream(image,data,length);
   4605       break;
   4606     }
   4607     case BlobStream:
   4608     {
   4609       register unsigned char
   4610         *q;
   4611 
   4612       if ((image->blob->offset+(MagickOffsetType) length) >=
   4613           (MagickOffsetType) image->blob->extent)
   4614         {
   4615           if (image->blob->mapped != MagickFalse)
   4616             return(0);
   4617           image->blob->extent+=length+image->blob->quantum;
   4618           image->blob->quantum<<=1;
   4619           image->blob->data=(unsigned char *) ResizeQuantumMemory(
   4620             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
   4621           (void) SyncBlob(image);
   4622           if (image->blob->data == (unsigned char *) NULL)
   4623             {
   4624               (void) DetachBlob(image->blob);
   4625               return(0);
   4626             }
   4627         }
   4628       q=image->blob->data+image->blob->offset;
   4629       (void) memcpy(q,p,length);
   4630       image->blob->offset+=length;
   4631       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
   4632         image->blob->length=(size_t) image->blob->offset;
   4633       count=(ssize_t) length;
   4634     }
   4635   }
   4636   return(count);
   4637 }
   4638 
   4639 /*
   4641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4642 %                                                                             %
   4643 %                                                                             %
   4644 %                                                                             %
   4645 +  W r i t e B l o b B y t e                                                  %
   4646 %                                                                             %
   4647 %                                                                             %
   4648 %                                                                             %
   4649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4650 %
   4651 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
   4652 %  written (either 0 or 1);
   4653 %
   4654 %  The format of the WriteBlobByte method is:
   4655 %
   4656 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
   4657 %
   4658 %  A description of each parameter follows.
   4659 %
   4660 %    o image: the image.
   4661 %
   4662 %    o value: Specifies the value to write.
   4663 %
   4664 */
   4665 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
   4666 {
   4667   assert(image != (Image *) NULL);
   4668   assert(image->signature == MagickCoreSignature);
   4669   return(WriteBlobStream(image,1,&value));
   4670 }
   4671 
   4672 /*
   4674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4675 %                                                                             %
   4676 %                                                                             %
   4677 %                                                                             %
   4678 +  W r i t e B l o b F l o a t                                                %
   4679 %                                                                             %
   4680 %                                                                             %
   4681 %                                                                             %
   4682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4683 %
   4684 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
   4685 %  specified by the endian member of the image structure.
   4686 %
   4687 %  The format of the WriteBlobFloat method is:
   4688 %
   4689 %      ssize_t WriteBlobFloat(Image *image,const float value)
   4690 %
   4691 %  A description of each parameter follows.
   4692 %
   4693 %    o image: the image.
   4694 %
   4695 %    o value: Specifies the value to write.
   4696 %
   4697 */
   4698 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
   4699 {
   4700   union
   4701   {
   4702     unsigned int
   4703       unsigned_value;
   4704 
   4705     float
   4706       float_value;
   4707   } quantum;
   4708 
   4709   quantum.unsigned_value=0U;
   4710   quantum.float_value=value;
   4711   return(WriteBlobLong(image,quantum.unsigned_value));
   4712 }
   4713 
   4714 /*
   4716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4717 %                                                                             %
   4718 %                                                                             %
   4719 %                                                                             %
   4720 +  W r i t e B l o b L o n g                                                  %
   4721 %                                                                             %
   4722 %                                                                             %
   4723 %                                                                             %
   4724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4725 %
   4726 %  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
   4727 %  byte-order specified by the endian member of the image structure.
   4728 %
   4729 %  The format of the WriteBlobLong method is:
   4730 %
   4731 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
   4732 %
   4733 %  A description of each parameter follows.
   4734 %
   4735 %    o image: the image.
   4736 %
   4737 %    o value: Specifies the value to write.
   4738 %
   4739 */
   4740 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
   4741 {
   4742   unsigned char
   4743     buffer[4];
   4744 
   4745   assert(image != (Image *) NULL);
   4746   assert(image->signature == MagickCoreSignature);
   4747   if (image->endian == LSBEndian)
   4748     {
   4749       buffer[0]=(unsigned char) value;
   4750       buffer[1]=(unsigned char) (value >> 8);
   4751       buffer[2]=(unsigned char) (value >> 16);
   4752       buffer[3]=(unsigned char) (value >> 24);
   4753       return(WriteBlobStream(image,4,buffer));
   4754     }
   4755   buffer[0]=(unsigned char) (value >> 24);
   4756   buffer[1]=(unsigned char) (value >> 16);
   4757   buffer[2]=(unsigned char) (value >> 8);
   4758   buffer[3]=(unsigned char) value;
   4759   return(WriteBlobStream(image,4,buffer));
   4760 }
   4761 
   4762 /*
   4764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4765 %                                                                             %
   4766 %                                                                             %
   4767 %                                                                             %
   4768 +   W r i t e B l o b S h o r t                                               %
   4769 %                                                                             %
   4770 %                                                                             %
   4771 %                                                                             %
   4772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4773 %
   4774 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
   4775 %  byte-order specified by the endian member of the image structure.
   4776 %
   4777 %  The format of the WriteBlobShort method is:
   4778 %
   4779 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
   4780 %
   4781 %  A description of each parameter follows.
   4782 %
   4783 %    o image: the image.
   4784 %
   4785 %    o value:  Specifies the value to write.
   4786 %
   4787 */
   4788 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
   4789 {
   4790   unsigned char
   4791     buffer[2];
   4792 
   4793   assert(image != (Image *) NULL);
   4794   assert(image->signature == MagickCoreSignature);
   4795   if (image->endian == LSBEndian)
   4796     {
   4797       buffer[0]=(unsigned char) value;
   4798       buffer[1]=(unsigned char) (value >> 8);
   4799       return(WriteBlobStream(image,2,buffer));
   4800     }
   4801   buffer[0]=(unsigned char) (value >> 8);
   4802   buffer[1]=(unsigned char) value;
   4803   return(WriteBlobStream(image,2,buffer));
   4804 }
   4805 
   4806 /*
   4808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4809 %                                                                             %
   4810 %                                                                             %
   4811 %                                                                             %
   4812 +  W r i t e B l o b L S B L o n g                                            %
   4813 %                                                                             %
   4814 %                                                                             %
   4815 %                                                                             %
   4816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4817 %
   4818 %  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
   4819 %  least-significant byte first order.
   4820 %
   4821 %  The format of the WriteBlobLSBLong method is:
   4822 %
   4823 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
   4824 %
   4825 %  A description of each parameter follows.
   4826 %
   4827 %    o image: the image.
   4828 %
   4829 %    o value: Specifies the value to write.
   4830 %
   4831 */
   4832 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
   4833 {
   4834   unsigned char
   4835     buffer[4];
   4836 
   4837   assert(image != (Image *) NULL);
   4838   assert(image->signature == MagickCoreSignature);
   4839   buffer[0]=(unsigned char) value;
   4840   buffer[1]=(unsigned char) (value >> 8);
   4841   buffer[2]=(unsigned char) (value >> 16);
   4842   buffer[3]=(unsigned char) (value >> 24);
   4843   return(WriteBlobStream(image,4,buffer));
   4844 }
   4845 
   4846 /*
   4848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4849 %                                                                             %
   4850 %                                                                             %
   4851 %                                                                             %
   4852 +   W r i t e B l o b L S B S h o r t                                         %
   4853 %                                                                             %
   4854 %                                                                             %
   4855 %                                                                             %
   4856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4857 %
   4858 %  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
   4859 %  least-significant byte first order.
   4860 %
   4861 %  The format of the WriteBlobLSBShort method is:
   4862 %
   4863 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
   4864 %
   4865 %  A description of each parameter follows.
   4866 %
   4867 %    o image: the image.
   4868 %
   4869 %    o value:  Specifies the value to write.
   4870 %
   4871 */
   4872 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
   4873 {
   4874   unsigned char
   4875     buffer[2];
   4876 
   4877   assert(image != (Image *) NULL);
   4878   assert(image->signature == MagickCoreSignature);
   4879   buffer[0]=(unsigned char) value;
   4880   buffer[1]=(unsigned char) (value >> 8);
   4881   return(WriteBlobStream(image,2,buffer));
   4882 }
   4883 
   4884 /*
   4886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4887 %                                                                             %
   4888 %                                                                             %
   4889 %                                                                             %
   4890 +  W r i t e B l o b L S B S i g n e d L o n g                                %
   4891 %                                                                             %
   4892 %                                                                             %
   4893 %                                                                             %
   4894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4895 %
   4896 %  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
   4897 %  least-significant byte first order.
   4898 %
   4899 %  The format of the WriteBlobLSBSignedLong method is:
   4900 %
   4901 %      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
   4902 %
   4903 %  A description of each parameter follows.
   4904 %
   4905 %    o image: the image.
   4906 %
   4907 %    o value: Specifies the value to write.
   4908 %
   4909 */
   4910 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
   4911 {
   4912   union
   4913   {
   4914     unsigned int
   4915       unsigned_value;
   4916 
   4917     signed int
   4918       signed_value;
   4919   } quantum;
   4920 
   4921   unsigned char
   4922     buffer[4];
   4923 
   4924   assert(image != (Image *) NULL);
   4925   assert(image->signature == MagickCoreSignature);
   4926   quantum.signed_value=value;
   4927   buffer[0]=(unsigned char) quantum.unsigned_value;
   4928   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
   4929   buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
   4930   buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
   4931   return(WriteBlobStream(image,4,buffer));
   4932 }
   4933 
   4934 /*
   4936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4937 %                                                                             %
   4938 %                                                                             %
   4939 %                                                                             %
   4940 +   W r i t e B l o b L S B S i g n e d S h o r t                             %
   4941 %                                                                             %
   4942 %                                                                             %
   4943 %                                                                             %
   4944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4945 %
   4946 %  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
   4947 %  in least-significant byte first order.
   4948 %
   4949 %  The format of the WriteBlobLSBSignedShort method is:
   4950 %
   4951 %      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
   4952 %
   4953 %  A description of each parameter follows.
   4954 %
   4955 %    o image: the image.
   4956 %
   4957 %    o value:  Specifies the value to write.
   4958 %
   4959 */
   4960 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
   4961   const signed short value)
   4962 {
   4963   union
   4964   {
   4965     unsigned short
   4966       unsigned_value;
   4967 
   4968     signed short
   4969       signed_value;
   4970   } quantum;
   4971 
   4972   unsigned char
   4973     buffer[2];
   4974 
   4975   assert(image != (Image *) NULL);
   4976   assert(image->signature == MagickCoreSignature);
   4977   quantum.signed_value=value;
   4978   buffer[0]=(unsigned char) quantum.unsigned_value;
   4979   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
   4980   return(WriteBlobStream(image,2,buffer));
   4981 }
   4982 
   4983 /*
   4985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4986 %                                                                             %
   4987 %                                                                             %
   4988 %                                                                             %
   4989 +  W r i t e B l o b M S B L o n g                                            %
   4990 %                                                                             %
   4991 %                                                                             %
   4992 %                                                                             %
   4993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   4994 %
   4995 %  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
   4996 %  most-significant byte first order.
   4997 %
   4998 %  The format of the WriteBlobMSBLong method is:
   4999 %
   5000 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
   5001 %
   5002 %  A description of each parameter follows.
   5003 %
   5004 %    o value:  Specifies the value to write.
   5005 %
   5006 %    o image: the image.
   5007 %
   5008 */
   5009 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
   5010 {
   5011   unsigned char
   5012     buffer[4];
   5013 
   5014   assert(image != (Image *) NULL);
   5015   assert(image->signature == MagickCoreSignature);
   5016   buffer[0]=(unsigned char) (value >> 24);
   5017   buffer[1]=(unsigned char) (value >> 16);
   5018   buffer[2]=(unsigned char) (value >> 8);
   5019   buffer[3]=(unsigned char) value;
   5020   return(WriteBlobStream(image,4,buffer));
   5021 }
   5022 
   5023 /*
   5025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5026 %                                                                             %
   5027 %                                                                             %
   5028 %                                                                             %
   5029 +  W r i t e B l o b M S B L o n g L o n g                                    %
   5030 %                                                                             %
   5031 %                                                                             %
   5032 %                                                                             %
   5033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5034 %
   5035 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
   5036 %  most-significant byte first order.
   5037 %
   5038 %  The format of the WriteBlobMSBLongLong method is:
   5039 %
   5040 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
   5041 %
   5042 %  A description of each parameter follows.
   5043 %
   5044 %    o value:  Specifies the value to write.
   5045 %
   5046 %    o image: the image.
   5047 %
   5048 */
   5049 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
   5050   const MagickSizeType value)
   5051 {
   5052   unsigned char
   5053     buffer[8];
   5054 
   5055   assert(image != (Image *) NULL);
   5056   assert(image->signature == MagickCoreSignature);
   5057   buffer[0]=(unsigned char) (value >> 56);
   5058   buffer[1]=(unsigned char) (value >> 48);
   5059   buffer[2]=(unsigned char) (value >> 40);
   5060   buffer[3]=(unsigned char) (value >> 32);
   5061   buffer[4]=(unsigned char) (value >> 24);
   5062   buffer[5]=(unsigned char) (value >> 16);
   5063   buffer[6]=(unsigned char) (value >> 8);
   5064   buffer[7]=(unsigned char) value;
   5065   return(WriteBlobStream(image,8,buffer));
   5066 }
   5067 
   5068 /*
   5070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5071 %                                                                             %
   5072 %                                                                             %
   5073 %                                                                             %
   5074 +  W r i t e B l o b M S B S i g n e d L o n g                                %
   5075 %                                                                             %
   5076 %                                                                             %
   5077 %                                                                             %
   5078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5079 %
   5080 %  WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
   5081 %  most-significant byte first order.
   5082 %
   5083 %  The format of the WriteBlobMSBSignedLong method is:
   5084 %
   5085 %      ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
   5086 %
   5087 %  A description of each parameter follows.
   5088 %
   5089 %    o image: the image.
   5090 %
   5091 %    o value: Specifies the value to write.
   5092 %
   5093 */
   5094 MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
   5095 {
   5096   union
   5097   {
   5098     unsigned int
   5099       unsigned_value;
   5100 
   5101     signed int
   5102       signed_value;
   5103   } quantum;
   5104 
   5105   unsigned char
   5106     buffer[4];
   5107 
   5108   assert(image != (Image *) NULL);
   5109   assert(image->signature == MagickCoreSignature);
   5110   quantum.signed_value=value;
   5111   buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
   5112   buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
   5113   buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
   5114   buffer[3]=(unsigned char) quantum.unsigned_value;
   5115   return(WriteBlobStream(image,4,buffer));
   5116 }
   5117 
   5118 /*
   5120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5121 %                                                                             %
   5122 %                                                                             %
   5123 %                                                                             %
   5124 +   W r i t e B l o b M S B S i g n e d S h o r t                             %
   5125 %                                                                             %
   5126 %                                                                             %
   5127 %                                                                             %
   5128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5129 %
   5130 %  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
   5131 %  in most-significant byte first order.
   5132 %
   5133 %  The format of the WriteBlobMSBSignedShort method is:
   5134 %
   5135 %      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
   5136 %
   5137 %  A description of each parameter follows.
   5138 %
   5139 %    o image: the image.
   5140 %
   5141 %    o value:  Specifies the value to write.
   5142 %
   5143 */
   5144 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
   5145   const signed short value)
   5146 {
   5147   union
   5148   {
   5149     unsigned short
   5150       unsigned_value;
   5151 
   5152     signed short
   5153       signed_value;
   5154   } quantum;
   5155 
   5156   unsigned char
   5157     buffer[2];
   5158 
   5159   assert(image != (Image *) NULL);
   5160   assert(image->signature == MagickCoreSignature);
   5161   quantum.signed_value=value;
   5162   buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
   5163   buffer[1]=(unsigned char) quantum.unsigned_value;
   5164   return(WriteBlobStream(image,2,buffer));
   5165 }
   5166 
   5167 /*
   5169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5170 %                                                                             %
   5171 %                                                                             %
   5172 %                                                                             %
   5173 +  W r i t e B l o b M S B S h o r t                                          %
   5174 %                                                                             %
   5175 %                                                                             %
   5176 %                                                                             %
   5177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5178 %
   5179 %  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
   5180 %  most-significant byte first order.
   5181 %
   5182 %  The format of the WriteBlobMSBShort method is:
   5183 %
   5184 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
   5185 %
   5186 %  A description of each parameter follows.
   5187 %
   5188 %   o  value:  Specifies the value to write.
   5189 %
   5190 %   o  file:  Specifies the file to write the data to.
   5191 %
   5192 */
   5193 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
   5194 {
   5195   unsigned char
   5196     buffer[2];
   5197 
   5198   assert(image != (Image *) NULL);
   5199   assert(image->signature == MagickCoreSignature);
   5200   buffer[0]=(unsigned char) (value >> 8);
   5201   buffer[1]=(unsigned char) value;
   5202   return(WriteBlobStream(image,2,buffer));
   5203 }
   5204 
   5205 /*
   5207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5208 %                                                                             %
   5209 %                                                                             %
   5210 %                                                                             %
   5211 +  W r i t e B l o b S t r i n g                                              %
   5212 %                                                                             %
   5213 %                                                                             %
   5214 %                                                                             %
   5215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   5216 %
   5217 %  WriteBlobString() write a string to a blob.  It returns the number of
   5218 %  characters written.
   5219 %
   5220 %  The format of the WriteBlobString method is:
   5221 %
   5222 %      ssize_t WriteBlobString(Image *image,const char *string)
   5223 %
   5224 %  A description of each parameter follows.
   5225 %
   5226 %    o image: the image.
   5227 %
   5228 %    o string: Specifies the string to write.
   5229 %
   5230 */
   5231 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
   5232 {
   5233   assert(image != (Image *) NULL);
   5234   assert(image->signature == MagickCoreSignature);
   5235   assert(string != (const char *) NULL);
   5236   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
   5237 }
   5238