MagickCore  6.7.5
blob.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                         BBBB   L       OOO   BBBB                           %
00007 %                         B   B  L      O   O  B   B                          %
00008 %                         BBBB   L      O   O  BBBB                           %
00009 %                         B   B  L      O   O  B   B                          %
00010 %                         BBBB   LLLLL   OOO   BBBB                           %
00011 %                                                                             %
00012 %                                                                             %
00013 %                     MagickCore Binary Large OBjectS Methods                 %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 July 1999                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 %
00038 */
00039 
00040 /*
00041   Include declarations.
00042 */
00043 #include "MagickCore/studio.h"
00044 #include "MagickCore/blob.h"
00045 #include "MagickCore/blob-private.h"
00046 #include "MagickCore/cache.h"
00047 #include "MagickCore/client.h"
00048 #include "MagickCore/constitute.h"
00049 #include "MagickCore/delegate.h"
00050 #include "MagickCore/exception.h"
00051 #include "MagickCore/exception-private.h"
00052 #include "MagickCore/image-private.h"
00053 #include "MagickCore/list.h"
00054 #include "MagickCore/locale_.h"
00055 #include "MagickCore/log.h"
00056 #include "MagickCore/magick.h"
00057 #include "MagickCore/memory_.h"
00058 #include "MagickCore/policy.h"
00059 #include "MagickCore/resource_.h"
00060 #include "MagickCore/semaphore.h"
00061 #include "MagickCore/string_.h"
00062 #include "MagickCore/string-private.h"
00063 #include "MagickCore/token.h"
00064 #include "MagickCore/utility.h"
00065 #include "MagickCore/utility-private.h"
00066 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
00067 # include <sys/mman.h>
00068 #endif
00069 #if defined(MAGICKCORE_ZLIB_DELEGATE)
00070 #include "zlib.h"
00071 #endif
00072 #if defined(MAGICKCORE_BZLIB_DELEGATE)
00073 #include "bzlib.h"
00074 #endif
00075 
00076 /*
00077   Define declarations.
00078 */
00079 #define MagickMaxBlobExtent  65541
00080 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
00081 # define MAP_ANONYMOUS  MAP_ANON
00082 #endif
00083 #if !defined(MAP_FAILED)
00084 #define MAP_FAILED  ((void *) -1)
00085 #endif
00086 #if !defined(MS_SYNC)
00087 #define MS_SYNC  0x04
00088 #endif
00089 #if defined(__OS2__)
00090 #include <io.h>
00091 #define _O_BINARY O_BINARY
00092 #endif
00093 
00094 /*
00095   Typedef declarations.
00096 */
00097 struct _BlobInfo
00098 {
00099   size_t
00100     length,
00101     extent,
00102     quantum;
00103 
00104   MagickBooleanType
00105     mapped,
00106     eof;
00107 
00108   MagickOffsetType
00109     offset;
00110 
00111   MagickSizeType
00112     size;
00113 
00114   MagickBooleanType
00115     exempt,
00116     synchronize,
00117     status,
00118     temporary;
00119 
00120   StreamType
00121     type;
00122 
00123   union {
00124     FILE
00125       *file;
00126 
00127 #if defined(MAGICKCORE_ZLIB_DELEGATE)
00128     gzFile
00129       gzfile;
00130 #endif
00131 
00132 #if defined(MAGICKCORE_BZLIB_DELEGATE)
00133     BZFILE
00134       *bzfile;
00135 #endif
00136   };
00137 
00138   struct stat
00139     properties;
00140 
00141   StreamHandler
00142     stream;
00143 
00144   unsigned char
00145     *data;
00146 
00147   MagickBooleanType
00148     debug;
00149 
00150   SemaphoreInfo
00151     *semaphore;
00152 
00153   ssize_t
00154     reference_count;
00155 
00156   size_t
00157     signature;
00158 };
00159 
00160 /*
00161   Forward declarations.
00162 */
00163 static int
00164   SyncBlob(Image *);
00165 
00166 /*
00167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00168 %                                                                             %
00169 %                                                                             %
00170 %                                                                             %
00171 +   A t t a c h B l o b                                                       %
00172 %                                                                             %
00173 %                                                                             %
00174 %                                                                             %
00175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00176 %
00177 %  AttachBlob() attaches a blob to the BlobInfo structure.
00178 %
00179 %  The format of the AttachBlob method is:
00180 %
00181 %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
00182 %
00183 %  A description of each parameter follows:
00184 %
00185 %    o blob_info: Specifies a pointer to a BlobInfo structure.
00186 %
00187 %    o blob: the address of a character stream in one of the image formats
00188 %      understood by ImageMagick.
00189 %
00190 %    o length: This size_t integer reflects the length in bytes of the blob.
00191 %
00192 */
00193 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
00194   const size_t length)
00195 {
00196   assert(blob_info != (BlobInfo *) NULL);
00197   if (blob_info->debug != MagickFalse)
00198     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00199   blob_info->length=length;
00200   blob_info->extent=length;
00201   blob_info->quantum=(size_t) MagickMaxBlobExtent;
00202   blob_info->offset=0;
00203   blob_info->type=BlobStream;
00204   blob_info->file=(FILE *) NULL;
00205   blob_info->data=(unsigned char *) blob;
00206   blob_info->mapped=MagickFalse;
00207 }
00208 
00209 /*
00210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00211 %                                                                             %
00212 %                                                                             %
00213 %                                                                             %
00214 +   B l o b T o F i l e                                                       %
00215 %                                                                             %
00216 %                                                                             %
00217 %                                                                             %
00218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00219 %
00220 %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
00221 %  occurs otherwise MagickTrue.
00222 %
00223 %  The format of the BlobToFile method is:
00224 %
00225 %       MagickBooleanType BlobToFile(char *filename,const void *blob,
00226 %         const size_t length,ExceptionInfo *exception)
00227 %
00228 %  A description of each parameter follows:
00229 %
00230 %    o filename: Write the blob to this file.
00231 %
00232 %    o blob: the address of a blob.
00233 %
00234 %    o length: This length in bytes of the blob.
00235 %
00236 %    o exception: return any errors or warnings in this structure.
00237 %
00238 */
00239 
00240 static inline MagickSizeType MagickMin(const MagickSizeType x,
00241   const MagickSizeType y)
00242 {
00243   if (x < y)
00244     return(x);
00245   return(y);
00246 }
00247 
00248 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
00249   const size_t length,ExceptionInfo *exception)
00250 {
00251   int
00252     file;
00253 
00254   register size_t
00255     i;
00256 
00257   ssize_t
00258     count;
00259 
00260   assert(filename != (const char *) NULL);
00261   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00262   assert(blob != (const void *) NULL);
00263   if (*filename == '\0')
00264     file=AcquireUniqueFileResource(filename);
00265   else
00266     file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
00267   if (file == -1)
00268     {
00269       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
00270       return(MagickFalse);
00271     }
00272   for (i=0; i < length; i+=count)
00273   {
00274     count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length-
00275       i,(MagickSizeType) SSIZE_MAX));
00276     if (count <= 0)
00277       {
00278         count=0;
00279         if (errno != EINTR)
00280           break;
00281       }
00282   }
00283   file=close(file);
00284   if ((file == -1) || (i < length))
00285     {
00286       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
00287       return(MagickFalse);
00288     }
00289   return(MagickTrue);
00290 }
00291 
00292 /*
00293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00294 %                                                                             %
00295 %                                                                             %
00296 %                                                                             %
00297 %   B l o b T o I m a g e                                                     %
00298 %                                                                             %
00299 %                                                                             %
00300 %                                                                             %
00301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00302 %
00303 %  BlobToImage() implements direct to memory image formats.  It returns the
00304 %  blob as an image.
00305 %
00306 %  The format of the BlobToImage method is:
00307 %
00308 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
00309 %        const size_t length,ExceptionInfo *exception)
00310 %
00311 %  A description of each parameter follows:
00312 %
00313 %    o image_info: the image info.
00314 %
00315 %    o blob: the address of a character stream in one of the image formats
00316 %      understood by ImageMagick.
00317 %
00318 %    o length: This size_t integer reflects the length in bytes of the blob.
00319 %
00320 %    o exception: return any errors or warnings in this structure.
00321 %
00322 */
00323 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
00324   const size_t length,ExceptionInfo *exception)
00325 {
00326   const MagickInfo
00327     *magick_info;
00328 
00329   Image
00330     *image;
00331 
00332   ImageInfo
00333     *blob_info,
00334     *clone_info;
00335 
00336   MagickBooleanType
00337     status;
00338 
00339   assert(image_info != (ImageInfo *) NULL);
00340   assert(image_info->signature == MagickSignature);
00341   if (image_info->debug != MagickFalse)
00342     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00343       image_info->filename);
00344   assert(exception != (ExceptionInfo *) NULL);
00345   if ((blob == (const void *) NULL) || (length == 0))
00346     {
00347       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
00348         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
00349       return((Image *) NULL);
00350     }
00351   blob_info=CloneImageInfo(image_info);
00352   blob_info->blob=(void *) blob;
00353   blob_info->length=length;
00354   if (*blob_info->magick == '\0')
00355     (void) SetImageInfo(blob_info,0,exception);
00356   magick_info=GetMagickInfo(blob_info->magick,exception);
00357   if (magick_info == (const MagickInfo *) NULL)
00358     {
00359       blob_info=DestroyImageInfo(blob_info);
00360       (void) ThrowMagickException(exception,GetMagickModule(),
00361         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
00362         image_info->filename);
00363       return((Image *) NULL);
00364     }
00365   if (GetMagickBlobSupport(magick_info) != MagickFalse)
00366     {
00367       /*
00368         Native blob support for this image format.
00369       */
00370       (void) CopyMagickString(blob_info->filename,image_info->filename,
00371         MaxTextExtent);
00372       (void) CopyMagickString(blob_info->magick,image_info->magick,
00373         MaxTextExtent);
00374       image=ReadImage(blob_info,exception);
00375       if (image != (Image *) NULL)
00376         (void) DetachBlob(image->blob);
00377       blob_info=DestroyImageInfo(blob_info);
00378       return(image);
00379     }
00380   /*
00381     Write blob to a temporary file on disk.
00382   */
00383   blob_info->blob=(void *) NULL;
00384   blob_info->length=0;
00385   *blob_info->filename='\0';
00386   status=BlobToFile(blob_info->filename,blob,length,exception);
00387   if (status == MagickFalse)
00388     {
00389       (void) RelinquishUniqueFileResource(blob_info->filename);
00390       blob_info=DestroyImageInfo(blob_info);
00391       return((Image *) NULL);
00392     }
00393   clone_info=CloneImageInfo(blob_info);
00394   (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
00395     blob_info->magick,blob_info->filename);
00396   image=ReadImage(clone_info,exception);
00397   clone_info=DestroyImageInfo(clone_info);
00398   (void) RelinquishUniqueFileResource(blob_info->filename);
00399   blob_info=DestroyImageInfo(blob_info);
00400   return(image);
00401 }
00402 
00403 /*
00404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00405 %                                                                             %
00406 %                                                                             %
00407 %                                                                             %
00408 +   C l o n e B l o b I n f o                                                 %
00409 %                                                                             %
00410 %                                                                             %
00411 %                                                                             %
00412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00413 %
00414 %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
00415 %  blob info is NULL, a new one.
00416 %
00417 %  The format of the CloneBlobInfo method is:
00418 %
00419 %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
00420 %
00421 %  A description of each parameter follows:
00422 %
00423 %    o blob_info: the blob info.
00424 %
00425 */
00426 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
00427 {
00428   BlobInfo
00429     *clone_info;
00430 
00431   clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
00432   if (clone_info == (BlobInfo *) NULL)
00433     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00434   GetBlobInfo(clone_info);
00435   if (blob_info == (BlobInfo *) NULL)
00436     return(clone_info);
00437   clone_info->length=blob_info->length;
00438   clone_info->extent=blob_info->extent;
00439   clone_info->synchronize=blob_info->synchronize;
00440   clone_info->quantum=blob_info->quantum;
00441   clone_info->mapped=blob_info->mapped;
00442   clone_info->eof=blob_info->eof;
00443   clone_info->offset=blob_info->offset;
00444   clone_info->size=blob_info->size;
00445   clone_info->exempt=blob_info->exempt;
00446   clone_info->status=blob_info->status;
00447   clone_info->temporary=blob_info->temporary;
00448   clone_info->type=blob_info->type;
00449   clone_info->file=blob_info->file;
00450   clone_info->properties=blob_info->properties;
00451   clone_info->stream=blob_info->stream;
00452   clone_info->data=blob_info->data;
00453   clone_info->debug=IsEventLogging();
00454   clone_info->reference_count=1;
00455   return(clone_info);
00456 }
00457 
00458 /*
00459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00460 %                                                                             %
00461 %                                                                             %
00462 %                                                                             %
00463 +   C l o s e B l o b                                                         %
00464 %                                                                             %
00465 %                                                                             %
00466 %                                                                             %
00467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00468 %
00469 %  CloseBlob() closes a stream associated with the image.
00470 %
00471 %  The format of the CloseBlob method is:
00472 %
00473 %      MagickBooleanType CloseBlob(Image *image)
00474 %
00475 %  A description of each parameter follows:
00476 %
00477 %    o image: the image.
00478 %
00479 */
00480 MagickExport MagickBooleanType CloseBlob(Image *image)
00481 {
00482   int
00483     status;
00484 
00485   /*
00486     Close image file.
00487   */
00488   assert(image != (Image *) NULL);
00489   assert(image->signature == MagickSignature);
00490   if (image->debug != MagickFalse)
00491     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00492   assert(image->blob != (BlobInfo *) NULL);
00493   if (image->blob->type == UndefinedStream)
00494     return(MagickTrue);
00495   if (image->blob->synchronize != MagickFalse)
00496     SyncBlob(image);
00497   image->blob->size=GetBlobSize(image);
00498   image->extent=image->blob->size;
00499   image->blob->eof=MagickFalse;
00500   if (image->blob->exempt != MagickFalse)
00501     {
00502       image->blob->type=UndefinedStream;
00503       return(MagickTrue);
00504     }
00505   status=0;
00506   switch (image->blob->type)
00507   {
00508     case UndefinedStream:
00509       break;
00510     case FileStream:
00511     case StandardStream:
00512     case PipeStream:
00513     {
00514       status=ferror(image->blob->file);
00515       break;
00516     }
00517     case ZipStream:
00518     {
00519 #if defined(MAGICKCORE_ZLIB_DELEGATE)
00520       (void) gzerror(image->blob->gzfile,&status);
00521 #endif
00522       break;
00523     }
00524     case BZipStream:
00525     {
00526 #if defined(MAGICKCORE_BZLIB_DELEGATE)
00527       (void) BZ2_bzerror(image->blob->bzfile,&status);
00528 #endif
00529       break;
00530     }
00531     case FifoStream:
00532     case BlobStream:
00533       break;
00534   }
00535   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
00536   switch (image->blob->type)
00537   {
00538     case UndefinedStream:
00539       break;
00540     case FileStream:
00541     case StandardStream:
00542     {
00543       if (image->blob->synchronize != MagickFalse)
00544         {
00545           status=fflush(image->blob->file);
00546           status=fsync(fileno(image->blob->file));
00547         }
00548       status=fclose(image->blob->file);
00549       break;
00550     }
00551     case PipeStream:
00552     {
00553 #if defined(MAGICKCORE_HAVE_PCLOSE)
00554       status=pclose(image->blob->file);
00555 #endif
00556       break;
00557     }
00558     case ZipStream:
00559     {
00560 #if defined(MAGICKCORE_ZLIB_DELEGATE)
00561       status=gzclose(image->blob->gzfile);
00562 #endif
00563       break;
00564     }
00565     case BZipStream:
00566     {
00567 #if defined(MAGICKCORE_BZLIB_DELEGATE)
00568       BZ2_bzclose(image->blob->bzfile);
00569 #endif
00570       break;
00571     }
00572     case FifoStream:
00573       break;
00574     case BlobStream:
00575     {
00576       if (image->blob->file != (FILE *) NULL)
00577         {
00578           if (image->blob->synchronize != MagickFalse)
00579             (void) fsync(fileno(image->blob->file));
00580           status=fclose(image->blob->file);
00581         }
00582       break;
00583     }
00584   }
00585   (void) DetachBlob(image->blob);
00586   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
00587   return(image->blob->status);
00588 }
00589 
00590 /*
00591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00592 %                                                                             %
00593 %                                                                             %
00594 %                                                                             %
00595 +   D e s t r o y B l o b                                                     %
00596 %                                                                             %
00597 %                                                                             %
00598 %                                                                             %
00599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00600 %
00601 %  DestroyBlob() deallocates memory associated with a blob.
00602 %
00603 %  The format of the DestroyBlob method is:
00604 %
00605 %      void DestroyBlob(Image *image)
00606 %
00607 %  A description of each parameter follows:
00608 %
00609 %    o image: the image.
00610 %
00611 */
00612 MagickExport void DestroyBlob(Image *image)
00613 {
00614   MagickBooleanType
00615     destroy;
00616 
00617   assert(image != (Image *) NULL);
00618   assert(image->signature == MagickSignature);
00619   if (image->debug != MagickFalse)
00620     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00621   assert(image->blob != (BlobInfo *) NULL);
00622   assert(image->blob->signature == MagickSignature);
00623   destroy=MagickFalse;
00624   LockSemaphoreInfo(image->blob->semaphore);
00625   image->blob->reference_count--;
00626   assert(image->blob->reference_count >= 0);
00627   if (image->blob->reference_count == 0)
00628     destroy=MagickTrue;
00629   UnlockSemaphoreInfo(image->blob->semaphore);
00630   if (destroy == MagickFalse)
00631     return;
00632   (void) CloseBlob(image);
00633   if (image->blob->mapped != MagickFalse)
00634     (void) UnmapBlob(image->blob->data,image->blob->length);
00635   if (image->blob->semaphore != (SemaphoreInfo *) NULL)
00636     DestroySemaphoreInfo(&image->blob->semaphore);
00637   image->blob->signature=(~MagickSignature);
00638   image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
00639 }
00640 
00641 /*
00642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00643 %                                                                             %
00644 %                                                                             %
00645 %                                                                             %
00646 +   D e t a c h B l o b                                                       %
00647 %                                                                             %
00648 %                                                                             %
00649 %                                                                             %
00650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00651 %
00652 %  DetachBlob() detaches a blob from the BlobInfo structure.
00653 %
00654 %  The format of the DetachBlob method is:
00655 %
00656 %      unsigned char *DetachBlob(BlobInfo *blob_info)
00657 %
00658 %  A description of each parameter follows:
00659 %
00660 %    o blob_info: Specifies a pointer to a BlobInfo structure.
00661 %
00662 */
00663 MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
00664 {
00665   unsigned char
00666     *data;
00667 
00668   assert(blob_info != (BlobInfo *) NULL);
00669   if (blob_info->debug != MagickFalse)
00670     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00671   if (blob_info->mapped != MagickFalse)
00672     (void) UnmapBlob(blob_info->data,blob_info->length);
00673   blob_info->mapped=MagickFalse;
00674   blob_info->length=0;
00675   blob_info->offset=0;
00676   blob_info->eof=MagickFalse;
00677   blob_info->exempt=MagickFalse;
00678   blob_info->type=UndefinedStream;
00679   blob_info->file=(FILE *) NULL;
00680   data=blob_info->data;
00681   blob_info->data=(unsigned char *) NULL;
00682   blob_info->stream=(StreamHandler) NULL;
00683   return(data);
00684 }
00685 
00686 /*
00687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00688 %                                                                             %
00689 %                                                                             %
00690 %                                                                             %
00691 +  D i s c a r d B l o b B y t e s                                            %
00692 %                                                                             %
00693 %                                                                             %
00694 %                                                                             %
00695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00696 %
00697 %  DiscardBlobBytes() discards bytes in a blob.
00698 %
00699 %  The format of the DiscardBlobBytes method is:
00700 %
00701 %      MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
00702 %
00703 %  A description of each parameter follows.
00704 %
00705 %    o image: the image.
00706 %
00707 %    o length:  the number of bytes to skip.
00708 %
00709 */
00710 
00711 static inline const unsigned char *ReadBlobStream(Image *image,
00712   const size_t length,unsigned char *data,ssize_t *count)
00713 {
00714   assert(count != (ssize_t *) NULL);
00715   assert(image->blob != (BlobInfo *) NULL);
00716   if (image->blob->type != BlobStream)
00717     {
00718       *count=ReadBlob(image,length,data);
00719       return(data);
00720     }
00721   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
00722     {
00723       *count=0;
00724       image->blob->eof=MagickTrue;
00725       return(data);
00726     }
00727   data=image->blob->data+image->blob->offset;
00728   *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
00729     image->blob->offset));
00730   image->blob->offset+=(*count);
00731   if (*count != (ssize_t) length)
00732     image->blob->eof=MagickTrue;
00733   return(data);
00734 }
00735 
00736 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
00737   const MagickSizeType length)
00738 {
00739   register MagickOffsetType
00740     i;
00741 
00742   size_t
00743     quantum;
00744 
00745   ssize_t
00746     count;
00747 
00748   unsigned char
00749     buffer[16384];
00750 
00751   assert(image != (Image *) NULL);
00752   assert(image->signature == MagickSignature);
00753   count=0;
00754   for (i=0; i < (MagickOffsetType) length; i+=count)
00755   {
00756     quantum=(size_t) MagickMin(length-i,sizeof(buffer));
00757     (void) ReadBlobStream(image,quantum,buffer,&count);
00758     if (count <= 0)
00759       {
00760         count=0;
00761         if (errno != EINTR)
00762           break;
00763       }
00764   }
00765   return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
00766 }
00767 
00768 /*
00769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00770 %                                                                             %
00771 %                                                                             %
00772 %                                                                             %
00773 +   D u p l i c a t e s B l o b                                               %
00774 %                                                                             %
00775 %                                                                             %
00776 %                                                                             %
00777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00778 %
00779 %  DuplicateBlob() duplicates a blob descriptor.
00780 %
00781 %  The format of the DuplicateBlob method is:
00782 %
00783 %      void DuplicateBlob(Image *image,const Image *duplicate)
00784 %
00785 %  A description of each parameter follows:
00786 %
00787 %    o image: the image.
00788 %
00789 %    o duplicate: the duplicate image.
00790 %
00791 */
00792 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
00793 {
00794   assert(image != (Image *) NULL);
00795   assert(image->signature == MagickSignature);
00796   if (image->debug != MagickFalse)
00797     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00798   assert(duplicate != (Image *) NULL);
00799   assert(duplicate->signature == MagickSignature);
00800   DestroyBlob(image);
00801   image->blob=ReferenceBlob(duplicate->blob);
00802 }
00803 
00804 /*
00805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00806 %                                                                             %
00807 %                                                                             %
00808 %                                                                             %
00809 +  E O F B l o b                                                              %
00810 %                                                                             %
00811 %                                                                             %
00812 %                                                                             %
00813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00814 %
00815 %  EOFBlob() returns a non-zero value when EOF has been detected reading from
00816 %  a blob or file.
00817 %
00818 %  The format of the EOFBlob method is:
00819 %
00820 %      int EOFBlob(const Image *image)
00821 %
00822 %  A description of each parameter follows:
00823 %
00824 %    o image: the image.
00825 %
00826 */
00827 MagickExport int EOFBlob(const Image *image)
00828 {
00829   assert(image != (Image *) NULL);
00830   assert(image->signature == MagickSignature);
00831   if (image->debug != MagickFalse)
00832     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00833   assert(image->blob != (BlobInfo *) NULL);
00834   assert(image->blob->type != UndefinedStream);
00835   switch (image->blob->type)
00836   {
00837     case UndefinedStream:
00838       break;
00839     case FileStream:
00840     case StandardStream:
00841     case PipeStream:
00842     {
00843       image->blob->eof=feof(image->blob->file) != 0 ? MagickTrue : MagickFalse;
00844       break;
00845     }
00846     case ZipStream:
00847     {
00848       image->blob->eof=MagickFalse;
00849       break;
00850     }
00851     case BZipStream:
00852     {
00853 #if defined(MAGICKCORE_BZLIB_DELEGATE)
00854       int
00855         status;
00856 
00857       status=0;
00858       (void) BZ2_bzerror(image->blob->bzfile,&status);
00859       image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
00860 #endif
00861       break;
00862     }
00863     case FifoStream:
00864     {
00865       image->blob->eof=MagickFalse;
00866       break;
00867     }
00868     case BlobStream:
00869       break;
00870   }
00871   return((int) image->blob->eof);
00872 }
00873 
00874 /*
00875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00876 %                                                                             %
00877 %                                                                             %
00878 %                                                                             %
00879 +   F i l e T o B l o b                                                       %
00880 %                                                                             %
00881 %                                                                             %
00882 %                                                                             %
00883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00884 %
00885 %  FileToBlob() returns the contents of a file as a buffer terminated with
00886 %  the '\0' character.  The length of the buffer (not including the extra
00887 %  terminating '\0' character) is returned via the 'length' parameter.  Free
00888 %  the buffer with RelinquishMagickMemory().
00889 %
00890 %  The format of the FileToBlob method is:
00891 %
00892 %      unsigned char *FileToBlob(const char *filename,const size_t extent,
00893 %        size_t *length,ExceptionInfo *exception)
00894 %
00895 %  A description of each parameter follows:
00896 %
00897 %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
00898 %      an error occurs NULL is returned.
00899 %
00900 %    o filename: the filename.
00901 %
00902 %    o extent:  The maximum length of the blob.
00903 %
00904 %    o length: On return, this reflects the actual length of the blob.
00905 %
00906 %    o exception: return any errors or warnings in this structure.
00907 %
00908 */
00909 MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
00910   size_t *length,ExceptionInfo *exception)
00911 {
00912   int
00913     file;
00914 
00915   MagickOffsetType
00916     offset;
00917 
00918   register size_t
00919     i;
00920 
00921   ssize_t
00922     count;
00923 
00924   unsigned char
00925     *blob;
00926 
00927   void
00928     *map;
00929 
00930   assert(filename != (const char *) NULL);
00931   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00932   assert(exception != (ExceptionInfo *) NULL);
00933   *length=0;
00934   file=fileno(stdin);
00935   if (LocaleCompare(filename,"-") != 0)
00936     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
00937   if (file == -1)
00938     {
00939       ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
00940       return((unsigned char *) NULL);
00941     }
00942   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
00943   count=0;
00944   if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
00945     {
00946       size_t
00947         quantum;
00948 
00949       struct stat
00950         file_info;
00951 
00952       /*
00953         Stream is not seekable.
00954       */
00955       quantum=(size_t) MagickMaxBufferExtent;
00956       if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
00957         quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
00958           MagickMaxBufferExtent);
00959       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
00960       for (i=0; blob != (unsigned char *) NULL; i+=count)
00961       {
00962         count=(ssize_t) read(file,blob+i,quantum);
00963         if (count <= 0)
00964           {
00965             count=0;
00966             if (errno != EINTR)
00967               break;
00968           }
00969         if (~(1UL*i) < (quantum+1))
00970           {
00971             blob=(unsigned char *) RelinquishMagickMemory(blob);
00972             break;
00973           }
00974         blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
00975           sizeof(*blob));
00976         if ((size_t) (i+count) >= extent)
00977           break;
00978       }
00979       if (LocaleCompare(filename,"-") != 0)
00980         file=close(file);
00981       if (blob == (unsigned char *) NULL)
00982         {
00983           (void) ThrowMagickException(exception,GetMagickModule(),
00984             ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
00985           return((unsigned char *) NULL);
00986         }
00987       if (file == -1)
00988         {
00989           blob=(unsigned char *) RelinquishMagickMemory(blob);
00990           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
00991           return((unsigned char *) NULL);
00992         }
00993       *length=(size_t) MagickMin(i+count,extent);
00994       blob[*length]='\0';
00995       return(blob);
00996     }
00997   *length=(size_t) MagickMin((MagickSizeType) offset,extent);
00998   blob=(unsigned char *) NULL;
00999   if (~(*length) >= (MaxTextExtent-1))
01000     blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
01001       sizeof(*blob));
01002   if (blob == (unsigned char *) NULL)
01003     {
01004       file=close(file);
01005       (void) ThrowMagickException(exception,GetMagickModule(),
01006         ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
01007       return((unsigned char *) NULL);
01008     }
01009   map=MapBlob(file,ReadMode,0,*length);
01010   if (map != (unsigned char *) NULL)
01011     {
01012       (void) memcpy(blob,map,*length);
01013       (void) UnmapBlob(map,*length);
01014     }
01015   else
01016     {
01017       (void) lseek(file,0,SEEK_SET);
01018       for (i=0; i < *length; i+=count)
01019       {
01020         count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i,
01021           (MagickSizeType) SSIZE_MAX));
01022         if (count <= 0)
01023           {
01024             count=0;
01025             if (errno != EINTR)
01026               break;
01027           }
01028       }
01029       if (i < *length)
01030         {
01031           file=close(file)-1;
01032           blob=(unsigned char *) RelinquishMagickMemory(blob);
01033           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
01034           return((unsigned char *) NULL);
01035         }
01036     }
01037   blob[*length]='\0';
01038   if (LocaleCompare(filename,"-") != 0)
01039     file=close(file);
01040   if (file == -1)
01041     {
01042       blob=(unsigned char *) RelinquishMagickMemory(blob);
01043       ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
01044     }
01045   return(blob);
01046 }
01047 
01048 /*
01049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01050 %                                                                             %
01051 %                                                                             %
01052 %                                                                             %
01053 %   F i l e T o I m a g e                                                     %
01054 %                                                                             %
01055 %                                                                             %
01056 %                                                                             %
01057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01058 %
01059 %  FileToImage() write the contents of a file to an image.
01060 %
01061 %  The format of the FileToImage method is:
01062 %
01063 %      MagickBooleanType FileToImage(Image *,const char *filename)
01064 %
01065 %  A description of each parameter follows:
01066 %
01067 %    o image: the image.
01068 %
01069 %    o filename: the filename.
01070 %
01071 */
01072 
01073 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
01074   const unsigned char *data)
01075 {
01076   MagickSizeType
01077     extent;
01078 
01079   register unsigned char
01080     *q;
01081 
01082   assert(image->blob != (BlobInfo *) NULL);
01083   if (image->blob->type != BlobStream)
01084     return(WriteBlob(image,length,data));
01085   assert(image->blob->type != UndefinedStream);
01086   assert(data != (void *) NULL);
01087   extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
01088   if (extent >= image->blob->extent)
01089     {
01090       image->blob->quantum<<=1;
01091       extent=image->blob->extent+image->blob->quantum+length;
01092       if (SetBlobExtent(image,extent) == MagickFalse)
01093         return(0);
01094     }
01095   q=image->blob->data+image->blob->offset;
01096   (void) memcpy(q,data,length);
01097   image->blob->offset+=length;
01098   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
01099     image->blob->length=(size_t) image->blob->offset;
01100   return((ssize_t) length);
01101 }
01102 
01103 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
01104   ExceptionInfo *exception)
01105 {
01106   int
01107     file;
01108 
01109   size_t
01110     length,
01111     quantum;
01112 
01113   ssize_t
01114     count;
01115 
01116   struct stat
01117     file_info;
01118 
01119   unsigned char
01120     *blob;
01121 
01122   assert(image != (const Image *) NULL);
01123   assert(image->signature == MagickSignature);
01124   assert(filename != (const char *) NULL);
01125   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
01126   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
01127   if (file == -1)
01128     {
01129       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
01130       return(MagickFalse);
01131     }
01132   quantum=(size_t) MagickMaxBufferExtent;
01133   if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
01134     quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
01135   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
01136   if (blob == (unsigned char *) NULL)
01137     {
01138       ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
01139         filename);
01140       return(MagickFalse);
01141     }
01142   for ( ; ; )
01143   {
01144     count=(ssize_t) read(file,blob,quantum);
01145     if (count <= 0)
01146       {
01147         count=0;
01148         if (errno != EINTR)
01149           break;
01150       }
01151     length=(size_t) count;
01152     count=WriteBlobStream(image,length,blob);
01153     if (count != (ssize_t) length)
01154       {
01155         ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
01156         break;
01157       }
01158   }
01159   file=close(file);
01160   if (file == -1)
01161     ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
01162   blob=(unsigned char *) RelinquishMagickMemory(blob);
01163   return(MagickTrue);
01164 }
01165 
01166 /*
01167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01168 %                                                                             %
01169 %                                                                             %
01170 %                                                                             %
01171 +   G e t B l o b E r r o r                                                   %
01172 %                                                                             %
01173 %                                                                             %
01174 %                                                                             %
01175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01176 %
01177 %  GetBlobError() returns MagickTrue if the blob associated with the specified
01178 %  image encountered an error.
01179 %
01180 %  The format of the GetBlobError method is:
01181 %
01182 %       MagickBooleanType GetBlobError(const Image *image)
01183 %
01184 %  A description of each parameter follows:
01185 %
01186 %    o image: the image.
01187 %
01188 */
01189 MagickPrivate MagickBooleanType GetBlobError(const Image *image)
01190 {
01191   assert(image != (const Image *) NULL);
01192   assert(image->signature == MagickSignature);
01193   if (image->debug != MagickFalse)
01194     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01195   return(image->blob->status);
01196 }
01197 
01198 /*
01199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01200 %                                                                             %
01201 %                                                                             %
01202 %                                                                             %
01203 +   G e t B l o b F i l e H a n d l e                                         %
01204 %                                                                             %
01205 %                                                                             %
01206 %                                                                             %
01207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01208 %
01209 %  GetBlobFileHandle() returns the file handle associated with the image blob.
01210 %
01211 %  The format of the GetBlobFile method is:
01212 %
01213 %      FILE *GetBlobFileHandle(const Image *image)
01214 %
01215 %  A description of each parameter follows:
01216 %
01217 %    o image: the image.
01218 %
01219 */
01220 MagickExport FILE *GetBlobFileHandle(const Image *image)
01221 {
01222   assert(image != (const Image *) NULL);
01223   assert(image->signature == MagickSignature);
01224   return(image->blob->file);
01225 }
01226 
01227 /*
01228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01229 %                                                                             %
01230 %                                                                             %
01231 %                                                                             %
01232 +   G e t B l o b I n f o                                                     %
01233 %                                                                             %
01234 %                                                                             %
01235 %                                                                             %
01236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01237 %
01238 %  GetBlobInfo() initializes the BlobInfo structure.
01239 %
01240 %  The format of the GetBlobInfo method is:
01241 %
01242 %      void GetBlobInfo(BlobInfo *blob_info)
01243 %
01244 %  A description of each parameter follows:
01245 %
01246 %    o blob_info: Specifies a pointer to a BlobInfo structure.
01247 %
01248 */
01249 MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
01250 {
01251   assert(blob_info != (BlobInfo *) NULL);
01252   (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
01253   blob_info->type=UndefinedStream;
01254   blob_info->quantum=(size_t) MagickMaxBlobExtent;
01255   blob_info->properties.st_mtime=time((time_t *) NULL);
01256   blob_info->properties.st_ctime=time((time_t *) NULL);
01257   blob_info->debug=IsEventLogging();
01258   blob_info->reference_count=1;
01259   blob_info->semaphore=AllocateSemaphoreInfo();
01260   blob_info->signature=MagickSignature;
01261 }
01262 
01263 /*
01264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01265 %                                                                             %
01266 %                                                                             %
01267 %                                                                             %
01268 %  G e t B l o b P r o p e r t i e s                                          %
01269 %                                                                             %
01270 %                                                                             %
01271 %                                                                             %
01272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01273 %
01274 %  GetBlobProperties() returns information about an image blob.
01275 %
01276 %  The format of the GetBlobProperties method is:
01277 %
01278 %      const struct stat *GetBlobProperties(const Image *image)
01279 %
01280 %  A description of each parameter follows:
01281 %
01282 %    o image: the image.
01283 %
01284 */
01285 MagickPrivate const struct stat *GetBlobProperties(const Image *image)
01286 {
01287   assert(image != (Image *) NULL);
01288   assert(image->signature == MagickSignature);
01289   if (image->debug != MagickFalse)
01290     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01291   return(&image->blob->properties);
01292 }
01293 
01294 /*
01295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01296 %                                                                             %
01297 %                                                                             %
01298 %                                                                             %
01299 +  G e t B l o b S i z e                                                      %
01300 %                                                                             %
01301 %                                                                             %
01302 %                                                                             %
01303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01304 %
01305 %  GetBlobSize() returns the current length of the image file or blob; zero is
01306 %  returned if the size cannot be determined.
01307 %
01308 %  The format of the GetBlobSize method is:
01309 %
01310 %      MagickSizeType GetBlobSize(const Image *image)
01311 %
01312 %  A description of each parameter follows:
01313 %
01314 %    o image: the image.
01315 %
01316 */
01317 MagickExport MagickSizeType GetBlobSize(const Image *image)
01318 {
01319   MagickSizeType
01320     extent;
01321 
01322   assert(image != (Image *) NULL);
01323   assert(image->signature == MagickSignature);
01324   if (image->debug != MagickFalse)
01325     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01326   assert(image->blob != (BlobInfo *) NULL);
01327   extent=0;
01328   switch (image->blob->type)
01329   {
01330     case UndefinedStream:
01331     {
01332       extent=image->blob->size;
01333       break;
01334     }
01335     case FileStream:
01336     {
01337       if (fstat(fileno(image->blob->file),&image->blob->properties) == 0)
01338         extent=(MagickSizeType) image->blob->properties.st_size;
01339       break;
01340     }
01341     case StandardStream:
01342     case PipeStream:
01343     {
01344       extent=image->blob->size;
01345       break;
01346     }
01347     case ZipStream:
01348     case BZipStream:
01349     {
01350       MagickBooleanType
01351         status;
01352 
01353       status=GetPathAttributes(image->filename,&image->blob->properties);
01354       if (status != MagickFalse)
01355         extent=(MagickSizeType) image->blob->properties.st_size;
01356       break;
01357     }
01358     case FifoStream:
01359       break;
01360     case BlobStream:
01361     {
01362       extent=(MagickSizeType) image->blob->length;
01363       break;
01364     }
01365   }
01366   return(extent);
01367 }
01368 
01369 /*
01370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01371 %                                                                             %
01372 %                                                                             %
01373 %                                                                             %
01374 +   G e t B l o b S t r e a m D a t a                                         %
01375 %                                                                             %
01376 %                                                                             %
01377 %                                                                             %
01378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01379 %
01380 %  GetBlobStreamData() returns the stream data for the image.
01381 %
01382 %  The format of the GetBlobStreamData method is:
01383 %
01384 %      unsigned char *GetBlobStreamData(const Image *image)
01385 %
01386 %  A description of each parameter follows:
01387 %
01388 %    o image: the image.
01389 %
01390 */
01391 MagickExport unsigned char *GetBlobStreamData(const Image *image)
01392 {
01393   assert(image != (const Image *) NULL);
01394   assert(image->signature == MagickSignature);
01395   return(image->blob->data);
01396 }
01397 
01398 /*
01399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01400 %                                                                             %
01401 %                                                                             %
01402 %                                                                             %
01403 +   G e t B l o b S t r e a m H a n d l e r                                   %
01404 %                                                                             %
01405 %                                                                             %
01406 %                                                                             %
01407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01408 %
01409 %  GetBlobStreamHandler() returns the stream handler for the image.
01410 %
01411 %  The format of the GetBlobStreamHandler method is:
01412 %
01413 %      StreamHandler GetBlobStreamHandler(const Image *image)
01414 %
01415 %  A description of each parameter follows:
01416 %
01417 %    o image: the image.
01418 %
01419 */
01420 MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
01421 {
01422   assert(image != (const Image *) NULL);
01423   assert(image->signature == MagickSignature);
01424   if (image->debug != MagickFalse)
01425     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01426   return(image->blob->stream);
01427 }
01428 
01429 /*
01430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01431 %                                                                             %
01432 %                                                                             %
01433 %                                                                             %
01434 %   I m a g e T o B l o b                                                     %
01435 %                                                                             %
01436 %                                                                             %
01437 %                                                                             %
01438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01439 %
01440 %  ImageToBlob() implements direct to memory image formats.  It returns the
01441 %  image as a formatted blob and its length.  The magick member of the Image
01442 %  structure determines the format of the returned blob (GIF, JPEG, PNG,
01443 %  etc.).  This method is the equivalent of WriteImage(), but writes the
01444 %  formatted "file" to a memory buffer rather than to an actual file.
01445 %
01446 %  The format of the ImageToBlob method is:
01447 %
01448 %      unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
01449 %        size_t *length,ExceptionInfo *exception)
01450 %
01451 %  A description of each parameter follows:
01452 %
01453 %    o image_info: the image info.
01454 %
01455 %    o image: the image.
01456 %
01457 %    o length: This pointer to a size_t integer sets the initial length of the
01458 %      blob.  On return, it reflects the actual length of the blob.
01459 %
01460 %    o exception: return any errors or warnings in this structure.
01461 %
01462 */
01463 MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
01464   Image *image,size_t *length,ExceptionInfo *exception)
01465 {
01466   const MagickInfo
01467     *magick_info;
01468 
01469   ImageInfo
01470     *blob_info;
01471 
01472   MagickBooleanType
01473     status;
01474 
01475   unsigned char
01476     *blob;
01477 
01478   assert(image_info != (const ImageInfo *) NULL);
01479   assert(image_info->signature == MagickSignature);
01480   if (image_info->debug != MagickFalse)
01481     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01482       image_info->filename);
01483   assert(image != (Image *) NULL);
01484   assert(image->signature == MagickSignature);
01485   assert(exception != (ExceptionInfo *) NULL);
01486   *length=0;
01487   blob=(unsigned char *) NULL;
01488   blob_info=CloneImageInfo(image_info);
01489   blob_info->adjoin=MagickFalse;
01490   (void) SetImageInfo(blob_info,1,exception);
01491   if (*blob_info->magick != '\0')
01492     (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
01493   magick_info=GetMagickInfo(image->magick,exception);
01494   if (magick_info == (const MagickInfo *) NULL)
01495     {
01496       (void) ThrowMagickException(exception,GetMagickModule(),
01497         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
01498         image->filename);
01499       return(blob);
01500     }
01501   (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
01502   if (GetMagickBlobSupport(magick_info) != MagickFalse)
01503     {
01504       /*
01505         Native blob support for this image format.
01506       */
01507       blob_info->length=0;
01508       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
01509         sizeof(unsigned char));
01510       if (blob_info->blob == (void *) NULL)
01511         (void) ThrowMagickException(exception,GetMagickModule(),
01512           ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
01513       else
01514         {
01515           (void) CloseBlob(image);
01516           image->blob->exempt=MagickTrue;
01517           *image->filename='\0';
01518           status=WriteImage(blob_info,image,exception);
01519           if ((status != MagickFalse) && (image->blob->length != 0))
01520             {
01521               *length=image->blob->length;
01522               blob=DetachBlob(image->blob);
01523               blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
01524                 sizeof(*blob));
01525             }
01526         }
01527     }
01528   else
01529     {
01530       char
01531         unique[MaxTextExtent];
01532 
01533       int
01534         file;
01535 
01536       /*
01537         Write file to disk in blob image format.
01538       */
01539       file=AcquireUniqueFileResource(unique);
01540       if (file == -1)
01541         {
01542           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
01543             image_info->filename);
01544         }
01545       else
01546         {
01547           blob_info->file=fdopen(file,"wb");
01548           if (blob_info->file != (FILE *) NULL)
01549             {
01550               (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
01551                 image->magick,unique);
01552               status=WriteImage(blob_info,image,exception);
01553               (void) fclose(blob_info->file);
01554               if (status != MagickFalse)
01555                 blob=FileToBlob(image->filename,~0UL,length,exception);
01556             }
01557           (void) RelinquishUniqueFileResource(unique);
01558         }
01559     }
01560   blob_info=DestroyImageInfo(blob_info);
01561   return(blob);
01562 }
01563 
01564 /*
01565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01566 %                                                                             %
01567 %                                                                             %
01568 %                                                                             %
01569 %   I m a g e T o F i l e                                                     %
01570 %                                                                             %
01571 %                                                                             %
01572 %                                                                             %
01573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01574 %
01575 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
01576 %  occurs otherwise MagickTrue.
01577 %
01578 %  The format of the ImageToFile method is:
01579 %
01580 %       MagickBooleanType ImageToFile(Image *image,char *filename,
01581 %         ExceptionInfo *exception)
01582 %
01583 %  A description of each parameter follows:
01584 %
01585 %    o image: the image.
01586 %
01587 %    o filename: Write the image to this file.
01588 %
01589 %    o exception: return any errors or warnings in this structure.
01590 %
01591 */
01592 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
01593   ExceptionInfo *exception)
01594 {
01595   int
01596     file;
01597 
01598   register const unsigned char
01599     *p;
01600 
01601   register size_t
01602     i;
01603 
01604   size_t
01605     length,
01606     quantum;
01607 
01608   ssize_t
01609     count;
01610 
01611   struct stat
01612     file_info;
01613 
01614   unsigned char
01615     *buffer;
01616 
01617   assert(image != (Image *) NULL);
01618   assert(image->signature == MagickSignature);
01619   assert(image->blob != (BlobInfo *) NULL);
01620   assert(image->blob->type != UndefinedStream);
01621   if (image->debug != MagickFalse)
01622     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
01623   assert(filename != (const char *) NULL);
01624   if (*filename == '\0')
01625     file=AcquireUniqueFileResource(filename);
01626   else
01627     if (LocaleCompare(filename,"-") == 0)
01628       file=fileno(stdout);
01629     else
01630       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
01631   if (file == -1)
01632     {
01633       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
01634       return(MagickFalse);
01635     }
01636   quantum=(size_t) MagickMaxBufferExtent;
01637   if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
01638     quantum=(size_t) MagickMin((MagickSizeType) file_info.st_size,
01639       MagickMaxBufferExtent);
01640   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
01641   if (buffer == (unsigned char *) NULL)
01642     {
01643       file=close(file)-1;
01644       (void) ThrowMagickException(exception,GetMagickModule(),
01645         ResourceLimitError,"MemoryAllocationError","`%s'",filename);
01646       return(MagickFalse);
01647     }
01648   length=0;
01649   p=ReadBlobStream(image,quantum,buffer,&count);
01650   for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
01651   {
01652     length=(size_t) count;
01653     for (i=0; i < length; i+=count)
01654     {
01655       count=write(file,p+i,(size_t) (length-i));
01656       if (count <= 0)
01657         {
01658           count=0;
01659           if (errno != EINTR)
01660             break;
01661         }
01662     }
01663     if (i < length)
01664       break;
01665   }
01666   if (LocaleCompare(filename,"-") != 0)
01667     file=close(file);
01668   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
01669   if ((file == -1) || (i < length))
01670     {
01671       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
01672       return(MagickFalse);
01673     }
01674   return(MagickTrue);
01675 }
01676 
01677 /*
01678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01679 %                                                                             %
01680 %                                                                             %
01681 %                                                                             %
01682 %   I m a g e s T o B l o b                                                   %
01683 %                                                                             %
01684 %                                                                             %
01685 %                                                                             %
01686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01687 %
01688 %  ImagesToBlob() implements direct to memory image formats.  It returns the
01689 %  image sequence as a blob and its length.  The magick member of the ImageInfo
01690 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
01691 %
01692 %  Note, some image formats do not permit multiple images to the same image
01693 %  stream (e.g. JPEG).  in this instance, just the first image of the
01694 %  sequence is returned as a blob.
01695 %
01696 %  The format of the ImagesToBlob method is:
01697 %
01698 %      unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
01699 %        size_t *length,ExceptionInfo *exception)
01700 %
01701 %  A description of each parameter follows:
01702 %
01703 %    o image_info: the image info.
01704 %
01705 %    o images: the image list.
01706 %
01707 %    o length: This pointer to a size_t integer sets the initial length of the
01708 %      blob.  On return, it reflects the actual length of the blob.
01709 %
01710 %    o exception: return any errors or warnings in this structure.
01711 %
01712 */
01713 MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
01714   Image *images,size_t *length,ExceptionInfo *exception)
01715 {
01716   const MagickInfo
01717     *magick_info;
01718 
01719   ImageInfo
01720     *blob_info;
01721 
01722   MagickBooleanType
01723     status;
01724 
01725   unsigned char
01726     *blob;
01727 
01728   assert(image_info != (const ImageInfo *) NULL);
01729   assert(image_info->signature == MagickSignature);
01730   if (image_info->debug != MagickFalse)
01731     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01732       image_info->filename);
01733   assert(images != (Image *) NULL);
01734   assert(images->signature == MagickSignature);
01735   assert(exception != (ExceptionInfo *) NULL);
01736   *length=0;
01737   blob=(unsigned char *) NULL;
01738   blob_info=CloneImageInfo(image_info);
01739   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
01740     exception);
01741   if (*blob_info->magick != '\0')
01742     (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
01743   if (blob_info->adjoin == MagickFalse)
01744     {
01745       blob_info=DestroyImageInfo(blob_info);
01746       return(ImageToBlob(image_info,images,length,exception));
01747     }
01748   magick_info=GetMagickInfo(images->magick,exception);
01749   if (magick_info == (const MagickInfo *) NULL)
01750     {
01751       (void) ThrowMagickException(exception,GetMagickModule(),
01752         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
01753         images->filename);
01754       return(blob);
01755     }
01756   (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
01757   if (GetMagickBlobSupport(magick_info) != MagickFalse)
01758     {
01759       /*
01760         Native blob support for this images format.
01761       */
01762       blob_info->length=0;
01763       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
01764         sizeof(unsigned char));
01765       if (blob_info->blob == (void *) NULL)
01766         (void) ThrowMagickException(exception,GetMagickModule(),
01767           ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
01768       else
01769         {
01770           images->blob->exempt=MagickTrue;
01771           *images->filename='\0';
01772           status=WriteImages(blob_info,images,images->filename,exception);
01773           if ((status != MagickFalse) && (images->blob->length != 0))
01774             {
01775               *length=images->blob->length;
01776               blob=DetachBlob(images->blob);
01777               blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
01778                 sizeof(*blob));
01779             }
01780         }
01781     }
01782   else
01783     {
01784       char
01785         filename[MaxTextExtent],
01786         unique[MaxTextExtent];
01787 
01788       int
01789         file;
01790 
01791       /*
01792         Write file to disk in blob images format.
01793       */
01794       file=AcquireUniqueFileResource(unique);
01795       if (file == -1)
01796         {
01797           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
01798             image_info->filename);
01799         }
01800       else
01801         {
01802           blob_info->file=fdopen(file,"wb");
01803           if (blob_info->file != (FILE *) NULL)
01804             {
01805               (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
01806                 images->magick,unique);
01807               status=WriteImages(blob_info,images,filename,exception);
01808               (void) fclose(blob_info->file);
01809               if (status != MagickFalse)
01810                 blob=FileToBlob(images->filename,~0UL,length,exception);
01811             }
01812           (void) RelinquishUniqueFileResource(unique);
01813         }
01814     }
01815   blob_info=DestroyImageInfo(blob_info);
01816   return(blob);
01817 }
01818 /*
01819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01820 %                                                                             %
01821 %                                                                             %
01822 %                                                                             %
01823 %   I n j e c t I m a g e B l o b                                             %
01824 %                                                                             %
01825 %                                                                             %
01826 %                                                                             %
01827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01828 %
01829 %  InjectImageBlob() injects the image with a copy of itself in the specified
01830 %  format (e.g. inject JPEG into a PDF image).
01831 %
01832 %  The format of the InjectImageBlob method is:
01833 %
01834 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
01835 %        Image *image,Image *inject_image,const char *format,
01836 %        ExceptionInfo *exception)
01837 %
01838 %  A description of each parameter follows:
01839 %
01840 %    o image_info: the image info..
01841 %
01842 %    o image: the image.
01843 %
01844 %    o inject_image: inject into the image stream.
01845 %
01846 %    o format: the image format.
01847 %
01848 %    o exception: return any errors or warnings in this structure.
01849 %
01850 */
01851 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
01852   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
01853 {
01854   char
01855     filename[MaxTextExtent];
01856 
01857   FILE
01858     *unique_file;
01859 
01860   Image
01861     *byte_image;
01862 
01863   ImageInfo
01864     *write_info;
01865 
01866   int
01867     file;
01868 
01869   MagickBooleanType
01870     status;
01871 
01872   register ssize_t
01873     i;
01874 
01875   size_t
01876     quantum;
01877 
01878   ssize_t
01879     count;
01880 
01881   struct stat
01882     file_info;
01883 
01884   unsigned char
01885     *buffer;
01886 
01887   /*
01888     Write inject image to a temporary file.
01889   */
01890   assert(image_info != (ImageInfo *) NULL);
01891   assert(image_info->signature == MagickSignature);
01892   assert(image != (Image *) NULL);
01893   assert(image->signature == MagickSignature);
01894   if (image->debug != MagickFalse)
01895     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01896   assert(inject_image != (Image *) NULL);
01897   assert(inject_image->signature == MagickSignature);
01898   assert(exception != (ExceptionInfo *) NULL);
01899   unique_file=(FILE *) NULL;
01900   file=AcquireUniqueFileResource(filename);
01901   if (file != -1)
01902     unique_file=fdopen(file,"wb");
01903   if ((file == -1) || (unique_file == (FILE *) NULL))
01904     {
01905       (void) CopyMagickString(image->filename,filename,MaxTextExtent);
01906       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
01907         image->filename);
01908       return(MagickFalse);
01909     }
01910   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
01911   if (byte_image == (Image *) NULL)
01912     {
01913       (void) fclose(unique_file);
01914       (void) RelinquishUniqueFileResource(filename);
01915       return(MagickFalse);
01916     }
01917   (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
01918     filename);
01919   DestroyBlob(byte_image);
01920   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
01921   write_info=CloneImageInfo(image_info);
01922   SetImageInfoFile(write_info,unique_file);
01923   status=WriteImage(write_info,byte_image,exception);
01924   write_info=DestroyImageInfo(write_info);
01925   byte_image=DestroyImage(byte_image);
01926   (void) fclose(unique_file);
01927   if (status == MagickFalse)
01928     {
01929       (void) RelinquishUniqueFileResource(filename);
01930       return(MagickFalse);
01931     }
01932   /*
01933     Inject into image stream.
01934   */
01935   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
01936   if (file == -1)
01937     {
01938       (void) RelinquishUniqueFileResource(filename);
01939       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
01940         image_info->filename);
01941       return(MagickFalse);
01942     }
01943   quantum=(size_t) MagickMaxBufferExtent;
01944   if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0))
01945     quantum=(size_t) MagickMin(file_info.st_size,MagickMaxBufferExtent);
01946   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
01947   if (buffer == (unsigned char *) NULL)
01948     {
01949       (void) RelinquishUniqueFileResource(filename);
01950       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
01951         image->filename);
01952     }
01953   for (i=0; ; i+=count)
01954   {
01955     count=(ssize_t) read(file,buffer,quantum);
01956     if (count <= 0)
01957       {
01958         count=0;
01959         if (errno != EINTR)
01960           break;
01961       }
01962     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
01963       MagickFalse;
01964   }
01965   file=close(file);
01966   if (file == -1)
01967     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
01968   (void) RelinquishUniqueFileResource(filename);
01969   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
01970   return(status);
01971 }
01972 
01973 /*
01974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01975 %                                                                             %
01976 %                                                                             %
01977 %                                                                             %
01978 +   I s B l o b E x e m p t                                                   %
01979 %                                                                             %
01980 %                                                                             %
01981 %                                                                             %
01982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01983 %
01984 %  IsBlobExempt() returns true if the blob is exempt.
01985 %
01986 %  The format of the IsBlobExempt method is:
01987 %
01988 %       MagickBooleanType IsBlobExempt(const Image *image)
01989 %
01990 %  A description of each parameter follows:
01991 %
01992 %    o image: the image.
01993 %
01994 */
01995 MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
01996 {
01997   assert(image != (const Image *) NULL);
01998   assert(image->signature == MagickSignature);
01999   if (image->debug != MagickFalse)
02000     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02001   return(image->blob->exempt);
02002 }
02003 
02004 /*
02005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02006 %                                                                             %
02007 %                                                                             %
02008 %                                                                             %
02009 +   I s B l o b S e e k a b l e                                               %
02010 %                                                                             %
02011 %                                                                             %
02012 %                                                                             %
02013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02014 %
02015 %  IsBlobSeekable() returns true if the blob is seekable.
02016 %
02017 %  The format of the IsBlobSeekable method is:
02018 %
02019 %       MagickBooleanType IsBlobSeekable(const Image *image)
02020 %
02021 %  A description of each parameter follows:
02022 %
02023 %    o image: the image.
02024 %
02025 */
02026 MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
02027 {
02028   MagickBooleanType
02029     seekable;
02030 
02031   assert(image != (const Image *) NULL);
02032   assert(image->signature == MagickSignature);
02033   if (image->debug != MagickFalse)
02034     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02035   switch (image->blob->type)
02036   {
02037     case FileStream:
02038     case BlobStream:
02039     case ZipStream:
02040     {
02041       seekable=MagickTrue;
02042       break;
02043     }
02044     default:
02045     {
02046       seekable=MagickFalse;
02047       break;
02048     }
02049   }
02050   return(seekable);
02051 }
02052 
02053 /*
02054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02055 %                                                                             %
02056 %                                                                             %
02057 %                                                                             %
02058 +   I s B l o b T e m p o r a r y                                             %
02059 %                                                                             %
02060 %                                                                             %
02061 %                                                                             %
02062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02063 %
02064 %  IsBlobTemporary() returns true if the blob is temporary.
02065 %
02066 %  The format of the IsBlobTemporary method is:
02067 %
02068 %       MagickBooleanType IsBlobTemporary(const Image *image)
02069 %
02070 %  A description of each parameter follows:
02071 %
02072 %    o image: the image.
02073 %
02074 */
02075 MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
02076 {
02077   assert(image != (const Image *) NULL);
02078   assert(image->signature == MagickSignature);
02079   if (image->debug != MagickFalse)
02080     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02081   return(image->blob->temporary);
02082 }
02083 
02084 /*
02085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02086 %                                                                             %
02087 %                                                                             %
02088 %                                                                             %
02089 +  M a p B l o b                                                              %
02090 %                                                                             %
02091 %                                                                             %
02092 %                                                                             %
02093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02094 %
02095 %  MapBlob() creates a mapping from a file to a binary large object.
02096 %
02097 %  The format of the MapBlob method is:
02098 %
02099 %      unsigned char *MapBlob(int file,const MapMode mode,
02100 %        const MagickOffsetType offset,const size_t length)
02101 %
02102 %  A description of each parameter follows:
02103 %
02104 %    o file: map this file descriptor.
02105 %
02106 %    o mode: ReadMode, WriteMode, or IOMode.
02107 %
02108 %    o offset: starting at this offset within the file.
02109 %
02110 %    o length: the length of the mapping is returned in this pointer.
02111 %
02112 */
02113 MagickExport unsigned char *MapBlob(int file,const MapMode mode,
02114   const MagickOffsetType offset,const size_t length)
02115 {
02116 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
02117   int
02118     flags,
02119     protection;
02120 
02121   unsigned char
02122     *map;
02123 
02124   /*
02125     Map file.
02126   */
02127   flags=0;
02128   if (file == -1)
02129 #if defined(MAP_ANONYMOUS)
02130     flags|=MAP_ANONYMOUS;
02131 #else
02132     return((unsigned char *) NULL);
02133 #endif
02134   switch (mode)
02135   {
02136     case ReadMode:
02137     default:
02138     {
02139       protection=PROT_READ;
02140       flags|=MAP_PRIVATE;
02141       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
02142         (off_t) offset);
02143       break;
02144     }
02145     case WriteMode:
02146     {
02147       protection=PROT_WRITE;
02148       flags|=MAP_SHARED;
02149       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
02150         (off_t) offset);
02151 #if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
02152       (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
02153         POSIX_MADV_WILLNEED);
02154 #endif
02155       break;
02156     }
02157     case IOMode:
02158     {
02159       protection=PROT_READ | PROT_WRITE;
02160       flags|=MAP_SHARED;
02161       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
02162         (off_t) offset);
02163       break;
02164     }
02165   }
02166   if (map == (unsigned char *) MAP_FAILED)
02167     return((unsigned char *) NULL);
02168   return(map);
02169 #else
02170   (void) file;
02171   (void) mode;
02172   (void) offset;
02173   (void) length;
02174   return((unsigned char *) NULL);
02175 #endif
02176 }
02177 
02178 /*
02179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02180 %                                                                             %
02181 %                                                                             %
02182 %                                                                             %
02183 +  M S B O r d e r L o n g                                                    %
02184 %                                                                             %
02185 %                                                                             %
02186 %                                                                             %
02187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02188 %
02189 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
02190 %  most-significant byte first.
02191 %
02192 %  The format of the MSBOrderLong method is:
02193 %
02194 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
02195 %
02196 %  A description of each parameter follows.
02197 %
02198 %   o  buffer:  Specifies a pointer to a buffer of integers.
02199 %
02200 %   o  length:  Specifies the length of the buffer.
02201 %
02202 */
02203 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
02204 {
02205   int
02206     c;
02207 
02208   register unsigned char
02209     *p,
02210     *q;
02211 
02212   assert(buffer != (unsigned char *) NULL);
02213   q=buffer+length;
02214   while (buffer < q)
02215   {
02216     p=buffer+3;
02217     c=(int) (*p);
02218     *p=(*buffer);
02219     *buffer++=(unsigned char) c;
02220     p=buffer+1;
02221     c=(int) (*p);
02222     *p=(*buffer);
02223     *buffer++=(unsigned char) c;
02224     buffer+=2;
02225   }
02226 }
02227 
02228 /*
02229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02230 %                                                                             %
02231 %                                                                             %
02232 %                                                                             %
02233 +  M S B O r d e r S h o r t                                                  %
02234 %                                                                             %
02235 %                                                                             %
02236 %                                                                             %
02237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02238 %
02239 %  MSBOrderShort() converts a least-significant byte first buffer of integers
02240 %  to most-significant byte first.
02241 %
02242 %  The format of the MSBOrderShort method is:
02243 %
02244 %      void MSBOrderShort(unsigned char *p,const size_t length)
02245 %
02246 %  A description of each parameter follows.
02247 %
02248 %   o  p:  Specifies a pointer to a buffer of integers.
02249 %
02250 %   o  length:  Specifies the length of the buffer.
02251 %
02252 */
02253 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
02254 {
02255   int
02256     c;
02257 
02258   register unsigned char
02259     *q;
02260 
02261   assert(p != (unsigned char *) NULL);
02262   q=p+length;
02263   while (p < q)
02264   {
02265     c=(int) (*p);
02266     *p=(*(p+1));
02267     p++;
02268     *p++=(unsigned char) c;
02269   }
02270 }
02271 
02272 /*
02273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02274 %                                                                             %
02275 %                                                                             %
02276 %                                                                             %
02277 +   O p e n B l o b                                                           %
02278 %                                                                             %
02279 %                                                                             %
02280 %                                                                             %
02281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02282 %
02283 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
02284 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
02285 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
02286 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
02287 %  from a system command.
02288 %
02289 %  The format of the OpenBlob method is:
02290 %
02291 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
02292 %        const BlobMode mode,ExceptionInfo *exception)
02293 %
02294 %  A description of each parameter follows:
02295 %
02296 %    o image_info: the image info.
02297 %
02298 %    o image: the image.
02299 %
02300 %    o mode: the mode for opening the file.
02301 %
02302 */
02303 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
02304   Image *image,const BlobMode mode,ExceptionInfo *exception)
02305 {
02306   char
02307     extension[MaxTextExtent],
02308     filename[MaxTextExtent];
02309 
02310   const char
02311     *type;
02312 
02313   MagickBooleanType
02314     status;
02315 
02316   PolicyRights
02317     rights;
02318 
02319   assert(image_info != (ImageInfo *) NULL);
02320   assert(image_info->signature == MagickSignature);
02321   if (image_info->debug != MagickFalse)
02322     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02323       image_info->filename);
02324   assert(image != (Image *) NULL);
02325   assert(image->signature == MagickSignature);
02326   if (image_info->blob != (void *) NULL)
02327     {
02328       if (image_info->stream != (StreamHandler) NULL)
02329         image->blob->stream=(StreamHandler) image_info->stream;
02330       AttachBlob(image->blob,image_info->blob,image_info->length);
02331       return(MagickTrue);
02332     }
02333   (void) DetachBlob(image->blob);
02334   switch (mode)
02335   {
02336     default: type="r"; break;
02337     case ReadBlobMode: type="r"; break;
02338     case ReadBinaryBlobMode: type="rb"; break;
02339     case WriteBlobMode: type="w"; break;
02340     case WriteBinaryBlobMode: type="w+b"; break;
02341     case AppendBlobMode: type="a"; break;
02342     case AppendBinaryBlobMode: type="a+b"; break;
02343   }
02344   if (*type != 'r')
02345     image->blob->synchronize=image_info->synchronize;
02346   if (image_info->stream != (StreamHandler) NULL)
02347     {
02348       image->blob->stream=(StreamHandler) image_info->stream;
02349       if (*type == 'w')
02350         {
02351           image->blob->type=FifoStream;
02352           return(MagickTrue);
02353         }
02354     }
02355   /*
02356     Open image file.
02357   */
02358   *filename='\0';
02359   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
02360   rights=ReadPolicyRights;
02361   if (*type == 'w')
02362     rights=WritePolicyRights;
02363   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
02364     {
02365       errno=EPERM;
02366       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
02367         "NotAuthorized","`%s'",filename);
02368       return(MagickFalse);
02369     }
02370   if ((LocaleCompare(filename,"-") == 0) ||
02371       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
02372     {
02373       image->blob->file=(*type == 'r') ? stdin : stdout;
02374 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
02375       if (strchr(type,'b') != (char *) NULL)
02376         setmode(_fileno(image->blob->file),_O_BINARY);
02377 #endif
02378       image->blob->type=StandardStream;
02379       image->blob->exempt=MagickTrue;
02380       return(MagickTrue);
02381     }
02382   if (LocaleNCompare(filename,"fd:",3) == 0)
02383     {
02384       char
02385         mode[MaxTextExtent];
02386 
02387       *mode=(*type);
02388       mode[1]='\0';
02389       image->blob->file=fdopen(StringToLong(filename+3),mode);
02390 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
02391       if (strchr(type,'b') != (char *) NULL)
02392         setmode(_fileno(image->blob->file),_O_BINARY);
02393 #endif
02394       image->blob->type=StandardStream;
02395       image->blob->exempt=MagickTrue;
02396       return(MagickTrue);
02397     }
02398 #if defined(MAGICKCORE_HAVE_POPEN)
02399   if (*filename == '|')
02400     {
02401       char
02402         mode[MaxTextExtent];
02403 
02404       /*
02405         Pipe image to or from a system command.
02406       */
02407 #if defined(SIGPIPE)
02408       if (*type == 'w')
02409         (void) signal(SIGPIPE,SIG_IGN);
02410 #endif
02411       *mode=(*type);
02412       mode[1]='\0';
02413       image->blob->file=(FILE *) popen_utf8(filename+1,mode);
02414       if (image->blob->file == (FILE *) NULL)
02415         {
02416           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
02417           return(MagickFalse);
02418         }
02419       image->blob->type=PipeStream;
02420       image->blob->exempt=MagickTrue;
02421       return(MagickTrue);
02422     }
02423 #endif
02424   status=GetPathAttributes(filename,&image->blob->properties);
02425 #if defined(S_ISFIFO)
02426   if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
02427     {
02428       image->blob->file=(FILE *) fopen_utf8(filename,type);
02429       if (image->blob->file == (FILE *) NULL)
02430         {
02431           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
02432           return(MagickFalse);
02433         }
02434       image->blob->type=FileStream;
02435       image->blob->exempt=MagickTrue;
02436       return(MagickTrue);
02437     }
02438 #endif
02439   GetPathComponent(image->filename,ExtensionPath,extension);
02440   if (*type == 'w')
02441     {
02442       (void) CopyMagickString(filename,image->filename,MaxTextExtent);
02443       if ((image_info->adjoin == MagickFalse) ||
02444           (strchr(filename,'%') != (char *) NULL))
02445         {
02446           /*
02447             Form filename for multi-part images.
02448           */
02449           (void) InterpretImageFilename(image_info,image,image->filename,(int)
02450             image->scene,filename,exception);
02451           if ((LocaleCompare(filename,image->filename) == 0) &&
02452               ((GetPreviousImageInList(image) != (Image *) NULL) ||
02453                (GetNextImageInList(image) != (Image *) NULL)))
02454             {
02455               char
02456                 path[MaxTextExtent];
02457 
02458               GetPathComponent(image->filename,RootPath,path);
02459               if (*extension == '\0')
02460                 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
02461                   path,(double) image->scene);
02462               else
02463                 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
02464                   path,(double) image->scene,extension);
02465             }
02466           (void) CopyMagickString(image->filename,filename,MaxTextExtent);
02467 #if defined(macintosh)
02468           SetApplicationType(filename,image_info->magick,'8BIM');
02469 #endif
02470         }
02471     }
02472   if (image_info->file != (FILE *) NULL)
02473     {
02474       image->blob->file=image_info->file;
02475       image->blob->type=FileStream;
02476       image->blob->exempt=MagickTrue;
02477     }
02478   else
02479     if (*type == 'r')
02480       {
02481         image->blob->file=(FILE *) fopen_utf8(filename,type);
02482         if (image->blob->file != (FILE *) NULL)
02483           {
02484             size_t
02485               count;
02486 
02487             unsigned char
02488               magick[3];
02489 
02490             image->blob->type=FileStream;
02491 #if defined(MAGICKCORE_HAVE_SETVBUF)
02492             (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,16384);
02493 #endif
02494             (void) ResetMagickMemory(magick,0,sizeof(magick));
02495             count=fread(magick,1,sizeof(magick),image->blob->file);
02496             (void) rewind(image->blob->file);
02497             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
02498                "  read %.20g magic header bytes",(double) count);
02499 #if defined(MAGICKCORE_ZLIB_DELEGATE)
02500             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
02501                 ((int) magick[2] == 0x08))
02502               {
02503                 (void) fclose(image->blob->file);
02504                 image->blob->gzfile=gzopen(filename,type);
02505                 if (image->blob->gzfile != (gzFile) NULL)
02506                   image->blob->type=ZipStream;
02507                }
02508 #endif
02509 #if defined(MAGICKCORE_BZLIB_DELEGATE)
02510             if (strncmp((char *) magick,"BZh",3) == 0)
02511               {
02512                 (void) fclose(image->blob->file);
02513                 image->blob->bzfile=BZ2_bzopen(filename,type);
02514                 if (image->blob->bzfile != (BZFILE *) NULL)
02515                   image->blob->type=BZipStream;
02516               }
02517 #endif
02518             if (image->blob->type == FileStream)
02519               {
02520                 const MagickInfo
02521                   *magick_info;
02522 
02523                 ExceptionInfo
02524                   *sans_exception;
02525 
02526                 struct stat
02527                   *properties;
02528 
02529                 sans_exception=AcquireExceptionInfo();
02530                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
02531                 sans_exception=DestroyExceptionInfo(sans_exception);
02532                 properties=(&image->blob->properties);
02533                 if ((magick_info != (const MagickInfo *) NULL) &&
02534                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
02535                     (properties->st_size <= MagickMaxBufferExtent))
02536                   {
02537                     size_t
02538                       length;
02539 
02540                     void
02541                       *blob;
02542 
02543                     length=(size_t) properties->st_size;
02544                     blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
02545                     if (blob != (void *) NULL)
02546                       {
02547                         /*
02548                           Format supports blobs-- use memory-mapped I/O.
02549                         */
02550                         if (image_info->file != (FILE *) NULL)
02551                           image->blob->exempt=MagickFalse;
02552                         else
02553                           {
02554                             (void) fclose(image->blob->file);
02555                             image->blob->file=(FILE *) NULL;
02556                           }
02557                         AttachBlob(image->blob,blob,length);
02558                         image->blob->mapped=MagickTrue;
02559                       }
02560                   }
02561               }
02562           }
02563         }
02564       else
02565 #if defined(MAGICKCORE_ZLIB_DELEGATE)
02566         if ((LocaleCompare(extension,"Z") == 0) ||
02567             (LocaleCompare(extension,"gz") == 0) ||
02568             (LocaleCompare(extension,"wmz") == 0) ||
02569             (LocaleCompare(extension,"svgz") == 0))
02570           {
02571             if (mode == WriteBinaryBlobMode)
02572               type="wb";
02573             image->blob->gzfile=gzopen(filename,type);
02574             if (image->blob->gzfile != (gzFile) NULL)
02575               image->blob->type=ZipStream;
02576           }
02577         else
02578 #endif
02579 #if defined(MAGICKCORE_BZLIB_DELEGATE)
02580           if (LocaleCompare(extension,"bz2") == 0)
02581             {
02582               image->blob->bzfile=BZ2_bzopen(filename,type);
02583               if (image->blob->bzfile != (BZFILE *) NULL)
02584                 image->blob->type=BZipStream;
02585             }
02586           else
02587 #endif
02588             {
02589               image->blob->file=(FILE *) fopen_utf8(filename,type);
02590               if (image->blob->file != (FILE *) NULL)
02591                 {
02592                   image->blob->type=FileStream;
02593 #if defined(MAGICKCORE_HAVE_SETVBUF)
02594                   (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,
02595                     16384);
02596 #endif
02597                 }
02598        }
02599   image->blob->status=MagickFalse;
02600   if (image->blob->type != UndefinedStream)
02601     image->blob->size=GetBlobSize(image);
02602   else
02603     {
02604       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
02605       return(MagickFalse);
02606     }
02607   return(MagickTrue);
02608 }
02609 
02610 /*
02611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02612 %                                                                             %
02613 %                                                                             %
02614 %                                                                             %
02615 +   P i n g B l o b                                                           %
02616 %                                                                             %
02617 %                                                                             %
02618 %                                                                             %
02619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02620 %
02621 %  PingBlob() returns all the attributes of an image or image sequence except
02622 %  for the pixels.  It is much faster and consumes far less memory than
02623 %  BlobToImage().  On failure, a NULL image is returned and exception
02624 %  describes the reason for the failure.
02625 %
02626 %  The format of the PingBlob method is:
02627 %
02628 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
02629 %        const size_t length,ExceptionInfo *exception)
02630 %
02631 %  A description of each parameter follows:
02632 %
02633 %    o image_info: the image info.
02634 %
02635 %    o blob: the address of a character stream in one of the image formats
02636 %      understood by ImageMagick.
02637 %
02638 %    o length: This size_t integer reflects the length in bytes of the blob.
02639 %
02640 %    o exception: return any errors or warnings in this structure.
02641 %
02642 */
02643 
02644 #if defined(__cplusplus) || defined(c_plusplus)
02645 extern "C" {
02646 #endif
02647 
02648 static size_t PingStream(const Image *magick_unused(image),
02649   const void *magick_unused(pixels),const size_t columns)
02650 {
02651   return(columns);
02652 }
02653 
02654 #if defined(__cplusplus) || defined(c_plusplus)
02655 }
02656 #endif
02657 
02658 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
02659   const size_t length,ExceptionInfo *exception)
02660 {
02661   Image
02662     *image;
02663 
02664   ImageInfo
02665     *ping_info;
02666 
02667   assert(image_info != (ImageInfo *) NULL);
02668   assert(image_info->signature == MagickSignature);
02669   if (image_info->debug != MagickFalse)
02670     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02671       image_info->filename);
02672   assert(exception != (ExceptionInfo *) NULL);
02673   if ((blob == (const void *) NULL) || (length == 0))
02674     {
02675       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
02676         "UnrecognizedImageFormat","`%s'",image_info->magick);
02677       return((Image *) NULL);
02678     }
02679   ping_info=CloneImageInfo(image_info);
02680   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
02681   if (ping_info->blob == (const void *) NULL)
02682     {
02683       (void) ThrowMagickException(exception,GetMagickModule(),
02684         ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
02685       return((Image *) NULL);
02686     }
02687   (void) memcpy(ping_info->blob,blob,length);
02688   ping_info->length=length;
02689   ping_info->ping=MagickTrue;
02690   image=ReadStream(ping_info,&PingStream,exception);
02691   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
02692   ping_info=DestroyImageInfo(ping_info);
02693   return(image);
02694 }
02695 
02696 /*
02697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02698 %                                                                             %
02699 %                                                                             %
02700 %                                                                             %
02701 +  R e a d B l o b                                                            %
02702 %                                                                             %
02703 %                                                                             %
02704 %                                                                             %
02705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02706 %
02707 %  ReadBlob() reads data from the blob or image file and returns it.  It
02708 %  returns the number of bytes read.
02709 %
02710 %  The format of the ReadBlob method is:
02711 %
02712 %      ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
02713 %
02714 %  A description of each parameter follows:
02715 %
02716 %    o image: the image.
02717 %
02718 %    o length:  Specifies an integer representing the number of bytes to read
02719 %      from the file.
02720 %
02721 %    o data:  Specifies an area to place the information requested from the
02722 %      file.
02723 %
02724 */
02725 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
02726   unsigned char *data)
02727 {
02728   int
02729     c;
02730 
02731   register unsigned char
02732     *q;
02733 
02734   ssize_t
02735     count;
02736 
02737   assert(image != (Image *) NULL);
02738   assert(image->signature == MagickSignature);
02739   assert(image->blob != (BlobInfo *) NULL);
02740   assert(image->blob->type != UndefinedStream);
02741   if (length == 0)
02742     return(0);
02743   assert(data != (void *) NULL);
02744   count=0;
02745   q=data;
02746   switch (image->blob->type)
02747   {
02748     case UndefinedStream:
02749       break;
02750     case FileStream:
02751     case StandardStream:
02752     case PipeStream:
02753     {
02754       switch (length)
02755       {
02756         default:
02757         {
02758           count=(ssize_t) fread(q,1,length,image->blob->file);
02759           break;
02760         }
02761         case 2:
02762         {
02763           c=getc(image->blob->file);
02764           if (c == EOF)
02765             break;
02766           *q++=(unsigned char) c;
02767           count++;
02768         }
02769         case 1:
02770         {
02771           c=getc(image->blob->file);
02772           if (c == EOF)
02773             break;
02774           *q++=(unsigned char) c;
02775           count++;
02776         }
02777         case 0:
02778           break;
02779       }
02780       break;
02781     }
02782     case ZipStream:
02783     {
02784 #if defined(MAGICKCORE_ZLIB_DELEGATE)
02785       switch (length)
02786       {
02787         default:
02788         {
02789           count=(ssize_t) gzread(image->blob->gzfile,q,(unsigned int) length);
02790           break;
02791         }
02792         case 2:
02793         {
02794           c=gzgetc(image->blob->gzfile);
02795           if (c == EOF)
02796             break;
02797           *q++=(unsigned char) c;
02798           count++;
02799         }
02800         case 1:
02801         {
02802           c=gzgetc(image->blob->gzfile);
02803           if (c == EOF)
02804             break;
02805           *q++=(unsigned char) c;
02806           count++;
02807         }
02808         case 0:
02809           break;
02810       }
02811 #endif
02812       break;
02813     }
02814     case BZipStream:
02815     {
02816 #if defined(MAGICKCORE_BZLIB_DELEGATE)
02817       count=(ssize_t) BZ2_bzread(image->blob->bzfile,q,(int) length);
02818 #endif
02819       break;
02820     }
02821     case FifoStream:
02822       break;
02823     case BlobStream:
02824     {
02825       register const unsigned char
02826         *p;
02827 
02828       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
02829         {
02830           image->blob->eof=MagickTrue;
02831           break;
02832         }
02833       p=image->blob->data+image->blob->offset;
02834       count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
02835       image->blob->offset+=count;
02836       if (count != (ssize_t) length)
02837         image->blob->eof=MagickTrue;
02838       (void) memcpy(q,p,(size_t) count);
02839       break;
02840     }
02841   }
02842   return(count);
02843 }
02844 
02845 /*
02846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02847 %                                                                             %
02848 %                                                                             %
02849 %                                                                             %
02850 +  R e a d B l o b B y t e                                                    %
02851 %                                                                             %
02852 %                                                                             %
02853 %                                                                             %
02854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02855 %
02856 %  ReadBlobByte() reads a single byte from the image file and returns it.
02857 %
02858 %  The format of the ReadBlobByte method is:
02859 %
02860 %      int ReadBlobByte(Image *image)
02861 %
02862 %  A description of each parameter follows.
02863 %
02864 %    o image: the image.
02865 %
02866 */
02867 MagickExport int ReadBlobByte(Image *image)
02868 {
02869   register const unsigned char
02870     *p;
02871 
02872   ssize_t
02873     count;
02874 
02875   unsigned char
02876     buffer[1];
02877 
02878   assert(image != (Image *) NULL);
02879   assert(image->signature == MagickSignature);
02880   p=ReadBlobStream(image,1,buffer,&count);
02881   if (count != 1)
02882     return(EOF);
02883   return((int) (*p));
02884 }
02885 
02886 /*
02887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02888 %                                                                             %
02889 %                                                                             %
02890 %                                                                             %
02891 +  R e a d B l o b D o u b l e                                                %
02892 %                                                                             %
02893 %                                                                             %
02894 %                                                                             %
02895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02896 %
02897 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
02898 %  specified by the endian member of the image structure.
02899 %
02900 %  The format of the ReadBlobDouble method is:
02901 %
02902 %      double ReadBlobDouble(Image *image)
02903 %
02904 %  A description of each parameter follows.
02905 %
02906 %    o image: the image.
02907 %
02908 */
02909 MagickExport double ReadBlobDouble(Image *image)
02910 {
02911   union
02912   {
02913     MagickSizeType
02914       unsigned_value;
02915 
02916     double
02917       double_value;
02918   } quantum;
02919 
02920   quantum.double_value=0.0;
02921   quantum.unsigned_value=ReadBlobLongLong(image);
02922   return(quantum.double_value);
02923 }
02924 
02925 /*
02926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02927 %                                                                             %
02928 %                                                                             %
02929 %                                                                             %
02930 +  R e a d B l o b F l o a t                                                  %
02931 %                                                                             %
02932 %                                                                             %
02933 %                                                                             %
02934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02935 %
02936 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
02937 %  specified by the endian member of the image structure.
02938 %
02939 %  The format of the ReadBlobFloat method is:
02940 %
02941 %      float ReadBlobFloat(Image *image)
02942 %
02943 %  A description of each parameter follows.
02944 %
02945 %    o image: the image.
02946 %
02947 */
02948 MagickExport float ReadBlobFloat(Image *image)
02949 {
02950   union
02951   {
02952     unsigned int
02953       unsigned_value;
02954 
02955     float
02956       float_value;
02957   } quantum;
02958 
02959   quantum.float_value=0.0;
02960   quantum.unsigned_value=ReadBlobLong(image);
02961   return(quantum.float_value);
02962 }
02963 
02964 /*
02965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02966 %                                                                             %
02967 %                                                                             %
02968 %                                                                             %
02969 +  R e a d B l o b L o n g                                                    %
02970 %                                                                             %
02971 %                                                                             %
02972 %                                                                             %
02973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02974 %
02975 %  ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
02976 %  specified by the endian member of the image structure.
02977 %
02978 %  The format of the ReadBlobLong method is:
02979 %
02980 %      unsigned int ReadBlobLong(Image *image)
02981 %
02982 %  A description of each parameter follows.
02983 %
02984 %    o image: the image.
02985 %
02986 */
02987 MagickExport unsigned int ReadBlobLong(Image *image)
02988 {
02989   register const unsigned char
02990     *p;
02991 
02992   ssize_t
02993     count;
02994 
02995   unsigned char
02996     buffer[4];
02997 
02998   unsigned int
02999     value;
03000 
03001   assert(image != (Image *) NULL);
03002   assert(image->signature == MagickSignature);
03003   *buffer='\0';
03004   p=ReadBlobStream(image,4,buffer,&count);
03005   if (count != 4)
03006     return(0UL);
03007   if (image->endian == LSBEndian)
03008     {
03009       value=(unsigned int) (*p++);
03010       value|=((unsigned int) (*p++)) << 8;
03011       value|=((unsigned int) (*p++)) << 16;
03012       value|=((unsigned int) (*p++)) << 24;
03013       return(value);
03014     }
03015   value=((unsigned int) (*p++)) << 24;
03016   value|=((unsigned int) (*p++)) << 16;
03017   value|=((unsigned int) (*p++)) << 8;
03018   value|=((unsigned int) (*p++));
03019   return(value);
03020 }
03021 
03022 /*
03023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03024 %                                                                             %
03025 %                                                                             %
03026 %                                                                             %
03027 +  R e a d B l o b L o n g L o n g                                            %
03028 %                                                                             %
03029 %                                                                             %
03030 %                                                                             %
03031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03032 %
03033 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
03034 %  byte-order specified by the endian member of the image structure.
03035 %
03036 %  The format of the ReadBlobLongLong method is:
03037 %
03038 %      MagickSizeType ReadBlobLongLong(Image *image)
03039 %
03040 %  A description of each parameter follows.
03041 %
03042 %    o image: the image.
03043 %
03044 */
03045 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
03046 {
03047   MagickSizeType
03048     value;
03049 
03050   register const unsigned char
03051     *p;
03052 
03053   ssize_t
03054     count;
03055 
03056   unsigned char
03057     buffer[8];
03058 
03059   assert(image != (Image *) NULL);
03060   assert(image->signature == MagickSignature);
03061   *buffer='\0';
03062   p=ReadBlobStream(image,8,buffer,&count);
03063   if (count != 8)
03064     return(MagickULLConstant(0));
03065   if (image->endian == LSBEndian)
03066     {
03067       value=(MagickSizeType) (*p++);
03068       value|=((MagickSizeType) (*p++)) << 8;
03069       value|=((MagickSizeType) (*p++)) << 16;
03070       value|=((MagickSizeType) (*p++)) << 24;
03071       value|=((MagickSizeType) (*p++)) << 32;
03072       value|=((MagickSizeType) (*p++)) << 40;
03073       value|=((MagickSizeType) (*p++)) << 48;
03074       value|=((MagickSizeType) (*p++)) << 56;
03075       return(value & MagickULLConstant(0xffffffffffffffff));
03076     }
03077   value=((MagickSizeType) (*p++)) << 56;
03078   value|=((MagickSizeType) (*p++)) << 48;
03079   value|=((MagickSizeType) (*p++)) << 40;
03080   value|=((MagickSizeType) (*p++)) << 32;
03081   value|=((MagickSizeType) (*p++)) << 24;
03082   value|=((MagickSizeType) (*p++)) << 16;
03083   value|=((MagickSizeType) (*p++)) << 8;
03084   value|=((MagickSizeType) (*p++));
03085   return(value & MagickULLConstant(0xffffffffffffffff));
03086 }
03087 
03088 /*
03089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03090 %                                                                             %
03091 %                                                                             %
03092 %                                                                             %
03093 +  R e a d B l o b S h o r t                                                  %
03094 %                                                                             %
03095 %                                                                             %
03096 %                                                                             %
03097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03098 %
03099 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
03100 %  specified by the endian member of the image structure.
03101 %
03102 %  The format of the ReadBlobShort method is:
03103 %
03104 %      unsigned short ReadBlobShort(Image *image)
03105 %
03106 %  A description of each parameter follows.
03107 %
03108 %    o image: the image.
03109 %
03110 */
03111 MagickExport unsigned short ReadBlobShort(Image *image)
03112 {
03113   register const unsigned char
03114     *p;
03115 
03116   register unsigned int
03117     value;
03118 
03119   ssize_t
03120     count;
03121 
03122   unsigned char
03123     buffer[2];
03124 
03125   assert(image != (Image *) NULL);
03126   assert(image->signature == MagickSignature);
03127   *buffer='\0';
03128   p=ReadBlobStream(image,2,buffer,&count);
03129   if (count != 2)
03130     return((unsigned short) 0U);
03131   if (image->endian == LSBEndian)
03132     {
03133       value=(unsigned int) (*p++);
03134       value|=((unsigned int) (*p++)) << 8;
03135       return((unsigned short) (value & 0xffff));
03136     }
03137   value=(unsigned int) ((*p++) << 8);
03138   value|=(unsigned int) (*p++);
03139   return((unsigned short) (value & 0xffff));
03140 }
03141 
03142 /*
03143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03144 %                                                                             %
03145 %                                                                             %
03146 %                                                                             %
03147 +  R e a d B l o b L S B L o n g                                              %
03148 %                                                                             %
03149 %                                                                             %
03150 %                                                                             %
03151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03152 %
03153 %  ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
03154 %  least-significant byte first order.
03155 %
03156 %  The format of the ReadBlobLSBLong method is:
03157 %
03158 %      unsigned int ReadBlobLSBLong(Image *image)
03159 %
03160 %  A description of each parameter follows.
03161 %
03162 %    o image: the image.
03163 %
03164 */
03165 MagickExport unsigned int ReadBlobLSBLong(Image *image)
03166 {
03167   register const unsigned char
03168     *p;
03169 
03170   register unsigned int
03171     value;
03172 
03173   ssize_t
03174     count;
03175 
03176   unsigned char
03177     buffer[4];
03178 
03179   assert(image != (Image *) NULL);
03180   assert(image->signature == MagickSignature);
03181   *buffer='\0';
03182   p=ReadBlobStream(image,4,buffer,&count);
03183   if (count != 4)
03184     return(0U);
03185   value=(unsigned int) (*p++);
03186   value|=((unsigned int) (*p++)) << 8;
03187   value|=((unsigned int) (*p++)) << 16;
03188   value|=((unsigned int) (*p++)) << 24;
03189   return(value);
03190 }
03191 
03192 /*
03193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03194 %                                                                             %
03195 %                                                                             %
03196 %                                                                             %
03197 +  R e a d B l o b L S B S h o r t                                            %
03198 %                                                                             %
03199 %                                                                             %
03200 %                                                                             %
03201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03202 %
03203 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
03204 %  least-significant byte first order.
03205 %
03206 %  The format of the ReadBlobLSBShort method is:
03207 %
03208 %      unsigned short ReadBlobLSBShort(Image *image)
03209 %
03210 %  A description of each parameter follows.
03211 %
03212 %    o image: the image.
03213 %
03214 */
03215 MagickExport unsigned short ReadBlobLSBShort(Image *image)
03216 {
03217   register const unsigned char
03218     *p;
03219 
03220   register unsigned int
03221     value;
03222 
03223   ssize_t
03224     count;
03225 
03226   unsigned char
03227     buffer[2];
03228 
03229   assert(image != (Image *) NULL);
03230   assert(image->signature == MagickSignature);
03231   *buffer='\0';
03232   p=ReadBlobStream(image,2,buffer,&count);
03233   if (count != 2)
03234     return((unsigned short) 0U);
03235   value=(unsigned int) (*p++);
03236   value|=((unsigned int) ((*p++)) << 8);
03237   return((unsigned short) (value & 0xffff));
03238 }
03239 
03240 /*
03241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03242 %                                                                             %
03243 %                                                                             %
03244 %                                                                             %
03245 +  R e a d B l o b M S B L o n g                                              %
03246 %                                                                             %
03247 %                                                                             %
03248 %                                                                             %
03249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03250 %
03251 %  ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
03252 %  most-significant byte first order.
03253 %
03254 %  The format of the ReadBlobMSBLong method is:
03255 %
03256 %      unsigned int ReadBlobMSBLong(Image *image)
03257 %
03258 %  A description of each parameter follows.
03259 %
03260 %    o image: the image.
03261 %
03262 */
03263 MagickExport unsigned int ReadBlobMSBLong(Image *image)
03264 {
03265   register const unsigned char
03266     *p;
03267 
03268   register unsigned int
03269     value;
03270 
03271   ssize_t
03272     count;
03273 
03274   unsigned char
03275     buffer[4];
03276 
03277   assert(image != (Image *) NULL);
03278   assert(image->signature == MagickSignature);
03279   *buffer='\0';
03280   p=ReadBlobStream(image,4,buffer,&count);
03281   if (count != 4)
03282     return(0UL);
03283   value=((unsigned int) (*p++) << 24);
03284   value|=((unsigned int) (*p++) << 16);
03285   value|=((unsigned int) (*p++) << 8);
03286   value|=(unsigned int) (*p++);
03287   return(value);
03288 }
03289 
03290 /*
03291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03292 %                                                                             %
03293 %                                                                             %
03294 %                                                                             %
03295 +  R e a d B l o b M S B L o n g L o n g                                      %
03296 %                                                                             %
03297 %                                                                             %
03298 %                                                                             %
03299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03300 %
03301 %  ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
03302 %  most-significant byte first order.
03303 %
03304 %  The format of the ReadBlobMSBLongLong method is:
03305 %
03306 %      unsigned int ReadBlobMSBLongLong(Image *image)
03307 %
03308 %  A description of each parameter follows.
03309 %
03310 %    o image: the image.
03311 %
03312 */
03313 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
03314 {
03315   register const unsigned char
03316     *p;
03317 
03318   register MagickSizeType
03319     value;
03320 
03321   ssize_t
03322     count;
03323 
03324   unsigned char
03325     buffer[8];
03326 
03327   assert(image != (Image *) NULL);
03328   assert(image->signature == MagickSignature);
03329   *buffer='\0';
03330   p=ReadBlobStream(image,8,buffer,&count);
03331   if (count != 8)
03332     return(MagickULLConstant(0));
03333   value=((MagickSizeType) (*p++)) << 56;
03334   value|=((MagickSizeType) (*p++)) << 48;
03335   value|=((MagickSizeType) (*p++)) << 40;
03336   value|=((MagickSizeType) (*p++)) << 32;
03337   value|=((MagickSizeType) (*p++)) << 24;
03338   value|=((MagickSizeType) (*p++)) << 16;
03339   value|=((MagickSizeType) (*p++)) << 8;
03340   value|=((MagickSizeType) (*p++));
03341   return(value & MagickULLConstant(0xffffffffffffffff));
03342 }
03343 
03344 /*
03345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03346 %                                                                             %
03347 %                                                                             %
03348 %                                                                             %
03349 +  R e a d B l o b M S B S h o r t                                            %
03350 %                                                                             %
03351 %                                                                             %
03352 %                                                                             %
03353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03354 %
03355 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
03356 %  most-significant byte first order.
03357 %
03358 %  The format of the ReadBlobMSBShort method is:
03359 %
03360 %      unsigned short ReadBlobMSBShort(Image *image)
03361 %
03362 %  A description of each parameter follows.
03363 %
03364 %    o image: the image.
03365 %
03366 */
03367 MagickExport unsigned short ReadBlobMSBShort(Image *image)
03368 {
03369   register const unsigned char
03370     *p;
03371 
03372   register unsigned int
03373     value;
03374 
03375   ssize_t
03376     count;
03377 
03378   unsigned char
03379     buffer[2];
03380 
03381   assert(image != (Image *) NULL);
03382   assert(image->signature == MagickSignature);
03383   *buffer='\0';
03384   p=ReadBlobStream(image,2,buffer,&count);
03385   if (count != 2)
03386     return((unsigned short) 0U);
03387   value=(unsigned int) ((*p++) << 8);
03388   value|=(unsigned int) (*p++);
03389   return((unsigned short) (value & 0xffff));
03390 }
03391 
03392 /*
03393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03394 %                                                                             %
03395 %                                                                             %
03396 %                                                                             %
03397 +   R e a d B l o b S t r i n g                                               %
03398 %                                                                             %
03399 %                                                                             %
03400 %                                                                             %
03401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03402 %
03403 %  ReadBlobString() reads characters from a blob or file until a newline
03404 %  character is read or an end-of-file condition is encountered.
03405 %
03406 %  The format of the ReadBlobString method is:
03407 %
03408 %      char *ReadBlobString(Image *image,char *string)
03409 %
03410 %  A description of each parameter follows:
03411 %
03412 %    o image: the image.
03413 %
03414 %    o string: the address of a character buffer.
03415 %
03416 */
03417 MagickExport char *ReadBlobString(Image *image,char *string)
03418 {
03419   register const unsigned char
03420     *p;
03421 
03422   register ssize_t
03423     i;
03424 
03425   ssize_t
03426     count;
03427 
03428   unsigned char
03429     buffer[1];
03430 
03431   assert(image != (Image *) NULL);
03432   assert(image->signature == MagickSignature);
03433   for (i=0; i < (MaxTextExtent-1L); i++)
03434   {
03435     p=ReadBlobStream(image,1,buffer,&count);
03436     if (count != 1)
03437       {
03438         if (i == 0)
03439           return((char *) NULL);
03440         break;
03441       }
03442     string[i]=(char) (*p);
03443     if ((string[i] == '\r') || (string[i] == '\n'))
03444       break;
03445   }
03446   if (string[i] == '\r')
03447     (void) ReadBlobStream(image,1,buffer,&count);
03448   string[i]='\0';
03449   return(string);
03450 }
03451 
03452 /*
03453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03454 %                                                                             %
03455 %                                                                             %
03456 %                                                                             %
03457 +   R e f e r e n c e B l o b                                                 %
03458 %                                                                             %
03459 %                                                                             %
03460 %                                                                             %
03461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03462 %
03463 %  ReferenceBlob() increments the reference count associated with the pixel
03464 %  blob returning a pointer to the blob.
03465 %
03466 %  The format of the ReferenceBlob method is:
03467 %
03468 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
03469 %
03470 %  A description of each parameter follows:
03471 %
03472 %    o blob_info: the blob_info.
03473 %
03474 */
03475 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
03476 {
03477   assert(blob != (BlobInfo *) NULL);
03478   assert(blob->signature == MagickSignature);
03479   if (blob->debug != MagickFalse)
03480     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03481   LockSemaphoreInfo(blob->semaphore);
03482   blob->reference_count++;
03483   UnlockSemaphoreInfo(blob->semaphore);
03484   return(blob);
03485 }
03486 
03487 /*
03488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03489 %                                                                             %
03490 %                                                                             %
03491 %                                                                             %
03492 +  S e e k B l o b                                                            %
03493 %                                                                             %
03494 %                                                                             %
03495 %                                                                             %
03496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03497 %
03498 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
03499 %  and returns the resulting offset.
03500 %
03501 %  The format of the SeekBlob method is:
03502 %
03503 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
03504 %        const int whence)
03505 %
03506 %  A description of each parameter follows:
03507 %
03508 %    o image: the image.
03509 %
03510 %    o offset:  Specifies an integer representing the offset in bytes.
03511 %
03512 %    o whence:  Specifies an integer representing how the offset is
03513 %      treated relative to the beginning of the blob as follows:
03514 %
03515 %        SEEK_SET  Set position equal to offset bytes.
03516 %        SEEK_CUR  Set position to current location plus offset.
03517 %        SEEK_END  Set position to EOF plus offset.
03518 %
03519 */
03520 MagickExport MagickOffsetType SeekBlob(Image *image,
03521   const MagickOffsetType offset,const int whence)
03522 {
03523   assert(image != (Image *) NULL);
03524   assert(image->signature == MagickSignature);
03525   if (image->debug != MagickFalse)
03526     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03527   assert(image->blob != (BlobInfo *) NULL);
03528   assert(image->blob->type != UndefinedStream);
03529   switch (image->blob->type)
03530   {
03531     case UndefinedStream:
03532       break;
03533     case FileStream:
03534     {
03535       if (fseek(image->blob->file,offset,whence) < 0)
03536         return(-1);
03537       image->blob->offset=TellBlob(image);
03538       break;
03539     }
03540     case StandardStream:
03541     case PipeStream:
03542     case ZipStream:
03543     {
03544 #if defined(MAGICKCORE_ZLIB_DELEGATE)
03545       if (gzseek(image->blob->gzfile,(off_t) offset,whence) < 0)
03546         return(-1);
03547 #endif
03548       image->blob->offset=TellBlob(image);
03549       break;
03550     }
03551     case BZipStream:
03552       return(-1);
03553     case FifoStream:
03554       return(-1);
03555     case BlobStream:
03556     {
03557       switch (whence)
03558       {
03559         case SEEK_SET:
03560         default:
03561         {
03562           if (offset < 0)
03563             return(-1);
03564           image->blob->offset=offset;
03565           break;
03566         }
03567         case SEEK_CUR:
03568         {
03569           if ((image->blob->offset+offset) < 0)
03570             return(-1);
03571           image->blob->offset+=offset;
03572           break;
03573         }
03574         case SEEK_END:
03575         {
03576           if (((MagickOffsetType) image->blob->length+offset) < 0)
03577             return(-1);
03578           image->blob->offset=image->blob->length+offset;
03579           break;
03580         }
03581       }
03582       if (image->blob->offset <= (MagickOffsetType)
03583           ((off_t) image->blob->length))
03584         image->blob->eof=MagickFalse;
03585       else
03586         if (image->blob->mapped != MagickFalse)
03587           return(-1);
03588         else
03589           {
03590             image->blob->extent=(size_t) (image->blob->offset+
03591               image->blob->quantum);
03592             image->blob->data=(unsigned char *) ResizeQuantumMemory(
03593               image->blob->data,image->blob->extent+1,
03594               sizeof(*image->blob->data));
03595             (void) SyncBlob(image);
03596             if (image->blob->data == (unsigned char *) NULL)
03597               {
03598                 (void) DetachBlob(image->blob);
03599                 return(-1);
03600               }
03601           }
03602       break;
03603     }
03604   }
03605   return(image->blob->offset);
03606 }
03607 
03608 /*
03609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03610 %                                                                             %
03611 %                                                                             %
03612 %                                                                             %
03613 +   S e t B l o b E x e m p t                                                 %
03614 %                                                                             %
03615 %                                                                             %
03616 %                                                                             %
03617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03618 %
03619 %  SetBlobExempt() sets the blob exempt status.
03620 %
03621 %  The format of the SetBlobExempt method is:
03622 %
03623 %      MagickBooleanType SetBlobExempt(const Image *image,
03624 %        const MagickBooleanType exempt)
03625 %
03626 %  A description of each parameter follows:
03627 %
03628 %    o image: the image.
03629 %
03630 %    o exempt: Set to true if this blob is exempt from being closed.
03631 %
03632 */
03633 MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
03634 {
03635   assert(image != (const Image *) NULL);
03636   assert(image->signature == MagickSignature);
03637   if (image->debug != MagickFalse)
03638     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03639   image->blob->exempt=exempt;
03640 }
03641 
03642 /*
03643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03644 %                                                                             %
03645 %                                                                             %
03646 %                                                                             %
03647 +  S e t B l o b E x t e n t                                                  %
03648 %                                                                             %
03649 %                                                                             %
03650 %                                                                             %
03651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03652 %
03653 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
03654 %  method is successful, subsequent writes to bytes in the specified range are
03655 %  guaranteed not to fail.
03656 %
03657 %  The format of the SetBlobExtent method is:
03658 %
03659 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
03660 %
03661 %  A description of each parameter follows:
03662 %
03663 %    o image: the image.
03664 %
03665 %    o extent:  the blob maximum extent.
03666 %
03667 */
03668 MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
03669   const MagickSizeType extent)
03670 {
03671   assert(image != (Image *) NULL);
03672   assert(image->signature == MagickSignature);
03673   if (image->debug != MagickFalse)
03674     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03675   assert(image->blob != (BlobInfo *) NULL);
03676   assert(image->blob->type != UndefinedStream);
03677   switch (image->blob->type)
03678   {
03679     case UndefinedStream:
03680       break;
03681     case FileStream:
03682     {
03683       if (extent != (MagickSizeType) ((off_t) extent))
03684         return(MagickFalse);
03685 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
03686         return(MagickFalse);
03687 #else
03688       {
03689         int
03690           status;
03691 
03692         MagickOffsetType
03693           offset;
03694 
03695         offset=TellBlob(image);
03696         status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
03697           (off_t) (extent-offset));
03698         if (status != 0)
03699           return(MagickFalse);
03700       }
03701 #endif
03702       break;
03703     }
03704     case StandardStream:
03705     case PipeStream:
03706     case ZipStream:
03707       return(MagickFalse);
03708     case BZipStream:
03709       return(MagickFalse);
03710     case FifoStream:
03711       return(MagickFalse);
03712     case BlobStream:
03713     {
03714       if (image->blob->mapped != MagickFalse)
03715         {
03716           if (image->blob->file == (FILE *) NULL)
03717             return(MagickFalse);
03718           (void) UnmapBlob(image->blob->data,image->blob->length);
03719 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
03720           return(MagickFalse);
03721 #else
03722           {
03723             int
03724               status;
03725 
03726             MagickOffsetType
03727               offset;
03728 
03729             offset=TellBlob(image);
03730             status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
03731               (off_t) (extent-offset));
03732             if (status != 0)
03733               return(MagickFalse);
03734           }
03735           image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
03736             WriteMode,0,(size_t) extent);
03737           image->blob->extent=(size_t) extent;
03738           image->blob->length=(size_t) extent;
03739           (void) SyncBlob(image);
03740           break;
03741 #endif
03742         }
03743       if (extent != (MagickSizeType) ((size_t) extent))
03744         return(MagickFalse);
03745       image->blob->extent=(size_t) extent;
03746       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
03747         image->blob->extent+1,sizeof(*image->blob->data));
03748       (void) SyncBlob(image);
03749       if (image->blob->data == (unsigned char *) NULL)
03750         {
03751           (void) DetachBlob(image->blob);
03752           return(MagickFalse);
03753         }
03754       break;
03755     }
03756   }
03757   return(MagickTrue);
03758 }
03759 
03760 /*
03761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03762 %                                                                             %
03763 %                                                                             %
03764 %                                                                             %
03765 +  S y n c B l o b                                                            %
03766 %                                                                             %
03767 %                                                                             %
03768 %                                                                             %
03769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03770 %
03771 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
03772 %  attributes if it is an blob.
03773 %
03774 %  The format of the SyncBlob method is:
03775 %
03776 %      int SyncBlob(Image *image)
03777 %
03778 %  A description of each parameter follows:
03779 %
03780 %    o image: the image.
03781 %
03782 */
03783 static int SyncBlob(Image *image)
03784 {
03785   int
03786     status;
03787 
03788   assert(image != (Image *) NULL);
03789   assert(image->signature == MagickSignature);
03790   if (image->debug != MagickFalse)
03791     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03792   assert(image->blob != (BlobInfo *) NULL);
03793   assert(image->blob->type != UndefinedStream);
03794   status=0;
03795   switch (image->blob->type)
03796   {
03797     case UndefinedStream:
03798       break;
03799     case FileStream:
03800     case StandardStream:
03801     case PipeStream:
03802     {
03803       status=fflush(image->blob->file);
03804       break;
03805     }
03806     case ZipStream:
03807     {
03808 #if defined(MAGICKCORE_ZLIB_DELEGATE)
03809       status=gzflush(image->blob->gzfile,Z_SYNC_FLUSH);
03810 #endif
03811       break;
03812     }
03813     case BZipStream:
03814     {
03815 #if defined(MAGICKCORE_BZLIB_DELEGATE)
03816       status=BZ2_bzflush(image->blob->bzfile);
03817 #endif
03818       break;
03819     }
03820     case FifoStream:
03821       break;
03822     case BlobStream:
03823     {
03824 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
03825       if (image->blob->mapped != MagickFalse)
03826         status=msync(image->blob->data,image->blob->length,MS_SYNC);
03827 #endif
03828       break;
03829     }
03830   }
03831   return(status);
03832 }
03833 
03834 /*
03835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03836 %                                                                             %
03837 %                                                                             %
03838 %                                                                             %
03839 +  T e l l B l o b                                                            %
03840 %                                                                             %
03841 %                                                                             %
03842 %                                                                             %
03843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03844 %
03845 %  TellBlob() obtains the current value of the blob or file position.
03846 %
03847 %  The format of the TellBlob method is:
03848 %
03849 %      MagickOffsetType TellBlob(const Image *image)
03850 %
03851 %  A description of each parameter follows:
03852 %
03853 %    o image: the image.
03854 %
03855 */
03856 MagickExport MagickOffsetType TellBlob(const Image *image)
03857 {
03858   MagickOffsetType
03859     offset;
03860 
03861   assert(image != (Image *) NULL);
03862   assert(image->signature == MagickSignature);
03863   if (image->debug != MagickFalse)
03864     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03865   assert(image->blob != (BlobInfo *) NULL);
03866   assert(image->blob->type != UndefinedStream);
03867   offset=(-1);
03868   switch (image->blob->type)
03869   {
03870     case UndefinedStream:
03871       break;
03872     case FileStream:
03873     {
03874       offset=ftell(image->blob->file);
03875       break;
03876     }
03877     case StandardStream:
03878     case PipeStream:
03879       break;
03880     case ZipStream:
03881     {
03882 #if defined(MAGICKCORE_ZLIB_DELEGATE)
03883       offset=(MagickOffsetType) gztell(image->blob->gzfile);
03884 #endif
03885       break;
03886     }
03887     case BZipStream:
03888       break;
03889     case FifoStream:
03890       break;
03891     case BlobStream:
03892     {
03893       offset=image->blob->offset;
03894       break;
03895     }
03896   }
03897   return(offset);
03898 }
03899 
03900 /*
03901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03902 %                                                                             %
03903 %                                                                             %
03904 %                                                                             %
03905 +  U n m a p B l o b                                                          %
03906 %                                                                             %
03907 %                                                                             %
03908 %                                                                             %
03909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03910 %
03911 %  UnmapBlob() deallocates the binary large object previously allocated with
03912 %  the MapBlob method.
03913 %
03914 %  The format of the UnmapBlob method is:
03915 %
03916 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
03917 %
03918 %  A description of each parameter follows:
03919 %
03920 %    o map: the address  of the binary large object.
03921 %
03922 %    o length: the length of the binary large object.
03923 %
03924 */
03925 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
03926 {
03927 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
03928   int
03929     status;
03930 
03931   status=munmap(map,length);
03932   return(status == -1 ? MagickFalse : MagickTrue);
03933 #else
03934   (void) map;
03935   (void) length;
03936   return(MagickFalse);
03937 #endif
03938 }
03939 
03940 /*
03941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03942 %                                                                             %
03943 %                                                                             %
03944 %                                                                             %
03945 +  W r i t e B l o b                                                          %
03946 %                                                                             %
03947 %                                                                             %
03948 %                                                                             %
03949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03950 %
03951 %  WriteBlob() writes data to a blob or image file.  It returns the number of
03952 %  bytes written.
03953 %
03954 %  The format of the WriteBlob method is:
03955 %
03956 %      ssize_t WriteBlob(Image *image,const size_t length,
03957 %        const unsigned char *data)
03958 %
03959 %  A description of each parameter follows:
03960 %
03961 %    o image: the image.
03962 %
03963 %    o length:  Specifies an integer representing the number of bytes to
03964 %      write to the file.
03965 %
03966 %    o data:  The address of the data to write to the blob or file.
03967 %
03968 */
03969 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
03970   const unsigned char *data)
03971 {
03972   int
03973     c;
03974 
03975   register const unsigned char
03976     *p;
03977 
03978   ssize_t
03979     count;
03980 
03981   assert(image != (Image *) NULL);
03982   assert(image->signature == MagickSignature);
03983   assert(data != (const unsigned char *) NULL);
03984   assert(image->blob != (BlobInfo *) NULL);
03985   assert(image->blob->type != UndefinedStream);
03986   if (length == 0)
03987     return(0);
03988   count=0;
03989   p=data;
03990   switch (image->blob->type)
03991   {
03992     case UndefinedStream:
03993       break;
03994     case FileStream:
03995     case StandardStream:
03996     case PipeStream:
03997     {
03998       switch (length)
03999       {
04000         default:
04001         {
04002           count=(ssize_t) fwrite((const char *) data,1,length,
04003             image->blob->file);
04004           break;
04005         }
04006         case 2:
04007         {
04008           c=putc((int) *p++,image->blob->file);
04009           if (c == EOF)
04010             break;
04011           count++;
04012         }
04013         case 1:
04014         {
04015           c=putc((int) *p++,image->blob->file);
04016           if (c == EOF)
04017             break;
04018           count++;
04019         }
04020         case 0:
04021           break;
04022       }
04023       break;
04024     }
04025     case ZipStream:
04026     {
04027 #if defined(MAGICKCORE_ZLIB_DELEGATE)
04028       switch (length)
04029       {
04030         default:
04031         {
04032           count=(ssize_t) gzwrite(image->blob->gzfile,(void *) data,
04033             (unsigned int) length);
04034           break;
04035         }
04036         case 2:
04037         {
04038           c=gzputc(image->blob->gzfile,(int) *p++);
04039           if (c == EOF)
04040             break;
04041           count++;
04042         }
04043         case 1:
04044         {
04045           c=gzputc(image->blob->gzfile,(int) *p++);
04046           if (c == EOF)
04047             break;
04048           count++;
04049         }
04050         case 0:
04051           break;
04052       }
04053 #endif
04054       break;
04055     }
04056     case BZipStream:
04057     {
04058 #if defined(MAGICKCORE_BZLIB_DELEGATE)
04059       count=(ssize_t) BZ2_bzwrite(image->blob->bzfile,(void *) data,(int)
04060         length);
04061 #endif
04062       break;
04063     }
04064     case FifoStream:
04065     {
04066       count=(ssize_t) image->blob->stream(image,data,length);
04067       break;
04068     }
04069     case BlobStream:
04070     {
04071       register unsigned char
04072         *q;
04073 
04074       if ((image->blob->offset+(MagickOffsetType) length) >=
04075           (MagickOffsetType) image->blob->extent)
04076         {
04077           if (image->blob->mapped != MagickFalse)
04078             return(0);
04079           image->blob->quantum<<=1;
04080           image->blob->extent+=length+image->blob->quantum;
04081           image->blob->data=(unsigned char *) ResizeQuantumMemory(
04082             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
04083           (void) SyncBlob(image);
04084           if (image->blob->data == (unsigned char *) NULL)
04085             {
04086               (void) DetachBlob(image->blob);
04087               return(0);
04088             }
04089         }
04090       q=image->blob->data+image->blob->offset;
04091       (void) memcpy(q,p,length);
04092       image->blob->offset+=length;
04093       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
04094         image->blob->length=(size_t) image->blob->offset;
04095       count=(ssize_t) length;
04096     }
04097   }
04098   return(count);
04099 }
04100 
04101 /*
04102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04103 %                                                                             %
04104 %                                                                             %
04105 %                                                                             %
04106 +  W r i t e B l o b B y t e                                                  %
04107 %                                                                             %
04108 %                                                                             %
04109 %                                                                             %
04110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04111 %
04112 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
04113 %  written (either 0 or 1);
04114 %
04115 %  The format of the WriteBlobByte method is:
04116 %
04117 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
04118 %
04119 %  A description of each parameter follows.
04120 %
04121 %    o image: the image.
04122 %
04123 %    o value: Specifies the value to write.
04124 %
04125 */
04126 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
04127 {
04128   assert(image != (Image *) NULL);
04129   assert(image->signature == MagickSignature);
04130   return(WriteBlobStream(image,1,&value));
04131 }
04132 
04133 /*
04134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04135 %                                                                             %
04136 %                                                                             %
04137 %                                                                             %
04138 +  W r i t e B l o b F l o a t                                                %
04139 %                                                                             %
04140 %                                                                             %
04141 %                                                                             %
04142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04143 %
04144 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
04145 %  specified by the endian member of the image structure.
04146 %
04147 %  The format of the WriteBlobFloat method is:
04148 %
04149 %      ssize_t WriteBlobFloat(Image *image,const float value)
04150 %
04151 %  A description of each parameter follows.
04152 %
04153 %    o image: the image.
04154 %
04155 %    o value: Specifies the value to write.
04156 %
04157 */
04158 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
04159 {
04160   union
04161   {
04162     unsigned int
04163       unsigned_value;
04164 
04165     float
04166       float_value;
04167   } quantum;
04168 
04169   quantum.unsigned_value=0U;
04170   quantum.float_value=value;
04171   return(WriteBlobLong(image,quantum.unsigned_value));
04172 }
04173 
04174 /*
04175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04176 %                                                                             %
04177 %                                                                             %
04178 %                                                                             %
04179 +  W r i t e B l o b L o n g                                                  %
04180 %                                                                             %
04181 %                                                                             %
04182 %                                                                             %
04183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04184 %
04185 %  WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
04186 %  specified by the endian member of the image structure.
04187 %
04188 %  The format of the WriteBlobLong method is:
04189 %
04190 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
04191 %
04192 %  A description of each parameter follows.
04193 %
04194 %    o image: the image.
04195 %
04196 %    o value: Specifies the value to write.
04197 %
04198 */
04199 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
04200 {
04201   unsigned char
04202     buffer[4];
04203 
04204   assert(image != (Image *) NULL);
04205   assert(image->signature == MagickSignature);
04206   if (image->endian == LSBEndian)
04207     {
04208       buffer[0]=(unsigned char) value;
04209       buffer[1]=(unsigned char) (value >> 8);
04210       buffer[2]=(unsigned char) (value >> 16);
04211       buffer[3]=(unsigned char) (value >> 24);
04212       return(WriteBlobStream(image,4,buffer));
04213     }
04214   buffer[0]=(unsigned char) (value >> 24);
04215   buffer[1]=(unsigned char) (value >> 16);
04216   buffer[2]=(unsigned char) (value >> 8);
04217   buffer[3]=(unsigned char) value;
04218   return(WriteBlobStream(image,4,buffer));
04219 }
04220 
04221 /*
04222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04223 %                                                                             %
04224 %                                                                             %
04225 %                                                                             %
04226 +   W r i t e B l o b S h o r t                                               %
04227 %                                                                             %
04228 %                                                                             %
04229 %                                                                             %
04230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04231 %
04232 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
04233 %  byte-order specified by the endian member of the image structure.
04234 %
04235 %  The format of the WriteBlobShort method is:
04236 %
04237 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
04238 %
04239 %  A description of each parameter follows.
04240 %
04241 %    o image: the image.
04242 %
04243 %    o value:  Specifies the value to write.
04244 %
04245 */
04246 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
04247 {
04248   unsigned char
04249     buffer[2];
04250 
04251