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