2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 % BBBB LLLLL OOO BBBB %
13 % MagickCore Binary Large OBjectS Methods %
20 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/client.h"
48 #include "MagickCore/constitute.h"
49 #include "MagickCore/delegate.h"
50 #include "MagickCore/exception.h"
51 #include "MagickCore/exception-private.h"
52 #include "MagickCore/image-private.h"
53 #include "MagickCore/list.h"
54 #include "MagickCore/locale_.h"
55 #include "MagickCore/log.h"
56 #include "MagickCore/magick.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/nt-base-private.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/resource_.h"
61 #include "MagickCore/semaphore.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/string-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
67 #if defined(MAGICKCORE_ZLIB_DELEGATE)
70 #if defined(MAGICKCORE_BZLIB_DELEGATE)
77 #define MagickMaxBlobExtent 65541
78 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
79 # define MAP_ANONYMOUS MAP_ANON
81 #if !defined(MAP_FAILED)
82 #define MAP_FAILED ((void *) -1)
86 #define _O_BINARY O_BINARY
92 typedef union FileInfo
97 #if defined(MAGICKCORE_ZLIB_DELEGATE)
102 #if defined(MAGICKCORE_BZLIB_DELEGATE)
160 Forward declarations.
166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 + A t t a c h B l o b %
174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
176 % AttachBlob() attaches a blob to the BlobInfo structure.
178 % The format of the AttachBlob method is:
180 % void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
182 % A description of each parameter follows:
184 % o blob_info: Specifies a pointer to a BlobInfo structure.
186 % o blob: the address of a character stream in one of the image formats
187 % understood by ImageMagick.
189 % o length: This size_t integer reflects the length in bytes of the blob.
192 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
195 assert(blob_info != (BlobInfo *) NULL);
196 if (blob_info->debug != MagickFalse)
197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
198 blob_info->length=length;
199 blob_info->extent=length;
200 blob_info->quantum=(size_t) MagickMaxBlobExtent;
202 blob_info->type=BlobStream;
203 blob_info->file_info.file=(FILE *) NULL;
204 blob_info->data=(unsigned char *) blob;
205 blob_info->mapped=MagickFalse;
209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213 + B l o b T o F i l e %
217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 % BlobToFile() writes a blob to a file. It returns MagickFalse if an error
220 % occurs otherwise MagickTrue.
222 % The format of the BlobToFile method is:
224 % MagickBooleanType BlobToFile(char *filename,const void *blob,
225 % const size_t length,ExceptionInfo *exception)
227 % A description of each parameter follows:
229 % o filename: Write the blob to this file.
231 % o blob: the address of a blob.
233 % o length: This length in bytes of the blob.
235 % o exception: return any errors or warnings in this structure.
239 static inline MagickSizeType MagickMin(const MagickSizeType x,
240 const MagickSizeType y)
247 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
248 const size_t length,ExceptionInfo *exception)
259 assert(filename != (const char *) NULL);
260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
261 assert(blob != (const void *) NULL);
262 if (*filename == '\0')
263 file=AcquireUniqueFileResource(filename);
265 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
268 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
271 for (i=0; i < length; i+=count)
273 count=write(file,(const char *) blob+i,(size_t) MagickMin(length-i,
274 (MagickSizeType) SSIZE_MAX));
283 if ((file == -1) || (i < length))
285 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 % B l o b T o I m a g e %
300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 % BlobToImage() implements direct to memory image formats. It returns the
305 % The format of the BlobToImage method is:
307 % Image *BlobToImage(const ImageInfo *image_info,const void *blob,
308 % const size_t length,ExceptionInfo *exception)
310 % A description of each parameter follows:
312 % o image_info: the image info.
314 % o blob: the address of a character stream in one of the image formats
315 % understood by ImageMagick.
317 % o length: This size_t integer reflects the length in bytes of the blob.
319 % o exception: return any errors or warnings in this structure.
322 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
323 const size_t length,ExceptionInfo *exception)
338 assert(image_info != (ImageInfo *) NULL);
339 assert(image_info->signature == MagickSignature);
340 if (image_info->debug != MagickFalse)
341 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
342 image_info->filename);
343 assert(exception != (ExceptionInfo *) NULL);
344 if ((blob == (const void *) NULL) || (length == 0))
346 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
347 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
348 return((Image *) NULL);
350 blob_info=CloneImageInfo(image_info);
351 blob_info->blob=(void *) blob;
352 blob_info->length=length;
353 if (*blob_info->magick == '\0')
354 (void) SetImageInfo(blob_info,0,exception);
355 magick_info=GetMagickInfo(blob_info->magick,exception);
356 if (magick_info == (const MagickInfo *) NULL)
358 (void) ThrowMagickException(exception,GetMagickModule(),
359 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
361 blob_info=DestroyImageInfo(blob_info);
362 return((Image *) NULL);
364 if (GetMagickBlobSupport(magick_info) != MagickFalse)
367 Native blob support for this image format.
369 (void) CopyMagickString(blob_info->filename,image_info->filename,
371 (void) CopyMagickString(blob_info->magick,image_info->magick,
373 image=ReadImage(blob_info,exception);
374 if (image != (Image *) NULL)
375 (void) DetachBlob(image->blob);
376 blob_info=DestroyImageInfo(blob_info);
380 Write blob to a temporary file on disk.
382 blob_info->blob=(void *) NULL;
384 *blob_info->filename='\0';
385 status=BlobToFile(blob_info->filename,blob,length,exception);
386 if (status == MagickFalse)
388 (void) RelinquishUniqueFileResource(blob_info->filename);
389 blob_info=DestroyImageInfo(blob_info);
390 return((Image *) NULL);
392 clone_info=CloneImageInfo(blob_info);
393 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
394 blob_info->magick,blob_info->filename);
395 image=ReadImage(clone_info,exception);
396 if (image != (Image *) NULL)
402 Restore original filenames and image format.
404 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
406 (void) CopyMagickString(images->filename,image_info->filename,
408 (void) CopyMagickString(images->magick_filename,image_info->filename,
410 (void) CopyMagickString(images->magick,magick_info->name,
412 images=GetNextImageInList(images);
415 clone_info=DestroyImageInfo(clone_info);
416 (void) RelinquishUniqueFileResource(blob_info->filename);
417 blob_info=DestroyImageInfo(blob_info);
422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426 + C l o n e B l o b I n f o %
430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 % CloneBlobInfo() makes a duplicate of the given blob info structure, or if
433 % blob info is NULL, a new one.
435 % The format of the CloneBlobInfo method is:
437 % BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
439 % A description of each parameter follows:
441 % o blob_info: the blob info.
444 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
449 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
450 if (clone_info == (BlobInfo *) NULL)
451 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
452 GetBlobInfo(clone_info);
453 if (blob_info == (BlobInfo *) NULL)
455 clone_info->length=blob_info->length;
456 clone_info->extent=blob_info->extent;
457 clone_info->synchronize=blob_info->synchronize;
458 clone_info->quantum=blob_info->quantum;
459 clone_info->mapped=blob_info->mapped;
460 clone_info->eof=blob_info->eof;
461 clone_info->offset=blob_info->offset;
462 clone_info->size=blob_info->size;
463 clone_info->exempt=blob_info->exempt;
464 clone_info->status=blob_info->status;
465 clone_info->temporary=blob_info->temporary;
466 clone_info->type=blob_info->type;
467 clone_info->file_info.file=blob_info->file_info.file;
468 clone_info->properties=blob_info->properties;
469 clone_info->stream=blob_info->stream;
470 clone_info->data=blob_info->data;
471 clone_info->debug=IsEventLogging();
472 clone_info->reference_count=1;
477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 + C l o s e B l o b %
485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487 % CloseBlob() closes a stream associated with the image.
489 % The format of the CloseBlob method is:
491 % MagickBooleanType CloseBlob(Image *image)
493 % A description of each parameter follows:
495 % o image: the image.
498 MagickExport MagickBooleanType CloseBlob(Image *image)
506 assert(image != (Image *) NULL);
507 assert(image->signature == MagickSignature);
508 if (image->debug != MagickFalse)
509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
510 assert(image->blob != (BlobInfo *) NULL);
511 if (image->blob->type == UndefinedStream)
513 status=SyncBlob(image);
514 switch (image->blob->type)
516 case UndefinedStream:
522 if (image->blob->synchronize != MagickFalse)
523 status=fsync(fileno(image->blob->file_info.file));
524 status=ferror(image->blob->file_info.file);
529 #if defined(MAGICKCORE_ZLIB_DELEGATE)
530 (void) gzerror(image->blob->file_info.gzfile,&status);
536 #if defined(MAGICKCORE_BZLIB_DELEGATE)
537 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
545 if ((image->blob->file_info.file != (FILE *) NULL) &&
546 (image->blob->synchronize != MagickFalse))
548 (void) fsync(fileno(image->blob->file_info.file));
549 status=ferror(image->blob->file_info.file);
554 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
555 image->blob->size=GetBlobSize(image);
556 image->extent=image->blob->size;
557 image->blob->eof=MagickFalse;
558 if (image->blob->exempt != MagickFalse)
560 image->blob->type=UndefinedStream;
561 return(image->blob->status);
563 switch (image->blob->type)
565 case UndefinedStream:
570 status=fclose(image->blob->file_info.file);
575 #if defined(MAGICKCORE_HAVE_PCLOSE)
576 status=pclose(image->blob->file_info.file);
582 #if defined(MAGICKCORE_ZLIB_DELEGATE)
583 status=gzclose(image->blob->file_info.gzfile);
589 #if defined(MAGICKCORE_BZLIB_DELEGATE)
590 BZ2_bzclose(image->blob->file_info.bzfile);
598 if (image->blob->file_info.file != (FILE *) NULL)
599 status=fclose(image->blob->file_info.file);
603 (void) DetachBlob(image->blob);
604 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
605 return(image->blob->status);
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 + D e s t r o y B l o b %
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 % DestroyBlob() deallocates memory associated with a blob.
621 % The format of the DestroyBlob method is:
623 % void DestroyBlob(Image *image)
625 % A description of each parameter follows:
627 % o image: the image.
630 MagickExport void DestroyBlob(Image *image)
635 assert(image != (Image *) NULL);
636 assert(image->signature == MagickSignature);
637 if (image->debug != MagickFalse)
638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
639 assert(image->blob != (BlobInfo *) NULL);
640 assert(image->blob->signature == MagickSignature);
642 LockSemaphoreInfo(image->blob->semaphore);
643 image->blob->reference_count--;
644 assert(image->blob->reference_count >= 0);
645 if (image->blob->reference_count == 0)
647 UnlockSemaphoreInfo(image->blob->semaphore);
648 if (destroy == MagickFalse)
650 (void) CloseBlob(image);
651 if (image->blob->mapped != MagickFalse)
653 (void) UnmapBlob(image->blob->data,image->blob->length);
654 RelinquishMagickResource(MapResource,image->blob->length);
656 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
657 RelinquishSemaphoreInfo(&image->blob->semaphore);
658 image->blob->signature=(~MagickSignature);
659 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 + D e t a c h B l o b %
671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673 % DetachBlob() detaches a blob from the BlobInfo structure.
675 % The format of the DetachBlob method is:
677 % unsigned char *DetachBlob(BlobInfo *blob_info)
679 % A description of each parameter follows:
681 % o blob_info: Specifies a pointer to a BlobInfo structure.
684 MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
689 assert(blob_info != (BlobInfo *) NULL);
690 if (blob_info->debug != MagickFalse)
691 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
692 if (blob_info->mapped != MagickFalse)
694 (void) UnmapBlob(blob_info->data,blob_info->length);
695 blob_info->data=(unsigned char *) NULL;
696 RelinquishMagickResource(MapResource,blob_info->length);
698 blob_info->mapped=MagickFalse;
701 blob_info->eof=MagickFalse;
702 blob_info->exempt=MagickFalse;
703 blob_info->type=UndefinedStream;
704 blob_info->file_info.file=(FILE *) NULL;
705 data=blob_info->data;
706 blob_info->data=(unsigned char *) NULL;
707 blob_info->stream=(StreamHandler) NULL;
712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716 + D i s c a r d B l o b B y t e s %
720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 % DiscardBlobBytes() discards bytes in a blob.
724 % The format of the DiscardBlobBytes method is:
726 % MagickBooleanType DiscardBlobBytes(Image *image,
727 % const MagickSizeType length)
729 % A description of each parameter follows.
731 % o image: the image.
733 % o length: the number of bytes to skip.
737 static inline const unsigned char *ReadBlobStream(Image *image,
738 const size_t length,unsigned char *data,ssize_t *count)
740 assert(count != (ssize_t *) NULL);
741 assert(image->blob != (BlobInfo *) NULL);
742 if (image->blob->type != BlobStream)
744 *count=ReadBlob(image,length,data);
747 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
750 image->blob->eof=MagickTrue;
753 data=image->blob->data+image->blob->offset;
754 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
755 image->blob->offset));
756 image->blob->offset+=(*count);
757 if (*count != (ssize_t) length)
758 image->blob->eof=MagickTrue;
762 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
763 const MagickSizeType length)
765 register MagickOffsetType
777 assert(image != (Image *) NULL);
778 assert(image->signature == MagickSignature);
780 for (i=0; i < (MagickOffsetType) length; i+=count)
782 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
783 (void) ReadBlobStream(image,quantum,buffer,&count);
791 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
799 + D u p l i c a t e s B l o b %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
805 % DuplicateBlob() duplicates a blob descriptor.
807 % The format of the DuplicateBlob method is:
809 % void DuplicateBlob(Image *image,const Image *duplicate)
811 % A description of each parameter follows:
813 % o image: the image.
815 % o duplicate: the duplicate image.
818 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
820 assert(image != (Image *) NULL);
821 assert(image->signature == MagickSignature);
822 if (image->debug != MagickFalse)
823 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
824 assert(duplicate != (Image *) NULL);
825 assert(duplicate->signature == MagickSignature);
827 image->blob=ReferenceBlob(duplicate->blob);
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 % EOFBlob() returns a non-zero value when EOF has been detected reading from
844 % The format of the EOFBlob method is:
846 % int EOFBlob(const Image *image)
848 % A description of each parameter follows:
850 % o image: the image.
853 MagickExport int EOFBlob(const Image *image)
855 assert(image != (Image *) NULL);
856 assert(image->signature == MagickSignature);
857 if (image->debug != MagickFalse)
858 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
859 assert(image->blob != (BlobInfo *) NULL);
860 assert(image->blob->type != UndefinedStream);
861 switch (image->blob->type)
863 case UndefinedStream:
869 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
875 image->blob->eof=MagickFalse;
880 #if defined(MAGICKCORE_BZLIB_DELEGATE)
885 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
886 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
892 image->blob->eof=MagickFalse;
898 return((int) image->blob->eof);
902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
906 + F i l e T o B l o b %
910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912 % FileToBlob() returns the contents of a file as a buffer terminated with
913 % the '\0' character. The length of the buffer (not including the extra
914 % terminating '\0' character) is returned via the 'length' parameter. Free
915 % the buffer with RelinquishMagickMemory().
917 % The format of the FileToBlob method is:
919 % unsigned char *FileToBlob(const char *filename,const size_t extent,
920 % size_t *length,ExceptionInfo *exception)
922 % A description of each parameter follows:
924 % o blob: FileToBlob() returns the contents of a file as a blob. If
925 % an error occurs NULL is returned.
927 % o filename: the filename.
929 % o extent: The maximum length of the blob.
931 % o length: On return, this reflects the actual length of the blob.
933 % o exception: return any errors or warnings in this structure.
936 MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
937 size_t *length,ExceptionInfo *exception)
957 assert(filename != (const char *) NULL);
958 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
959 assert(exception != (ExceptionInfo *) NULL);
962 if (LocaleCompare(filename,"-") != 0)
963 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
966 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
967 return((unsigned char *) NULL);
969 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
971 if ((file == fileno(stdin)) || (offset < 0) ||
972 (offset != (MagickOffsetType) ((ssize_t) offset)))
981 Stream is not seekable.
983 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
984 quantum=(size_t) MagickMaxBufferExtent;
985 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
986 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
987 MagickMaxBufferExtent);
988 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
989 for (i=0; blob != (unsigned char *) NULL; i+=count)
991 count=read(file,blob+i,quantum);
998 if (~((size_t) i) < (quantum+1))
1000 blob=(unsigned char *) RelinquishMagickMemory(blob);
1003 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1005 if ((size_t) (i+count) >= extent)
1008 if (LocaleCompare(filename,"-") != 0)
1010 if (blob == (unsigned char *) NULL)
1012 (void) ThrowMagickException(exception,GetMagickModule(),
1013 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1014 return((unsigned char *) NULL);
1018 blob=(unsigned char *) RelinquishMagickMemory(blob);
1019 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1020 return((unsigned char *) NULL);
1022 *length=(size_t) MagickMin(i+count,extent);
1026 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
1027 blob=(unsigned char *) NULL;
1028 if (~(*length) >= (MaxTextExtent-1))
1029 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1031 if (blob == (unsigned char *) NULL)
1034 (void) ThrowMagickException(exception,GetMagickModule(),
1035 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1036 return((unsigned char *) NULL);
1038 map=MapBlob(file,ReadMode,0,*length);
1039 if (map != (unsigned char *) NULL)
1041 (void) memcpy(blob,map,*length);
1042 (void) UnmapBlob(map,*length);
1046 (void) lseek(file,0,SEEK_SET);
1047 for (i=0; i < *length; i+=count)
1049 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1061 blob=(unsigned char *) RelinquishMagickMemory(blob);
1062 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1063 return((unsigned char *) NULL);
1067 if (LocaleCompare(filename,"-") != 0)
1071 blob=(unsigned char *) RelinquishMagickMemory(blob);
1072 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1082 % F i l e T o I m a g e %
1086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1088 % FileToImage() write the contents of a file to an image.
1090 % The format of the FileToImage method is:
1092 % MagickBooleanType FileToImage(Image *,const char *filename)
1094 % A description of each parameter follows:
1096 % o image: the image.
1098 % o filename: the filename.
1102 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1103 const unsigned char *data)
1108 register unsigned char
1111 assert(image->blob != (BlobInfo *) NULL);
1112 if (image->blob->type != BlobStream)
1113 return(WriteBlob(image,length,data));
1114 assert(image->blob->type != UndefinedStream);
1115 assert(data != (void *) NULL);
1116 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1117 if (extent >= image->blob->extent)
1119 extent=image->blob->extent+image->blob->quantum+length;
1120 image->blob->quantum<<=1;
1121 if (SetBlobExtent(image,extent) == MagickFalse)
1124 q=image->blob->data+image->blob->offset;
1125 (void) memcpy(q,data,length);
1126 image->blob->offset+=length;
1127 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1128 image->blob->length=(size_t) image->blob->offset;
1129 return((ssize_t) length);
1132 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1133 ExceptionInfo *exception)
1151 assert(image != (const Image *) NULL);
1152 assert(image->signature == MagickSignature);
1153 assert(filename != (const char *) NULL);
1154 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1156 if (LocaleCompare(filename,"-") != 0)
1157 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1160 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1161 return(MagickFalse);
1163 quantum=(size_t) MagickMaxBufferExtent;
1164 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1165 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1166 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1167 if (blob == (unsigned char *) NULL)
1170 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1172 return(MagickFalse);
1176 count=read(file,blob,quantum);
1183 length=(size_t) count;
1184 count=WriteBlobStream(image,length,blob);
1185 if (count != (ssize_t) length)
1187 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1193 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1194 blob=(unsigned char *) RelinquishMagickMemory(blob);
1199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203 + G e t B l o b E r r o r %
1207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209 % GetBlobError() returns MagickTrue if the blob associated with the specified
1210 % image encountered an error.
1212 % The format of the GetBlobError method is:
1214 % MagickBooleanType GetBlobError(const Image *image)
1216 % A description of each parameter follows:
1218 % o image: the image.
1221 MagickPrivate MagickBooleanType GetBlobError(const Image *image)
1223 assert(image != (const Image *) NULL);
1224 assert(image->signature == MagickSignature);
1225 if (image->debug != MagickFalse)
1226 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1227 return(image->blob->status);
1231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1235 + G e t B l o b F i l e H a n d l e %
1239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1241 % GetBlobFileHandle() returns the file handle associated with the image blob.
1243 % The format of the GetBlobFile method is:
1245 % FILE *GetBlobFileHandle(const Image *image)
1247 % A description of each parameter follows:
1249 % o image: the image.
1252 MagickExport FILE *GetBlobFileHandle(const Image *image)
1254 assert(image != (const Image *) NULL);
1255 assert(image->signature == MagickSignature);
1256 return(image->blob->file_info.file);
1260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 + G e t B l o b I n f o %
1268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1270 % GetBlobInfo() initializes the BlobInfo structure.
1272 % The format of the GetBlobInfo method is:
1274 % void GetBlobInfo(BlobInfo *blob_info)
1276 % A description of each parameter follows:
1278 % o blob_info: Specifies a pointer to a BlobInfo structure.
1281 MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
1283 assert(blob_info != (BlobInfo *) NULL);
1284 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1285 blob_info->type=UndefinedStream;
1286 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1287 blob_info->properties.st_mtime=time((time_t *) NULL);
1288 blob_info->properties.st_ctime=time((time_t *) NULL);
1289 blob_info->debug=IsEventLogging();
1290 blob_info->reference_count=1;
1291 blob_info->semaphore=AcquireSemaphoreInfo();
1292 blob_info->signature=MagickSignature;
1296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1300 % G e t B l o b P r o p e r t i e s %
1304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1306 % GetBlobProperties() returns information about an image blob.
1308 % The format of the GetBlobProperties method is:
1310 % const struct stat *GetBlobProperties(const Image *image)
1312 % A description of each parameter follows:
1314 % o image: the image.
1317 MagickPrivate const struct stat *GetBlobProperties(const Image *image)
1319 assert(image != (Image *) NULL);
1320 assert(image->signature == MagickSignature);
1321 if (image->debug != MagickFalse)
1322 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1323 return(&image->blob->properties);
1327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331 + G e t B l o b S i z e %
1335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 % GetBlobSize() returns the current length of the image file or blob; zero is
1338 % returned if the size cannot be determined.
1340 % The format of the GetBlobSize method is:
1342 % MagickSizeType GetBlobSize(const Image *image)
1344 % A description of each parameter follows:
1346 % o image: the image.
1349 MagickExport MagickSizeType GetBlobSize(const Image *image)
1354 assert(image != (Image *) NULL);
1355 assert(image->signature == MagickSignature);
1356 if (image->debug != MagickFalse)
1357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1358 assert(image->blob != (BlobInfo *) NULL);
1360 switch (image->blob->type)
1362 case UndefinedStream:
1364 extent=image->blob->size;
1367 case StandardStream:
1369 extent=image->blob->size;
1374 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
1375 extent=(MagickSizeType) image->blob->properties.st_size;
1380 extent=image->blob->size;
1389 status=GetPathAttributes(image->filename,&image->blob->properties);
1390 if (status != MagickFalse)
1391 extent=(MagickSizeType) image->blob->properties.st_size;
1398 extent=(MagickSizeType) image->blob->length;
1406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410 + G e t B l o b S t r e a m D a t a %
1414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1416 % GetBlobStreamData() returns the stream data for the image.
1418 % The format of the GetBlobStreamData method is:
1420 % unsigned char *GetBlobStreamData(const Image *image)
1422 % A description of each parameter follows:
1424 % o image: the image.
1427 MagickExport unsigned char *GetBlobStreamData(const Image *image)
1429 assert(image != (const Image *) NULL);
1430 assert(image->signature == MagickSignature);
1431 return(image->blob->data);
1435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439 + G e t B l o b S t r e a m H a n d l e r %
1443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1445 % GetBlobStreamHandler() returns the stream handler for the image.
1447 % The format of the GetBlobStreamHandler method is:
1449 % StreamHandler GetBlobStreamHandler(const Image *image)
1451 % A description of each parameter follows:
1453 % o image: the image.
1456 MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
1458 assert(image != (const Image *) NULL);
1459 assert(image->signature == MagickSignature);
1460 if (image->debug != MagickFalse)
1461 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1462 return(image->blob->stream);
1466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1470 % I m a g e T o B l o b %
1474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1476 % ImageToBlob() implements direct to memory image formats. It returns the
1477 % image as a formatted blob and its length. The magick member of the Image
1478 % structure determines the format of the returned blob (GIF, JPEG, PNG,
1479 % etc.). This method is the equivalent of WriteImage(), but writes the
1480 % formatted "file" to a memory buffer rather than to an actual file.
1482 % The format of the ImageToBlob method is:
1484 % unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1485 % size_t *length,ExceptionInfo *exception)
1487 % A description of each parameter follows:
1489 % o image_info: the image info.
1491 % o image: the image.
1493 % o length: return the actual length of the blob.
1495 % o exception: return any errors or warnings in this structure.
1498 MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1499 Image *image,size_t *length,ExceptionInfo *exception)
1513 assert(image_info != (const ImageInfo *) NULL);
1514 assert(image_info->signature == MagickSignature);
1515 if (image_info->debug != MagickFalse)
1516 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1517 image_info->filename);
1518 assert(image != (Image *) NULL);
1519 assert(image->signature == MagickSignature);
1520 assert(exception != (ExceptionInfo *) NULL);
1522 blob=(unsigned char *) NULL;
1523 blob_info=CloneImageInfo(image_info);
1524 blob_info->adjoin=MagickFalse;
1525 (void) SetImageInfo(blob_info,1,exception);
1526 if (*blob_info->magick != '\0')
1527 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1528 magick_info=GetMagickInfo(image->magick,exception);
1529 if (magick_info == (const MagickInfo *) NULL)
1531 (void) ThrowMagickException(exception,GetMagickModule(),
1532 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1534 blob_info=DestroyImageInfo(blob_info);
1537 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1538 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1541 Native blob support for this image format.
1543 blob_info->length=0;
1544 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1545 sizeof(unsigned char));
1546 if (blob_info->blob == (void *) NULL)
1547 (void) ThrowMagickException(exception,GetMagickModule(),
1548 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1551 (void) CloseBlob(image);
1552 image->blob->exempt=MagickTrue;
1553 *image->filename='\0';
1554 status=WriteImage(blob_info,image,exception);
1555 *length=image->blob->length;
1556 blob=DetachBlob(image->blob);
1557 if (status == MagickFalse)
1558 blob=(unsigned char *) RelinquishMagickMemory(blob);
1560 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1567 unique[MaxTextExtent];
1573 Write file to disk in blob image format.
1575 file=AcquireUniqueFileResource(unique);
1578 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1579 image_info->filename);
1583 blob_info->file=fdopen(file,"wb");
1584 if (blob_info->file != (FILE *) NULL)
1586 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
1587 image->magick,unique);
1588 status=WriteImage(blob_info,image,exception);
1589 (void) CloseBlob(image);
1590 (void) fclose(blob_info->file);
1591 if (status != MagickFalse)
1592 blob=FileToBlob(unique,~0UL,length,exception);
1594 (void) RelinquishUniqueFileResource(unique);
1597 blob_info=DestroyImageInfo(blob_info);
1602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1606 % I m a g e T o F i l e %
1610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1612 % ImageToFile() writes an image to a file. It returns MagickFalse if an error
1613 % occurs otherwise MagickTrue.
1615 % The format of the ImageToFile method is:
1617 % MagickBooleanType ImageToFile(Image *image,char *filename,
1618 % ExceptionInfo *exception)
1620 % A description of each parameter follows:
1622 % o image: the image.
1624 % o filename: Write the image to this file.
1626 % o exception: return any errors or warnings in this structure.
1629 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1630 ExceptionInfo *exception)
1635 register const unsigned char
1654 assert(image != (Image *) NULL);
1655 assert(image->signature == MagickSignature);
1656 assert(image->blob != (BlobInfo *) NULL);
1657 assert(image->blob->type != UndefinedStream);
1658 if (image->debug != MagickFalse)
1659 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1660 assert(filename != (const char *) NULL);
1661 if (*filename == '\0')
1662 file=AcquireUniqueFileResource(filename);
1664 if (LocaleCompare(filename,"-") == 0)
1665 file=fileno(stdout);
1667 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1670 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1671 return(MagickFalse);
1673 quantum=(size_t) MagickMaxBufferExtent;
1674 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1675 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
1676 MagickMaxBufferExtent);
1677 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1678 if (buffer == (unsigned char *) NULL)
1681 (void) ThrowMagickException(exception,GetMagickModule(),
1682 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1683 return(MagickFalse);
1686 p=ReadBlobStream(image,quantum,buffer,&count);
1687 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1689 length=(size_t) count;
1690 for (i=0; i < length; i+=count)
1692 count=write(file,p+i,(size_t) (length-i));
1703 if (LocaleCompare(filename,"-") != 0)
1705 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1706 if ((file == -1) || (i < length))
1710 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1711 return(MagickFalse);
1717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1721 % I m a g e s T o B l o b %
1725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1727 % ImagesToBlob() implements direct to memory image formats. It returns the
1728 % image sequence as a blob and its length. The magick member of the ImageInfo
1729 % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1731 % Note, some image formats do not permit multiple images to the same image
1732 % stream (e.g. JPEG). in this instance, just the first image of the
1733 % sequence is returned as a blob.
1735 % The format of the ImagesToBlob method is:
1737 % unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1738 % size_t *length,ExceptionInfo *exception)
1740 % A description of each parameter follows:
1742 % o image_info: the image info.
1744 % o images: the image list.
1746 % o length: return the actual length of the blob.
1748 % o exception: return any errors or warnings in this structure.
1751 MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1752 Image *images,size_t *length,ExceptionInfo *exception)
1766 assert(image_info != (const ImageInfo *) NULL);
1767 assert(image_info->signature == MagickSignature);
1768 if (image_info->debug != MagickFalse)
1769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1770 image_info->filename);
1771 assert(images != (Image *) NULL);
1772 assert(images->signature == MagickSignature);
1773 assert(exception != (ExceptionInfo *) NULL);
1775 blob=(unsigned char *) NULL;
1776 blob_info=CloneImageInfo(image_info);
1777 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1779 if (*blob_info->magick != '\0')
1780 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1781 magick_info=GetMagickInfo(images->magick,exception);
1782 if (magick_info == (const MagickInfo *) NULL)
1784 (void) ThrowMagickException(exception,GetMagickModule(),
1785 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1787 blob_info=DestroyImageInfo(blob_info);
1790 if (GetMagickAdjoin(magick_info) == MagickFalse)
1792 blob_info=DestroyImageInfo(blob_info);
1793 return(ImageToBlob(image_info,images,length,exception));
1795 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1796 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1799 Native blob support for this images format.
1801 blob_info->length=0;
1802 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1803 sizeof(unsigned char));
1804 if (blob_info->blob == (void *) NULL)
1805 (void) ThrowMagickException(exception,GetMagickModule(),
1806 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1809 (void) CloseBlob(images);
1810 images->blob->exempt=MagickTrue;
1811 *images->filename='\0';
1812 status=WriteImages(blob_info,images,images->filename,exception);
1813 *length=images->blob->length;
1814 blob=DetachBlob(images->blob);
1815 if (status == MagickFalse)
1816 blob=(unsigned char *) RelinquishMagickMemory(blob);
1818 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1825 filename[MaxTextExtent],
1826 unique[MaxTextExtent];
1832 Write file to disk in blob images format.
1834 file=AcquireUniqueFileResource(unique);
1837 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1838 image_info->filename);
1842 blob_info->file=fdopen(file,"wb");
1843 if (blob_info->file != (FILE *) NULL)
1845 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
1846 images->magick,unique);
1847 status=WriteImages(blob_info,images,filename,exception);
1848 (void) CloseBlob(images);
1849 (void) fclose(blob_info->file);
1850 if (status != MagickFalse)
1851 blob=FileToBlob(unique,~0UL,length,exception);
1853 (void) RelinquishUniqueFileResource(unique);
1856 blob_info=DestroyImageInfo(blob_info);
1860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864 % I n j e c t I m a g e B l o b %
1868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1870 % InjectImageBlob() injects the image with a copy of itself in the specified
1871 % format (e.g. inject JPEG into a PDF image).
1873 % The format of the InjectImageBlob method is:
1875 % MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1876 % Image *image,Image *inject_image,const char *format,
1877 % ExceptionInfo *exception)
1879 % A description of each parameter follows:
1881 % o image_info: the image info..
1883 % o image: the image.
1885 % o inject_image: inject into the image stream.
1887 % o format: the image format.
1889 % o exception: return any errors or warnings in this structure.
1892 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1893 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1896 filename[MaxTextExtent];
1929 Write inject image to a temporary file.
1931 assert(image_info != (ImageInfo *) NULL);
1932 assert(image_info->signature == MagickSignature);
1933 assert(image != (Image *) NULL);
1934 assert(image->signature == MagickSignature);
1935 if (image->debug != MagickFalse)
1936 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1937 assert(inject_image != (Image *) NULL);
1938 assert(inject_image->signature == MagickSignature);
1939 assert(exception != (ExceptionInfo *) NULL);
1940 unique_file=(FILE *) NULL;
1941 file=AcquireUniqueFileResource(filename);
1943 unique_file=fdopen(file,"wb");
1944 if ((file == -1) || (unique_file == (FILE *) NULL))
1946 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1947 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1949 return(MagickFalse);
1951 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1952 if (byte_image == (Image *) NULL)
1954 (void) fclose(unique_file);
1955 (void) RelinquishUniqueFileResource(filename);
1956 return(MagickFalse);
1958 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
1960 DestroyBlob(byte_image);
1961 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1962 write_info=CloneImageInfo(image_info);
1963 SetImageInfoFile(write_info,unique_file);
1964 status=WriteImage(write_info,byte_image,exception);
1965 write_info=DestroyImageInfo(write_info);
1966 byte_image=DestroyImage(byte_image);
1967 (void) fclose(unique_file);
1968 if (status == MagickFalse)
1970 (void) RelinquishUniqueFileResource(filename);
1971 return(MagickFalse);
1974 Inject into image stream.
1976 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1979 (void) RelinquishUniqueFileResource(filename);
1980 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1981 image_info->filename);
1982 return(MagickFalse);
1984 quantum=(size_t) MagickMaxBufferExtent;
1985 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1986 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1987 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1988 if (buffer == (unsigned char *) NULL)
1990 (void) RelinquishUniqueFileResource(filename);
1991 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1994 for (i=0; ; i+=count)
1996 count=read(file,buffer,quantum);
2003 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2008 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2009 (void) RelinquishUniqueFileResource(filename);
2010 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2019 + I s B l o b E x e m p t %
2023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2025 % IsBlobExempt() returns true if the blob is exempt.
2027 % The format of the IsBlobExempt method is:
2029 % MagickBooleanType IsBlobExempt(const Image *image)
2031 % A description of each parameter follows:
2033 % o image: the image.
2036 MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
2038 assert(image != (const Image *) NULL);
2039 assert(image->signature == MagickSignature);
2040 if (image->debug != MagickFalse)
2041 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2042 return(image->blob->exempt);
2046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2050 + I s B l o b S e e k a b l e %
2054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2056 % IsBlobSeekable() returns true if the blob is seekable.
2058 % The format of the IsBlobSeekable method is:
2060 % MagickBooleanType IsBlobSeekable(const Image *image)
2062 % A description of each parameter follows:
2064 % o image: the image.
2067 MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
2072 assert(image != (const Image *) NULL);
2073 assert(image->signature == MagickSignature);
2074 if (image->debug != MagickFalse)
2075 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2076 switch (image->blob->type)
2082 seekable=MagickTrue;
2087 seekable=MagickFalse;
2095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2099 + I s B l o b T e m p o r a r y %
2103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2105 % IsBlobTemporary() returns true if the blob is temporary.
2107 % The format of the IsBlobTemporary method is:
2109 % MagickBooleanType IsBlobTemporary(const Image *image)
2111 % A description of each parameter follows:
2113 % o image: the image.
2116 MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
2118 assert(image != (const Image *) NULL);
2119 assert(image->signature == MagickSignature);
2120 if (image->debug != MagickFalse)
2121 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2122 return(image->blob->temporary);
2126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2136 % MapBlob() creates a mapping from a file to a binary large object.
2138 % The format of the MapBlob method is:
2140 % unsigned char *MapBlob(int file,const MapMode mode,
2141 % const MagickOffsetType offset,const size_t length)
2143 % A description of each parameter follows:
2145 % o file: map this file descriptor.
2147 % o mode: ReadMode, WriteMode, or IOMode.
2149 % o offset: starting at this offset within the file.
2151 % o length: the length of the mapping is returned in this pointer.
2154 MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2155 const MagickOffsetType offset,const size_t length)
2157 #if defined(MAGICKCORE_HAVE_MMAP)
2170 #if defined(MAP_ANONYMOUS)
2171 flags|=MAP_ANONYMOUS;
2173 return((unsigned char *) NULL);
2180 protection=PROT_READ;
2186 protection=PROT_WRITE;
2192 protection=PROT_READ | PROT_WRITE;
2197 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2198 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2201 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
2202 MAP_HUGETLB,file,(off_t) offset);
2203 if (map == (unsigned char *) MAP_FAILED)
2204 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2207 if (map == (unsigned char *) MAP_FAILED)
2208 return((unsigned char *) NULL);
2215 return((unsigned char *) NULL);
2220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2224 + M S B O r d e r L o n g %
2228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2230 % MSBOrderLong() converts a least-significant byte first buffer of integers to
2231 % most-significant byte first.
2233 % The format of the MSBOrderLong method is:
2235 % void MSBOrderLong(unsigned char *buffer,const size_t length)
2237 % A description of each parameter follows.
2239 % o buffer: Specifies a pointer to a buffer of integers.
2241 % o length: Specifies the length of the buffer.
2244 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2249 register unsigned char
2253 assert(buffer != (unsigned char *) NULL);
2260 *buffer++=(unsigned char) c;
2264 *buffer++=(unsigned char) c;
2270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274 + M S B O r d e r S h o r t %
2278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2280 % MSBOrderShort() converts a least-significant byte first buffer of integers
2281 % to most-significant byte first.
2283 % The format of the MSBOrderShort method is:
2285 % void MSBOrderShort(unsigned char *p,const size_t length)
2287 % A description of each parameter follows.
2289 % o p: Specifies a pointer to a buffer of integers.
2291 % o length: Specifies the length of the buffer.
2294 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2299 register unsigned char
2302 assert(p != (unsigned char *) NULL);
2309 *p++=(unsigned char) c;
2314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2324 % OpenBlob() opens a file associated with the image. A file name of '-' sets
2325 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
2326 % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2327 % compressed for type 'w'. If the filename prefix is '|', it is piped to or
2328 % from a system command.
2330 % The format of the OpenBlob method is:
2332 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2333 % const BlobMode mode,ExceptionInfo *exception)
2335 % A description of each parameter follows:
2337 % o image_info: the image info.
2339 % o image: the image.
2341 % o mode: the mode for opening the file.
2344 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2345 Image *image,const BlobMode mode,ExceptionInfo *exception)
2348 extension[MaxTextExtent],
2349 filename[MaxTextExtent];
2360 assert(image_info != (ImageInfo *) NULL);
2361 assert(image_info->signature == MagickSignature);
2362 if (image_info->debug != MagickFalse)
2363 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2364 image_info->filename);
2365 assert(image != (Image *) NULL);
2366 assert(image->signature == MagickSignature);
2367 if (image_info->blob != (void *) NULL)
2369 if (image_info->stream != (StreamHandler) NULL)
2370 image->blob->stream=(StreamHandler) image_info->stream;
2371 AttachBlob(image->blob,image_info->blob,image_info->length);
2374 (void) DetachBlob(image->blob);
2377 default: type="r"; break;
2378 case ReadBlobMode: type="r"; break;
2379 case ReadBinaryBlobMode: type="rb"; break;
2380 case WriteBlobMode: type="w"; break;
2381 case WriteBinaryBlobMode: type="w+b"; break;
2382 case AppendBlobMode: type="a"; break;
2383 case AppendBinaryBlobMode: type="a+b"; break;
2386 image->blob->synchronize=image_info->synchronize;
2387 if (image_info->stream != (StreamHandler) NULL)
2389 image->blob->stream=(StreamHandler) image_info->stream;
2392 image->blob->type=FifoStream;
2400 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2401 rights=ReadPolicyRights;
2403 rights=WritePolicyRights;
2404 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2407 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2408 "NotAuthorized","`%s'",filename);
2409 return(MagickFalse);
2411 if ((LocaleCompare(filename,"-") == 0) ||
2412 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2414 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2415 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2416 if (strchr(type,'b') != (char *) NULL)
2417 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2419 image->blob->type=StandardStream;
2420 image->blob->exempt=MagickTrue;
2423 if (LocaleNCompare(filename,"fd:",3) == 0)
2426 mode[MaxTextExtent];
2430 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2431 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2432 if (strchr(type,'b') != (char *) NULL)
2433 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2435 image->blob->type=StandardStream;
2436 image->blob->exempt=MagickTrue;
2439 #if defined(MAGICKCORE_HAVE_POPEN)
2440 if (*filename == '|')
2443 mode[MaxTextExtent];
2446 Pipe image to or from a system command.
2448 #if defined(SIGPIPE)
2450 (void) signal(SIGPIPE,SIG_IGN);
2454 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2455 if (image->blob->file_info.file == (FILE *) NULL)
2457 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2458 return(MagickFalse);
2460 image->blob->type=PipeStream;
2461 image->blob->exempt=MagickTrue;
2465 status=GetPathAttributes(filename,&image->blob->properties);
2466 #if defined(S_ISFIFO)
2467 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
2469 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2470 if (image->blob->file_info.file == (FILE *) NULL)
2472 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2473 return(MagickFalse);
2475 image->blob->type=FileStream;
2476 image->blob->exempt=MagickTrue;
2480 GetPathComponent(image->filename,ExtensionPath,extension);
2483 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2484 if ((image_info->adjoin == MagickFalse) ||
2485 (strchr(filename,'%') != (char *) NULL))
2488 Form filename for multi-part images.
2490 (void) InterpretImageFilename(image_info,image,image->filename,(int)
2491 image->scene,filename,exception);
2492 if ((LocaleCompare(filename,image->filename) == 0) &&
2493 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2494 (GetNextImageInList(image) != (Image *) NULL)))
2497 path[MaxTextExtent];
2499 GetPathComponent(image->filename,RootPath,path);
2500 if (*extension == '\0')
2501 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
2502 path,(double) image->scene);
2504 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
2505 path,(double) image->scene,extension);
2507 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
2508 #if defined(macintosh)
2509 SetApplicationType(filename,image_info->magick,'8BIM');
2513 if (image_info->file != (FILE *) NULL)
2515 image->blob->file_info.file=image_info->file;
2516 image->blob->type=FileStream;
2517 image->blob->exempt=MagickTrue;
2522 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2523 if (image->blob->file_info.file != (FILE *) NULL)
2531 image->blob->type=FileStream;
2532 #if defined(MAGICKCORE_HAVE_SETVBUF)
2533 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2536 (void) ResetMagickMemory(magick,0,sizeof(magick));
2537 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2538 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
2539 (void) fflush(image->blob->file_info.file);
2540 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2541 " read %.20g magic header bytes",(double) count);
2542 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2543 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2544 ((int) magick[2] == 0x08))
2546 if (image->blob->file_info.file != (FILE *) NULL)
2547 (void) fclose(image->blob->file_info.file);
2548 image->blob->file_info.file=(FILE *) NULL;
2549 image->blob->file_info.gzfile=gzopen(filename,type);
2550 if (image->blob->file_info.gzfile != (gzFile) NULL)
2551 image->blob->type=ZipStream;
2554 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2555 if (strncmp((char *) magick,"BZh",3) == 0)
2557 if (image->blob->file_info.file != (FILE *) NULL)
2558 (void) fclose(image->blob->file_info.file);
2559 image->blob->file_info.file=(FILE *) NULL;
2560 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2561 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2562 image->blob->type=BZipStream;
2565 if (image->blob->type == FileStream)
2576 sans_exception=AcquireExceptionInfo();
2577 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2578 sans_exception=DestroyExceptionInfo(sans_exception);
2579 length=(size_t) image->blob->properties.st_size;
2580 if ((magick_info != (const MagickInfo *) NULL) &&
2581 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2582 (length <= MagickMaxBufferExtent) &&
2583 (AcquireMagickResource(MapResource,length) != MagickFalse))
2588 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2590 if (blob == (void *) NULL)
2591 RelinquishMagickResource(MapResource,length);
2595 Format supports blobs-- use memory-mapped I/O.
2597 if (image_info->file != (FILE *) NULL)
2598 image->blob->exempt=MagickFalse;
2601 (void) fclose(image->blob->file_info.file);
2602 image->blob->file_info.file=(FILE *) NULL;
2604 AttachBlob(image->blob,blob,length);
2605 image->blob->mapped=MagickTrue;
2612 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2613 if ((LocaleCompare(extension,"Z") == 0) ||
2614 (LocaleCompare(extension,"gz") == 0) ||
2615 (LocaleCompare(extension,"wmz") == 0) ||
2616 (LocaleCompare(extension,"svgz") == 0))
2618 if (mode == WriteBinaryBlobMode)
2620 image->blob->file_info.gzfile=gzopen(filename,type);
2621 if (image->blob->file_info.gzfile != (gzFile) NULL)
2622 image->blob->type=ZipStream;
2626 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2627 if (LocaleCompare(extension,"bz2") == 0)
2629 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2630 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2631 image->blob->type=BZipStream;
2636 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2637 if (image->blob->file_info.file != (FILE *) NULL)
2639 image->blob->type=FileStream;
2640 #if defined(MAGICKCORE_HAVE_SETVBUF)
2641 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2646 image->blob->status=MagickFalse;
2647 if (image->blob->type != UndefinedStream)
2648 image->blob->size=GetBlobSize(image);
2651 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2652 return(MagickFalse);
2658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2668 % PingBlob() returns all the attributes of an image or image sequence except
2669 % for the pixels. It is much faster and consumes far less memory than
2670 % BlobToImage(). On failure, a NULL image is returned and exception
2671 % describes the reason for the failure.
2673 % The format of the PingBlob method is:
2675 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
2676 % const size_t length,ExceptionInfo *exception)
2678 % A description of each parameter follows:
2680 % o image_info: the image info.
2682 % o blob: the address of a character stream in one of the image formats
2683 % understood by ImageMagick.
2685 % o length: This size_t integer reflects the length in bytes of the blob.
2687 % o exception: return any errors or warnings in this structure.
2691 #if defined(__cplusplus) || defined(c_plusplus)
2695 static size_t PingStream(const Image *magick_unused(image),
2696 const void *magick_unused(pixels),const size_t columns)
2701 #if defined(__cplusplus) || defined(c_plusplus)
2705 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2706 const size_t length,ExceptionInfo *exception)
2714 assert(image_info != (ImageInfo *) NULL);
2715 assert(image_info->signature == MagickSignature);
2716 if (image_info->debug != MagickFalse)
2717 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2718 image_info->filename);
2719 assert(exception != (ExceptionInfo *) NULL);
2720 if ((blob == (const void *) NULL) || (length == 0))
2722 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2723 "UnrecognizedImageFormat","`%s'",image_info->magick);
2724 return((Image *) NULL);
2726 ping_info=CloneImageInfo(image_info);
2727 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2728 if (ping_info->blob == (const void *) NULL)
2730 (void) ThrowMagickException(exception,GetMagickModule(),
2731 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2732 return((Image *) NULL);
2734 (void) memcpy(ping_info->blob,blob,length);
2735 ping_info->length=length;
2736 ping_info->ping=MagickTrue;
2737 image=ReadStream(ping_info,&PingStream,exception);
2738 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2739 ping_info=DestroyImageInfo(ping_info);
2744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2754 % ReadBlob() reads data from the blob or image file and returns it. It
2755 % returns the number of bytes read. If length is zero, ReadBlob() returns
2756 % zero and has no other results. If length is greater than SSIZE_MAX, the
2757 % result is unspecified.
2759 % The format of the ReadBlob method is:
2761 % ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2763 % A description of each parameter follows:
2765 % o image: the image.
2767 % o length: Specifies an integer representing the number of bytes to read
2770 % o data: Specifies an area to place the information requested from the
2774 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2775 unsigned char *data)
2780 register unsigned char
2786 assert(image != (Image *) NULL);
2787 assert(image->signature == MagickSignature);
2788 assert(image->blob != (BlobInfo *) NULL);
2789 assert(image->blob->type != UndefinedStream);
2792 assert(data != (void *) NULL);
2795 switch (image->blob->type)
2797 case UndefinedStream:
2799 case StandardStream:
2804 for (i=0; i < (ssize_t) length; i+=count)
2806 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
2807 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2825 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
2830 c=getc(image->blob->file_info.file);
2833 *q++=(unsigned char) c;
2838 c=getc(image->blob->file_info.file);
2841 *q++=(unsigned char) c;
2851 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2856 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
2857 (unsigned int) length);
2862 c=gzgetc(image->blob->file_info.gzfile);
2865 *q++=(unsigned char) c;
2870 c=gzgetc(image->blob->file_info.gzfile);
2873 *q++=(unsigned char) c;
2884 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2885 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
2893 register const unsigned char
2896 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2898 image->blob->eof=MagickTrue;
2901 p=image->blob->data+image->blob->offset;
2902 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2903 image->blob->offset));
2904 image->blob->offset+=count;
2905 if (count != (ssize_t) length)
2906 image->blob->eof=MagickTrue;
2907 (void) memcpy(q,p,(size_t) count);
2915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2919 + R e a d B l o b B y t e %
2923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2925 % ReadBlobByte() reads a single byte from the image file and returns it.
2927 % The format of the ReadBlobByte method is:
2929 % int ReadBlobByte(Image *image)
2931 % A description of each parameter follows.
2933 % o image: the image.
2936 MagickExport int ReadBlobByte(Image *image)
2938 register const unsigned char
2947 assert(image != (Image *) NULL);
2948 assert(image->signature == MagickSignature);
2949 p=ReadBlobStream(image,1,buffer,&count);
2956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2960 + R e a d B l o b D o u b l e %
2964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2966 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2967 % specified by the endian member of the image structure.
2969 % The format of the ReadBlobDouble method is:
2971 % double ReadBlobDouble(Image *image)
2973 % A description of each parameter follows.
2975 % o image: the image.
2978 MagickExport double ReadBlobDouble(Image *image)
2989 quantum.double_value=0.0;
2990 quantum.unsigned_value=ReadBlobLongLong(image);
2991 return(quantum.double_value);
2995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2999 + R e a d B l o b F l o a t %
3003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3005 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3006 % specified by the endian member of the image structure.
3008 % The format of the ReadBlobFloat method is:
3010 % float ReadBlobFloat(Image *image)
3012 % A description of each parameter follows.
3014 % o image: the image.
3017 MagickExport float ReadBlobFloat(Image *image)
3028 quantum.float_value=0.0;
3029 quantum.unsigned_value=ReadBlobLong(image);
3030 return(quantum.float_value);
3034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3038 + R e a d B l o b L o n g %
3042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3044 % ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
3045 % specified by the endian member of the image structure.
3047 % The format of the ReadBlobLong method is:
3049 % unsigned int ReadBlobLong(Image *image)
3051 % A description of each parameter follows.
3053 % o image: the image.
3056 MagickExport unsigned int ReadBlobLong(Image *image)
3058 register const unsigned char
3070 assert(image != (Image *) NULL);
3071 assert(image->signature == MagickSignature);
3073 p=ReadBlobStream(image,4,buffer,&count);
3076 if (image->endian == LSBEndian)
3078 value=(unsigned int) (*p++);
3079 value|=((unsigned int) (*p++)) << 8;
3080 value|=((unsigned int) (*p++)) << 16;
3081 value|=((unsigned int) (*p++)) << 24;
3084 value=((unsigned int) (*p++)) << 24;
3085 value|=((unsigned int) (*p++)) << 16;
3086 value|=((unsigned int) (*p++)) << 8;
3087 value|=((unsigned int) (*p++));
3092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3096 + R e a d B l o b L o n g L o n g %
3100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3102 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3103 % byte-order specified by the endian member of the image structure.
3105 % The format of the ReadBlobLongLong method is:
3107 % MagickSizeType ReadBlobLongLong(Image *image)
3109 % A description of each parameter follows.
3111 % o image: the image.
3114 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3119 register const unsigned char
3128 assert(image != (Image *) NULL);
3129 assert(image->signature == MagickSignature);
3131 p=ReadBlobStream(image,8,buffer,&count);
3133 return(MagickULLConstant(0));
3134 if (image->endian == LSBEndian)
3136 value=(MagickSizeType) (*p++);
3137 value|=((MagickSizeType) (*p++)) << 8;
3138 value|=((MagickSizeType) (*p++)) << 16;
3139 value|=((MagickSizeType) (*p++)) << 24;
3140 value|=((MagickSizeType) (*p++)) << 32;
3141 value|=((MagickSizeType) (*p++)) << 40;
3142 value|=((MagickSizeType) (*p++)) << 48;
3143 value|=((MagickSizeType) (*p++)) << 56;
3144 return(value & MagickULLConstant(0xffffffffffffffff));
3146 value=((MagickSizeType) (*p++)) << 56;
3147 value|=((MagickSizeType) (*p++)) << 48;
3148 value|=((MagickSizeType) (*p++)) << 40;
3149 value|=((MagickSizeType) (*p++)) << 32;
3150 value|=((MagickSizeType) (*p++)) << 24;
3151 value|=((MagickSizeType) (*p++)) << 16;
3152 value|=((MagickSizeType) (*p++)) << 8;
3153 value|=((MagickSizeType) (*p++));
3154 return(value & MagickULLConstant(0xffffffffffffffff));
3158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3162 + R e a d B l o b S h o r t %
3166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3168 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3169 % specified by the endian member of the image structure.
3171 % The format of the ReadBlobShort method is:
3173 % unsigned short ReadBlobShort(Image *image)
3175 % A description of each parameter follows.
3177 % o image: the image.
3180 MagickExport unsigned short ReadBlobShort(Image *image)
3182 register const unsigned char
3185 register unsigned int
3194 assert(image != (Image *) NULL);
3195 assert(image->signature == MagickSignature);
3197 p=ReadBlobStream(image,2,buffer,&count);
3199 return((unsigned short) 0U);
3200 if (image->endian == LSBEndian)
3202 value=(unsigned int) (*p++);
3203 value|=((unsigned int) (*p++)) << 8;
3204 return((unsigned short) (value & 0xffff));
3206 value=(unsigned int) ((*p++) << 8);
3207 value|=(unsigned int) (*p++);
3208 return((unsigned short) (value & 0xffff));
3212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3216 + R e a d B l o b L S B L o n g %
3220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3222 % ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
3223 % least-significant byte first order.
3225 % The format of the ReadBlobLSBLong method is:
3227 % unsigned int ReadBlobLSBLong(Image *image)
3229 % A description of each parameter follows.
3231 % o image: the image.
3234 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3236 register const unsigned char
3239 register unsigned int
3248 assert(image != (Image *) NULL);
3249 assert(image->signature == MagickSignature);
3251 p=ReadBlobStream(image,4,buffer,&count);
3254 value=(unsigned int) (*p++);
3255 value|=((unsigned int) (*p++)) << 8;
3256 value|=((unsigned int) (*p++)) << 16;
3257 value|=((unsigned int) (*p++)) << 24;
3262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3266 + R e a d B l o b L S B S h o r t %
3270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3272 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3273 % least-significant byte first order.
3275 % The format of the ReadBlobLSBShort method is:
3277 % unsigned short ReadBlobLSBShort(Image *image)
3279 % A description of each parameter follows.
3281 % o image: the image.
3284 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3286 register const unsigned char
3289 register unsigned int
3298 assert(image != (Image *) NULL);
3299 assert(image->signature == MagickSignature);
3301 p=ReadBlobStream(image,2,buffer,&count);
3303 return((unsigned short) 0U);
3304 value=(unsigned int) (*p++);
3305 value|=((unsigned int) ((*p++)) << 8);
3306 return((unsigned short) (value & 0xffff));
3310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3314 + R e a d B l o b M S B L o n g %
3318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3320 % ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
3321 % most-significant byte first order.
3323 % The format of the ReadBlobMSBLong method is:
3325 % unsigned int ReadBlobMSBLong(Image *image)
3327 % A description of each parameter follows.
3329 % o image: the image.
3332 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3334 register const unsigned char
3337 register unsigned int
3346 assert(image != (Image *) NULL);
3347 assert(image->signature == MagickSignature);
3349 p=ReadBlobStream(image,4,buffer,&count);
3352 value=((unsigned int) (*p++) << 24);
3353 value|=((unsigned int) (*p++) << 16);
3354 value|=((unsigned int) (*p++) << 8);
3355 value|=(unsigned int) (*p++);
3360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3364 + R e a d B l o b M S B L o n g L o n g %
3368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3370 % ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
3371 % most-significant byte first order.
3373 % The format of the ReadBlobMSBLongLong method is:
3375 % unsigned int ReadBlobMSBLongLong(Image *image)
3377 % A description of each parameter follows.
3379 % o image: the image.
3382 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3384 register const unsigned char
3387 register MagickSizeType
3396 assert(image != (Image *) NULL);
3397 assert(image->signature == MagickSignature);
3399 p=ReadBlobStream(image,8,buffer,&count);
3401 return(MagickULLConstant(0));
3402 value=((MagickSizeType) (*p++)) << 56;
3403 value|=((MagickSizeType) (*p++)) << 48;
3404 value|=((MagickSizeType) (*p++)) << 40;
3405 value|=((MagickSizeType) (*p++)) << 32;
3406 value|=((MagickSizeType) (*p++)) << 24;
3407 value|=((MagickSizeType) (*p++)) << 16;
3408 value|=((MagickSizeType) (*p++)) << 8;
3409 value|=((MagickSizeType) (*p++));
3410 return(value & MagickULLConstant(0xffffffffffffffff));
3414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3418 + R e a d B l o b M S B S h o r t %
3422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3424 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3425 % most-significant byte first order.
3427 % The format of the ReadBlobMSBShort method is:
3429 % unsigned short ReadBlobMSBShort(Image *image)
3431 % A description of each parameter follows.
3433 % o image: the image.
3436 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3438 register const unsigned char
3441 register unsigned int
3450 assert(image != (Image *) NULL);
3451 assert(image->signature == MagickSignature);
3453 p=ReadBlobStream(image,2,buffer,&count);
3455 return((unsigned short) 0U);
3456 value=(unsigned int) ((*p++) << 8);
3457 value|=(unsigned int) (*p++);
3458 return((unsigned short) (value & 0xffff));
3462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3466 + R e a d B l o b S t r i n g %
3470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3472 % ReadBlobString() reads characters from a blob or file until a newline
3473 % character is read or an end-of-file condition is encountered.
3475 % The format of the ReadBlobString method is:
3477 % char *ReadBlobString(Image *image,char *string)
3479 % A description of each parameter follows:
3481 % o image: the image.
3483 % o string: the address of a character buffer.
3486 MagickExport char *ReadBlobString(Image *image,char *string)
3488 register const unsigned char
3500 assert(image != (Image *) NULL);
3501 assert(image->signature == MagickSignature);
3502 for (i=0; i < (MaxTextExtent-1L); i++)
3504 p=ReadBlobStream(image,1,buffer,&count);
3508 return((char *) NULL);
3511 string[i]=(char) (*p);
3512 if ((string[i] == '\r') || (string[i] == '\n'))
3515 if (string[i] == '\r')
3516 (void) ReadBlobStream(image,1,buffer,&count);
3522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3526 + R e f e r e n c e B l o b %
3530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3532 % ReferenceBlob() increments the reference count associated with the pixel
3533 % blob returning a pointer to the blob.
3535 % The format of the ReferenceBlob method is:
3537 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
3539 % A description of each parameter follows:
3541 % o blob_info: the blob_info.
3544 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3546 assert(blob != (BlobInfo *) NULL);
3547 assert(blob->signature == MagickSignature);
3548 if (blob->debug != MagickFalse)
3549 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3550 LockSemaphoreInfo(blob->semaphore);
3551 blob->reference_count++;
3552 UnlockSemaphoreInfo(blob->semaphore);
3557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3567 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
3568 % and returns the resulting offset.
3570 % The format of the SeekBlob method is:
3572 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3575 % A description of each parameter follows:
3577 % o image: the image.
3579 % o offset: Specifies an integer representing the offset in bytes.
3581 % o whence: Specifies an integer representing how the offset is
3582 % treated relative to the beginning of the blob as follows:
3584 % SEEK_SET Set position equal to offset bytes.
3585 % SEEK_CUR Set position to current location plus offset.
3586 % SEEK_END Set position to EOF plus offset.
3589 MagickExport MagickOffsetType SeekBlob(Image *image,
3590 const MagickOffsetType offset,const int whence)
3592 assert(image != (Image *) NULL);
3593 assert(image->signature == MagickSignature);
3594 if (image->debug != MagickFalse)
3595 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3596 assert(image->blob != (BlobInfo *) NULL);
3597 assert(image->blob->type != UndefinedStream);
3598 switch (image->blob->type)
3600 case UndefinedStream:
3602 case StandardStream:
3606 if ((whence == SEEK_SET) && (offset < 0))
3608 if (fseek(image->blob->file_info.file,offset,whence) < 0)
3610 image->blob->offset=TellBlob(image);
3616 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3617 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
3620 image->blob->offset=TellBlob(image);
3636 image->blob->offset=offset;
3641 if ((image->blob->offset+offset) < 0)
3643 image->blob->offset+=offset;
3648 if (((MagickOffsetType) image->blob->length+offset) < 0)
3650 image->blob->offset=image->blob->length+offset;
3654 if (image->blob->offset <= (MagickOffsetType)
3655 ((off_t) image->blob->length))
3656 image->blob->eof=MagickFalse;
3658 if (image->blob->mapped != MagickFalse)
3662 image->blob->extent=(size_t) (image->blob->offset+
3663 image->blob->quantum);
3664 image->blob->quantum<<=1;
3665 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3666 image->blob->data,image->blob->extent+1,
3667 sizeof(*image->blob->data));
3668 (void) SyncBlob(image);
3669 if (image->blob->data == (unsigned char *) NULL)
3671 (void) DetachBlob(image->blob);
3678 return(image->blob->offset);
3682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3686 + S e t B l o b E x e m p t %
3690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3692 % SetBlobExempt() sets the blob exempt status.
3694 % The format of the SetBlobExempt method is:
3696 % MagickBooleanType SetBlobExempt(const Image *image,
3697 % const MagickBooleanType exempt)
3699 % A description of each parameter follows:
3701 % o image: the image.
3703 % o exempt: Set to true if this blob is exempt from being closed.
3706 MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3708 assert(image != (const Image *) NULL);
3709 assert(image->signature == MagickSignature);
3710 if (image->debug != MagickFalse)
3711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3712 image->blob->exempt=exempt;
3716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3720 + S e t B l o b E x t e n t %
3724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3726 % SetBlobExtent() ensures enough space is allocated for the blob. If the
3727 % method is successful, subsequent writes to bytes in the specified range are
3728 % guaranteed not to fail.
3730 % The format of the SetBlobExtent method is:
3732 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3734 % A description of each parameter follows:
3736 % o image: the image.
3738 % o extent: the blob maximum extent.
3741 MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
3742 const MagickSizeType extent)
3744 assert(image != (Image *) NULL);
3745 assert(image->signature == MagickSignature);
3746 if (image->debug != MagickFalse)
3747 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3748 assert(image->blob != (BlobInfo *) NULL);
3749 assert(image->blob->type != UndefinedStream);
3750 switch (image->blob->type)
3752 case UndefinedStream:
3754 case StandardStream:
3755 return(MagickFalse);
3764 if (extent != (MagickSizeType) ((off_t) extent))
3765 return(MagickFalse);
3766 offset=SeekBlob(image,0,SEEK_END);
3768 return(MagickFalse);
3769 if ((MagickSizeType) offset >= extent)
3771 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3772 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3773 image->blob->file_info.file);
3774 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3775 if (image->blob->synchronize != MagickFalse)
3781 file=fileno(image->blob->file_info.file);
3782 if ((file == -1) || (offset < 0))
3783 return(MagickFalse);
3784 status=posix_fallocate(file,offset,extent-offset);
3786 return(MagickFalse);
3789 offset=SeekBlob(image,offset,SEEK_SET);
3791 return(MagickFalse);
3796 return(MagickFalse);
3798 return(MagickFalse);
3800 return(MagickFalse);
3803 if (extent != (MagickSizeType) ((size_t) extent))
3804 return(MagickFalse);
3805 if (image->blob->mapped != MagickFalse)
3813 (void) UnmapBlob(image->blob->data,image->blob->length);
3814 RelinquishMagickResource(MapResource,image->blob->length);
3815 if (extent != (MagickSizeType) ((off_t) extent))
3816 return(MagickFalse);
3817 offset=SeekBlob(image,0,SEEK_END);
3819 return(MagickFalse);
3820 if ((MagickSizeType) offset >= extent)
3822 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3823 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3824 image->blob->file_info.file);
3825 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3826 if (image->blob->synchronize != MagickFalse)
3832 file=fileno(image->blob->file_info.file);
3833 if ((file == -1) || (offset < 0))
3834 return(MagickFalse);
3835 status=posix_fallocate(file,offset,extent-offset);
3837 return(MagickFalse);
3840 offset=SeekBlob(image,offset,SEEK_SET);
3842 return(MagickFalse);
3843 (void) AcquireMagickResource(MapResource,extent);
3844 image->blob->data=(unsigned char*) MapBlob(fileno(
3845 image->blob->file_info.file),WriteMode,0,(size_t) extent);
3846 image->blob->extent=(size_t) extent;
3847 image->blob->length=(size_t) extent;
3848 (void) SyncBlob(image);
3851 image->blob->extent=(size_t) extent;
3852 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3853 image->blob->extent+1,sizeof(*image->blob->data));
3854 (void) SyncBlob(image);
3855 if (image->blob->data == (unsigned char *) NULL)
3857 (void) DetachBlob(image->blob);
3858 return(MagickFalse);
3867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3877 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
3878 % attributes if it is an blob.
3880 % The format of the SyncBlob method is:
3882 % int SyncBlob(Image *image)
3884 % A description of each parameter follows:
3886 % o image: the image.
3889 static int SyncBlob(Image *image)
3894 assert(image != (Image *) NULL);
3895 assert(image->signature == MagickSignature);
3896 if (image->debug != MagickFalse)
3897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3898 assert(image->blob != (BlobInfo *) NULL);
3899 assert(image->blob->type != UndefinedStream);
3901 switch (image->blob->type)
3903 case UndefinedStream:
3904 case StandardStream:
3909 status=fflush(image->blob->file_info.file);
3914 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3915 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
3921 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3922 status=BZ2_bzflush(image->blob->file_info.bzfile);
3935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3945 % TellBlob() obtains the current value of the blob or file position.
3947 % The format of the TellBlob method is:
3949 % MagickOffsetType TellBlob(const Image *image)
3951 % A description of each parameter follows:
3953 % o image: the image.
3956 MagickExport MagickOffsetType TellBlob(const Image *image)
3961 assert(image != (Image *) NULL);
3962 assert(image->signature == MagickSignature);
3963 if (image->debug != MagickFalse)
3964 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3965 assert(image->blob != (BlobInfo *) NULL);
3966 assert(image->blob->type != UndefinedStream);
3968 switch (image->blob->type)
3970 case UndefinedStream:
3971 case StandardStream:
3975 offset=ftell(image->blob->file_info.file);
3982 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3983 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
3993 offset=image->blob->offset;
4001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4005 + U n m a p B l o b %
4009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4011 % UnmapBlob() deallocates the binary large object previously allocated with
4012 % the MapBlob method.
4014 % The format of the UnmapBlob method is:
4016 % MagickBooleanType UnmapBlob(void *map,const size_t length)
4018 % A description of each parameter follows:
4020 % o map: the address of the binary large object.
4022 % o length: the length of the binary large object.
4025 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4027 #if defined(MAGICKCORE_HAVE_MMAP)
4031 status=munmap(map,length);
4032 return(status == -1 ? MagickFalse : MagickTrue);
4036 return(MagickFalse);
4041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4045 + W r i t e B l o b %
4049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4051 % WriteBlob() writes data to a blob or image file. It returns the number of
4054 % The format of the WriteBlob method is:
4056 % ssize_t WriteBlob(Image *image,const size_t length,
4057 % const unsigned char *data)
4059 % A description of each parameter follows:
4061 % o image: the image.
4063 % o length: Specifies an integer representing the number of bytes to
4064 % write to the file.
4066 % o data: The address of the data to write to the blob or file.
4069 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4070 const unsigned char *data)
4075 register const unsigned char
4081 assert(image != (Image *) NULL);
4082 assert(image->signature == MagickSignature);
4083 assert(data != (const unsigned char *) NULL);
4084 assert(image->blob != (BlobInfo *) NULL);
4085 assert(image->blob->type != UndefinedStream);
4090 switch (image->blob->type)
4092 case UndefinedStream:
4094 case StandardStream:
4096 count=write(fileno(image->blob->file_info.file),data,length);
4106 count=(ssize_t) fwrite((const char *) data,1,length,
4107 image->blob->file_info.file);
4112 c=putc((int) *p++,image->blob->file_info.file);
4119 c=putc((int) *p++,image->blob->file_info.file);
4131 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4136 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
4137 (unsigned int) length);
4142 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4149 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4162 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4163 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
4170 count=(ssize_t) image->blob->stream(image,data,length);
4175 register unsigned char
4178 if ((image->blob->offset+(MagickOffsetType) length) >=
4179 (MagickOffsetType) image->blob->extent)
4181 if (image->blob->mapped != MagickFalse)
4183 image->blob->extent+=length+image->blob->quantum;
4184 image->blob->quantum<<=1;
4185 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4186 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4187 (void) SyncBlob(image);
4188 if (image->blob->data == (unsigned char *) NULL)
4190 (void) DetachBlob(image->blob);
4194 q=image->blob->data+image->blob->offset;
4195 (void) memcpy(q,p,length);
4196 image->blob->offset+=length;
4197 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4198 image->blob->length=(size_t) image->blob->offset;
4199 count=(ssize_t) length;
4206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4210 + W r i t e B l o b B y t e %
4214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4216 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
4217 % written (either 0 or 1);
4219 % The format of the WriteBlobByte method is:
4221 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
4223 % A description of each parameter follows.
4225 % o image: the image.
4227 % o value: Specifies the value to write.
4230 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4232 assert(image != (Image *) NULL);
4233 assert(image->signature == MagickSignature);
4234 return(WriteBlobStream(image,1,&value));
4238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4242 + W r i t e B l o b F l o a t %
4246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4248 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4249 % specified by the endian member of the image structure.
4251 % The format of the WriteBlobFloat method is:
4253 % ssize_t WriteBlobFloat(Image *image,const float value)
4255 % A description of each parameter follows.
4257 % o image: the image.
4259 % o value: Specifies the value to write.
4262 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4273 quantum.unsigned_value=0U;
4274 quantum.float_value=value;
4275 return(WriteBlobLong(image,quantum.unsigned_value));
4279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4283 + W r i t e B l o b L o n g %
4287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4289 % WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
4290 % specified by the endian member of the image structure.
4292 % The format of the WriteBlobLong method is:
4294 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
4296 % A description of each parameter follows.
4298 % o image: the image.
4300 % o value: Specifies the value to write.
4303 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4308 assert(image != (Image *) NULL);
4309 assert(image->signature == MagickSignature);
4310 if (image->endian == LSBEndian)
4312 buffer[0]=(unsigned char) value;
4313 buffer[1]=(unsigned char) (value >> 8);
4314 buffer[2]=(unsigned char) (value >> 16);
4315 buffer[3]=(unsigned char) (value >> 24);
4316 return(WriteBlobStream(image,4,buffer));
4318 buffer[0]=(unsigned char) (value >> 24);
4319 buffer[1]=(unsigned char) (value >> 16);
4320 buffer[2]=(unsigned char) (value >> 8);
4321 buffer[3]=(unsigned char) value;
4322 return(WriteBlobStream(image,4,buffer));
4326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4330 + W r i t e B l o b S h o r t %
4334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4336 % WriteBlobShort() writes a short value as a 16-bit quantity in the
4337 % byte-order specified by the endian member of the image structure.
4339 % The format of the WriteBlobShort method is:
4341 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
4343 % A description of each parameter follows.
4345 % o image: the image.
4347 % o value: Specifies the value to write.
4350 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4355 assert(image != (Image *) NULL);
4356 assert(image->signature == MagickSignature);
4357 if (image->endian == LSBEndian)
4359 buffer[0]=(unsigned char) value;
4360 buffer[1]=(unsigned char) (value >> 8);
4361 return(WriteBlobStream(image,2,buffer));
4363 buffer[0]=(unsigned char) (value >> 8);
4364 buffer[1]=(unsigned char) value;
4365 return(WriteBlobStream(image,2,buffer));
4369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4373 + W r i t e B l o b L S B L o n g %
4377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4379 % WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
4380 % least-significant byte first order.
4382 % The format of the WriteBlobLSBLong method is:
4384 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4386 % A description of each parameter follows.
4388 % o image: the image.
4390 % o value: Specifies the value to write.
4393 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4398 assert(image != (Image *) NULL);
4399 assert(image->signature == MagickSignature);
4400 buffer[0]=(unsigned char) value;
4401 buffer[1]=(unsigned char) (value >> 8);
4402 buffer[2]=(unsigned char) (value >> 16);
4403 buffer[3]=(unsigned char) (value >> 24);
4404 return(WriteBlobStream(image,4,buffer));
4408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4412 + W r i t e B l o b L S B S h o r t %
4416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4418 % WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
4419 % least-significant byte first order.
4421 % The format of the WriteBlobLSBShort method is:
4423 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4425 % A description of each parameter follows.
4427 % o image: the image.
4429 % o value: Specifies the value to write.
4432 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4437 assert(image != (Image *) NULL);
4438 assert(image->signature == MagickSignature);
4439 buffer[0]=(unsigned char) value;
4440 buffer[1]=(unsigned char) (value >> 8);
4441 return(WriteBlobStream(image,2,buffer));
4445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4449 + W r i t e B l o b M S B L o n g %
4453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4455 % WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
4456 % most-significant byte first order.
4458 % The format of the WriteBlobMSBLong method is:
4460 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4462 % A description of each parameter follows.
4464 % o value: Specifies the value to write.
4466 % o image: the image.
4469 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4474 assert(image != (Image *) NULL);
4475 assert(image->signature == MagickSignature);
4476 buffer[0]=(unsigned char) (value >> 24);
4477 buffer[1]=(unsigned char) (value >> 16);
4478 buffer[2]=(unsigned char) (value >> 8);
4479 buffer[3]=(unsigned char) value;
4480 return(WriteBlobStream(image,4,buffer));
4484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4488 + W r i t e B l o b M S B L o n g L o n g %
4492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4494 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4495 % most-significant byte first order.
4497 % The format of the WriteBlobMSBLongLong method is:
4499 % ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4501 % A description of each parameter follows.
4503 % o value: Specifies the value to write.
4505 % o image: the image.
4508 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4509 const MagickSizeType value)
4514 assert(image != (Image *) NULL);
4515 assert(image->signature == MagickSignature);
4516 buffer[0]=(unsigned char) (value >> 56);
4517 buffer[1]=(unsigned char) (value >> 48);
4518 buffer[2]=(unsigned char) (value >> 40);
4519 buffer[3]=(unsigned char) (value >> 32);
4520 buffer[4]=(unsigned char) (value >> 24);
4521 buffer[5]=(unsigned char) (value >> 16);
4522 buffer[6]=(unsigned char) (value >> 8);
4523 buffer[7]=(unsigned char) value;
4524 return(WriteBlobStream(image,8,buffer));
4528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4532 + W r i t e B l o b M S B S h o r t %
4536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4538 % WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
4539 % most-significant byte first order.
4541 % The format of the WriteBlobMSBShort method is:
4543 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4545 % A description of each parameter follows.
4547 % o value: Specifies the value to write.
4549 % o file: Specifies the file to write the data to.
4552 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4557 assert(image != (Image *) NULL);
4558 assert(image->signature == MagickSignature);
4559 buffer[0]=(unsigned char) (value >> 8);
4560 buffer[1]=(unsigned char) value;
4561 return(WriteBlobStream(image,2,buffer));
4565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4569 + W r i t e B l o b S t r i n g %
4573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4575 % WriteBlobString() write a string to a blob. It returns the number of
4576 % characters written.
4578 % The format of the WriteBlobString method is:
4580 % ssize_t WriteBlobString(Image *image,const char *string)
4582 % A description of each parameter follows.
4584 % o image: the image.
4586 % o string: Specifies the string to write.
4589 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4591 assert(image != (Image *) NULL);
4592 assert(image->signature == MagickSignature);
4593 assert(string != (const char *) NULL);
4594 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));