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

Generated on Thu Jul 2 12:03:13 2009 for MagickCore by  doxygen 1.5.8