2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 % BBBB LLLLL OOO BBBB %
13 % MagickCore Binary Large OBjectS Methods %
20 % Copyright 1999-2015 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 a s s o c i a t e B l o b %
720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 % DisassociateBlob() disassociates the image stream. It checks if the
723 % blob of the specified image is referenced by other images. If the reference
724 % count is higher then 1 a new blob is assigned to the specified image.
726 % The format of the DisassociateBlob method is:
728 % void DisassociateBlob(const Image *image)
730 % A description of each parameter follows:
732 % o image: the image.
735 MagickPrivate void DisassociateBlob(Image *image)
743 assert(image != (Image *) NULL);
744 assert(image->signature == MagickSignature);
745 if (image->debug != MagickFalse)
746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
747 assert(image->blob != (BlobInfo *) NULL);
748 assert(image->blob->signature == MagickSignature);
750 LockSemaphoreInfo(image->blob->semaphore);
751 assert(image->blob->reference_count >= 0);
752 if (image->blob->reference_count > 1)
754 UnlockSemaphoreInfo(image->blob->semaphore);
755 if (clone == MagickFalse)
757 blob=CloneBlobInfo(image->blob);
763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 + D i s c a r d B l o b B y t e s %
771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
773 % DiscardBlobBytes() discards bytes in a blob.
775 % The format of the DiscardBlobBytes method is:
777 % MagickBooleanType DiscardBlobBytes(Image *image,
778 % const MagickSizeType length)
780 % A description of each parameter follows.
782 % o image: the image.
784 % o length: the number of bytes to skip.
788 static inline const unsigned char *ReadBlobStream(Image *image,
789 const size_t length,unsigned char *data,ssize_t *count)
791 assert(count != (ssize_t *) NULL);
792 assert(image->blob != (BlobInfo *) NULL);
793 if (image->blob->type != BlobStream)
795 *count=ReadBlob(image,length,data);
798 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
801 image->blob->eof=MagickTrue;
804 data=image->blob->data+image->blob->offset;
805 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
806 image->blob->offset));
807 image->blob->offset+=(*count);
808 if (*count != (ssize_t) length)
809 image->blob->eof=MagickTrue;
813 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
814 const MagickSizeType length)
816 register MagickOffsetType
828 assert(image != (Image *) NULL);
829 assert(image->signature == MagickSignature);
831 for (i=0; i < (MagickOffsetType) length; i+=count)
833 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
834 (void) ReadBlobStream(image,quantum,buffer,&count);
842 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 + D u p l i c a t e s B l o b %
854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 % DuplicateBlob() duplicates a blob descriptor.
858 % The format of the DuplicateBlob method is:
860 % void DuplicateBlob(Image *image,const Image *duplicate)
862 % A description of each parameter follows:
864 % o image: the image.
866 % o duplicate: the duplicate image.
869 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
871 assert(image != (Image *) NULL);
872 assert(image->signature == MagickSignature);
873 if (image->debug != MagickFalse)
874 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
875 assert(duplicate != (Image *) NULL);
876 assert(duplicate->signature == MagickSignature);
878 image->blob=ReferenceBlob(duplicate->blob);
882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
892 % EOFBlob() returns a non-zero value when EOF has been detected reading from
895 % The format of the EOFBlob method is:
897 % int EOFBlob(const Image *image)
899 % A description of each parameter follows:
901 % o image: the image.
904 MagickExport int EOFBlob(const Image *image)
906 assert(image != (Image *) NULL);
907 assert(image->signature == MagickSignature);
908 if (image->debug != MagickFalse)
909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
910 assert(image->blob != (BlobInfo *) NULL);
911 assert(image->blob->type != UndefinedStream);
912 switch (image->blob->type)
914 case UndefinedStream:
920 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
926 image->blob->eof=MagickFalse;
931 #if defined(MAGICKCORE_BZLIB_DELEGATE)
936 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
937 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
943 image->blob->eof=MagickFalse;
949 return((int) image->blob->eof);
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957 + F i l e T o B l o b %
961 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963 % FileToBlob() returns the contents of a file as a buffer terminated with
964 % the '\0' character. The length of the buffer (not including the extra
965 % terminating '\0' character) is returned via the 'length' parameter. Free
966 % the buffer with RelinquishMagickMemory().
968 % The format of the FileToBlob method is:
970 % unsigned char *FileToBlob(const char *filename,const size_t extent,
971 % size_t *length,ExceptionInfo *exception)
973 % A description of each parameter follows:
975 % o blob: FileToBlob() returns the contents of a file as a blob. If
976 % an error occurs NULL is returned.
978 % o filename: the filename.
980 % o extent: The maximum length of the blob.
982 % o length: On return, this reflects the actual length of the blob.
984 % o exception: return any errors or warnings in this structure.
987 MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
988 size_t *length,ExceptionInfo *exception)
1008 assert(filename != (const char *) NULL);
1009 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1010 assert(exception != (ExceptionInfo *) NULL);
1013 if (LocaleCompare(filename,"-") != 0)
1014 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1017 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1018 return((unsigned char *) NULL);
1020 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1022 if ((file == fileno(stdin)) || (offset < 0) ||
1023 (offset != (MagickOffsetType) ((ssize_t) offset)))
1032 Stream is not seekable.
1034 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1035 quantum=(size_t) MagickMaxBufferExtent;
1036 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1037 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
1038 MagickMaxBufferExtent);
1039 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1040 for (i=0; blob != (unsigned char *) NULL; i+=count)
1042 count=read(file,blob+i,quantum);
1049 if (~((size_t) i) < (quantum+1))
1051 blob=(unsigned char *) RelinquishMagickMemory(blob);
1054 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1056 if ((size_t) (i+count) >= extent)
1059 if (LocaleCompare(filename,"-") != 0)
1061 if (blob == (unsigned char *) NULL)
1063 (void) ThrowMagickException(exception,GetMagickModule(),
1064 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1065 return((unsigned char *) NULL);
1069 blob=(unsigned char *) RelinquishMagickMemory(blob);
1070 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1071 return((unsigned char *) NULL);
1073 *length=(size_t) MagickMin(i+count,extent);
1077 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
1078 blob=(unsigned char *) NULL;
1079 if (~(*length) >= (MaxTextExtent-1))
1080 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1082 if (blob == (unsigned char *) NULL)
1085 (void) ThrowMagickException(exception,GetMagickModule(),
1086 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1087 return((unsigned char *) NULL);
1089 map=MapBlob(file,ReadMode,0,*length);
1090 if (map != (unsigned char *) NULL)
1092 (void) memcpy(blob,map,*length);
1093 (void) UnmapBlob(map,*length);
1097 (void) lseek(file,0,SEEK_SET);
1098 for (i=0; i < *length; i+=count)
1100 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1112 blob=(unsigned char *) RelinquishMagickMemory(blob);
1113 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1114 return((unsigned char *) NULL);
1118 if (LocaleCompare(filename,"-") != 0)
1122 blob=(unsigned char *) RelinquishMagickMemory(blob);
1123 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1133 % F i l e T o I m a g e %
1137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1139 % FileToImage() write the contents of a file to an image.
1141 % The format of the FileToImage method is:
1143 % MagickBooleanType FileToImage(Image *,const char *filename)
1145 % A description of each parameter follows:
1147 % o image: the image.
1149 % o filename: the filename.
1153 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1154 const unsigned char *data)
1159 register unsigned char
1162 assert(image->blob != (BlobInfo *) NULL);
1163 if (image->blob->type != BlobStream)
1164 return(WriteBlob(image,length,data));
1165 assert(image->blob->type != UndefinedStream);
1166 assert(data != (void *) NULL);
1167 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1168 if (extent >= image->blob->extent)
1170 extent=image->blob->extent+image->blob->quantum+length;
1171 image->blob->quantum<<=1;
1172 if (SetBlobExtent(image,extent) == MagickFalse)
1175 q=image->blob->data+image->blob->offset;
1176 (void) memcpy(q,data,length);
1177 image->blob->offset+=length;
1178 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1179 image->blob->length=(size_t) image->blob->offset;
1180 return((ssize_t) length);
1183 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1184 ExceptionInfo *exception)
1202 assert(image != (const Image *) NULL);
1203 assert(image->signature == MagickSignature);
1204 assert(filename != (const char *) NULL);
1205 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1207 if (LocaleCompare(filename,"-") != 0)
1208 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1211 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1212 return(MagickFalse);
1214 quantum=(size_t) MagickMaxBufferExtent;
1215 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1216 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1217 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1218 if (blob == (unsigned char *) NULL)
1221 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1223 return(MagickFalse);
1227 count=read(file,blob,quantum);
1234 length=(size_t) count;
1235 count=WriteBlobStream(image,length,blob);
1236 if (count != (ssize_t) length)
1238 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1244 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1245 blob=(unsigned char *) RelinquishMagickMemory(blob);
1251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1255 + G e t B l o b E r r o r %
1259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1261 % GetBlobError() returns MagickTrue if the blob associated with the specified
1262 % image encountered an error.
1264 % The format of the GetBlobError method is:
1266 % MagickBooleanType GetBlobError(const Image *image)
1268 % A description of each parameter follows:
1270 % o image: the image.
1273 MagickPrivate MagickBooleanType GetBlobError(const Image *image)
1275 assert(image != (const Image *) NULL);
1276 assert(image->signature == MagickSignature);
1277 if (image->debug != MagickFalse)
1278 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1279 return(image->blob->status);
1283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1287 + G e t B l o b F i l e H a n d l e %
1291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 % GetBlobFileHandle() returns the file handle associated with the image blob.
1295 % The format of the GetBlobFile method is:
1297 % FILE *GetBlobFileHandle(const Image *image)
1299 % A description of each parameter follows:
1301 % o image: the image.
1304 MagickExport FILE *GetBlobFileHandle(const Image *image)
1306 assert(image != (const Image *) NULL);
1307 assert(image->signature == MagickSignature);
1308 return(image->blob->file_info.file);
1312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1316 + G e t B l o b I n f o %
1320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1322 % GetBlobInfo() initializes the BlobInfo structure.
1324 % The format of the GetBlobInfo method is:
1326 % void GetBlobInfo(BlobInfo *blob_info)
1328 % A description of each parameter follows:
1330 % o blob_info: Specifies a pointer to a BlobInfo structure.
1333 MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
1335 assert(blob_info != (BlobInfo *) NULL);
1336 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1337 blob_info->type=UndefinedStream;
1338 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1339 blob_info->properties.st_mtime=time((time_t *) NULL);
1340 blob_info->properties.st_ctime=time((time_t *) NULL);
1341 blob_info->debug=IsEventLogging();
1342 blob_info->reference_count=1;
1343 blob_info->semaphore=AcquireSemaphoreInfo();
1344 blob_info->signature=MagickSignature;
1348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1352 % G e t B l o b P r o p e r t i e s %
1356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358 % GetBlobProperties() returns information about an image blob.
1360 % The format of the GetBlobProperties method is:
1362 % const struct stat *GetBlobProperties(const Image *image)
1364 % A description of each parameter follows:
1366 % o image: the image.
1369 MagickPrivate const struct stat *GetBlobProperties(const Image *image)
1371 assert(image != (Image *) NULL);
1372 assert(image->signature == MagickSignature);
1373 if (image->debug != MagickFalse)
1374 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1375 return(&image->blob->properties);
1379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1383 + G e t B l o b S i z e %
1387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1389 % GetBlobSize() returns the current length of the image file or blob; zero is
1390 % returned if the size cannot be determined.
1392 % The format of the GetBlobSize method is:
1394 % MagickSizeType GetBlobSize(const Image *image)
1396 % A description of each parameter follows:
1398 % o image: the image.
1401 MagickExport MagickSizeType GetBlobSize(const Image *image)
1406 assert(image != (Image *) NULL);
1407 assert(image->signature == MagickSignature);
1408 if (image->debug != MagickFalse)
1409 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1410 assert(image->blob != (BlobInfo *) NULL);
1412 switch (image->blob->type)
1414 case UndefinedStream:
1416 extent=image->blob->size;
1419 case StandardStream:
1421 extent=image->blob->size;
1426 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
1427 extent=(MagickSizeType) image->blob->properties.st_size;
1432 extent=image->blob->size;
1441 status=GetPathAttributes(image->filename,&image->blob->properties);
1442 if (status != MagickFalse)
1443 extent=(MagickSizeType) image->blob->properties.st_size;
1450 extent=(MagickSizeType) image->blob->length;
1458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1462 + G e t B l o b S t r e a m D a t a %
1466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1468 % GetBlobStreamData() returns the stream data for the image.
1470 % The format of the GetBlobStreamData method is:
1472 % unsigned char *GetBlobStreamData(const Image *image)
1474 % A description of each parameter follows:
1476 % o image: the image.
1479 MagickExport unsigned char *GetBlobStreamData(const Image *image)
1481 assert(image != (const Image *) NULL);
1482 assert(image->signature == MagickSignature);
1483 return(image->blob->data);
1487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1491 + G e t B l o b S t r e a m H a n d l e r %
1495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497 % GetBlobStreamHandler() returns the stream handler for the image.
1499 % The format of the GetBlobStreamHandler method is:
1501 % StreamHandler GetBlobStreamHandler(const Image *image)
1503 % A description of each parameter follows:
1505 % o image: the image.
1508 MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
1510 assert(image != (const Image *) NULL);
1511 assert(image->signature == MagickSignature);
1512 if (image->debug != MagickFalse)
1513 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1514 return(image->blob->stream);
1518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1522 % I m a g e T o B l o b %
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528 % ImageToBlob() implements direct to memory image formats. It returns the
1529 % image as a formatted blob and its length. The magick member of the Image
1530 % structure determines the format of the returned blob (GIF, JPEG, PNG,
1531 % etc.). This method is the equivalent of WriteImage(), but writes the
1532 % formatted "file" to a memory buffer rather than to an actual file.
1534 % The format of the ImageToBlob method is:
1536 % unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1537 % size_t *length,ExceptionInfo *exception)
1539 % A description of each parameter follows:
1541 % o image_info: the image info.
1543 % o image: the image.
1545 % o length: return the actual length of the blob.
1547 % o exception: return any errors or warnings in this structure.
1550 MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1551 Image *image,size_t *length,ExceptionInfo *exception)
1565 assert(image_info != (const ImageInfo *) NULL);
1566 assert(image_info->signature == MagickSignature);
1567 if (image_info->debug != MagickFalse)
1568 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1569 image_info->filename);
1570 assert(image != (Image *) NULL);
1571 assert(image->signature == MagickSignature);
1572 assert(exception != (ExceptionInfo *) NULL);
1574 blob=(unsigned char *) NULL;
1575 blob_info=CloneImageInfo(image_info);
1576 blob_info->adjoin=MagickFalse;
1577 (void) SetImageInfo(blob_info,1,exception);
1578 if (*blob_info->magick != '\0')
1579 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1580 magick_info=GetMagickInfo(image->magick,exception);
1581 if (magick_info == (const MagickInfo *) NULL)
1583 (void) ThrowMagickException(exception,GetMagickModule(),
1584 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1586 blob_info=DestroyImageInfo(blob_info);
1589 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1590 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1593 Native blob support for this image format.
1595 blob_info->length=0;
1596 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1597 sizeof(unsigned char));
1598 if (blob_info->blob == (void *) NULL)
1599 (void) ThrowMagickException(exception,GetMagickModule(),
1600 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1603 (void) CloseBlob(image);
1604 image->blob->exempt=MagickTrue;
1605 *image->filename='\0';
1606 status=WriteImage(blob_info,image,exception);
1607 *length=image->blob->length;
1608 blob=DetachBlob(image->blob);
1609 if (status == MagickFalse)
1610 blob=(unsigned char *) RelinquishMagickMemory(blob);
1612 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1619 unique[MaxTextExtent];
1625 Write file to disk in blob image format.
1627 file=AcquireUniqueFileResource(unique);
1630 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1631 image_info->filename);
1635 blob_info->file=fdopen(file,"wb");
1636 if (blob_info->file != (FILE *) NULL)
1638 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
1639 image->magick,unique);
1640 status=WriteImage(blob_info,image,exception);
1641 (void) CloseBlob(image);
1642 (void) fclose(blob_info->file);
1643 if (status != MagickFalse)
1644 blob=FileToBlob(unique,~0UL,length,exception);
1646 (void) RelinquishUniqueFileResource(unique);
1649 blob_info=DestroyImageInfo(blob_info);
1654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658 % I m a g e T o F i l e %
1662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1664 % ImageToFile() writes an image to a file. It returns MagickFalse if an error
1665 % occurs otherwise MagickTrue.
1667 % The format of the ImageToFile method is:
1669 % MagickBooleanType ImageToFile(Image *image,char *filename,
1670 % ExceptionInfo *exception)
1672 % A description of each parameter follows:
1674 % o image: the image.
1676 % o filename: Write the image to this file.
1678 % o exception: return any errors or warnings in this structure.
1681 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1682 ExceptionInfo *exception)
1687 register const unsigned char
1706 assert(image != (Image *) NULL);
1707 assert(image->signature == MagickSignature);
1708 assert(image->blob != (BlobInfo *) NULL);
1709 assert(image->blob->type != UndefinedStream);
1710 if (image->debug != MagickFalse)
1711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1712 assert(filename != (const char *) NULL);
1713 if (*filename == '\0')
1714 file=AcquireUniqueFileResource(filename);
1716 if (LocaleCompare(filename,"-") == 0)
1717 file=fileno(stdout);
1719 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1722 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1723 return(MagickFalse);
1725 quantum=(size_t) MagickMaxBufferExtent;
1726 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1727 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
1728 MagickMaxBufferExtent);
1729 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1730 if (buffer == (unsigned char *) NULL)
1733 (void) ThrowMagickException(exception,GetMagickModule(),
1734 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1735 return(MagickFalse);
1738 p=ReadBlobStream(image,quantum,buffer,&count);
1739 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1741 length=(size_t) count;
1742 for (i=0; i < length; i+=count)
1744 count=write(file,p+i,(size_t) (length-i));
1755 if (LocaleCompare(filename,"-") != 0)
1757 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1758 if ((file == -1) || (i < length))
1762 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1763 return(MagickFalse);
1769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773 % I m a g e s T o B l o b %
1777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1779 % ImagesToBlob() implements direct to memory image formats. It returns the
1780 % image sequence as a blob and its length. The magick member of the ImageInfo
1781 % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1783 % Note, some image formats do not permit multiple images to the same image
1784 % stream (e.g. JPEG). in this instance, just the first image of the
1785 % sequence is returned as a blob.
1787 % The format of the ImagesToBlob method is:
1789 % unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1790 % size_t *length,ExceptionInfo *exception)
1792 % A description of each parameter follows:
1794 % o image_info: the image info.
1796 % o images: the image list.
1798 % o length: return the actual length of the blob.
1800 % o exception: return any errors or warnings in this structure.
1803 MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1804 Image *images,size_t *length,ExceptionInfo *exception)
1818 assert(image_info != (const ImageInfo *) NULL);
1819 assert(image_info->signature == MagickSignature);
1820 if (image_info->debug != MagickFalse)
1821 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1822 image_info->filename);
1823 assert(images != (Image *) NULL);
1824 assert(images->signature == MagickSignature);
1825 assert(exception != (ExceptionInfo *) NULL);
1827 blob=(unsigned char *) NULL;
1828 blob_info=CloneImageInfo(image_info);
1829 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1831 if (*blob_info->magick != '\0')
1832 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1833 magick_info=GetMagickInfo(images->magick,exception);
1834 if (magick_info == (const MagickInfo *) NULL)
1836 (void) ThrowMagickException(exception,GetMagickModule(),
1837 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1839 blob_info=DestroyImageInfo(blob_info);
1842 if (GetMagickAdjoin(magick_info) == MagickFalse)
1844 blob_info=DestroyImageInfo(blob_info);
1845 return(ImageToBlob(image_info,images,length,exception));
1847 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1848 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1851 Native blob support for this images format.
1853 blob_info->length=0;
1854 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1855 sizeof(unsigned char));
1856 if (blob_info->blob == (void *) NULL)
1857 (void) ThrowMagickException(exception,GetMagickModule(),
1858 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1861 (void) CloseBlob(images);
1862 images->blob->exempt=MagickTrue;
1863 *images->filename='\0';
1864 status=WriteImages(blob_info,images,images->filename,exception);
1865 *length=images->blob->length;
1866 blob=DetachBlob(images->blob);
1867 if (status == MagickFalse)
1868 blob=(unsigned char *) RelinquishMagickMemory(blob);
1870 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1877 filename[MaxTextExtent],
1878 unique[MaxTextExtent];
1884 Write file to disk in blob images format.
1886 file=AcquireUniqueFileResource(unique);
1889 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1890 image_info->filename);
1894 blob_info->file=fdopen(file,"wb");
1895 if (blob_info->file != (FILE *) NULL)
1897 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
1898 images->magick,unique);
1899 status=WriteImages(blob_info,images,filename,exception);
1900 (void) CloseBlob(images);
1901 (void) fclose(blob_info->file);
1902 if (status != MagickFalse)
1903 blob=FileToBlob(unique,~0UL,length,exception);
1905 (void) RelinquishUniqueFileResource(unique);
1908 blob_info=DestroyImageInfo(blob_info);
1912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1916 % I n j e c t I m a g e B l o b %
1920 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1922 % InjectImageBlob() injects the image with a copy of itself in the specified
1923 % format (e.g. inject JPEG into a PDF image).
1925 % The format of the InjectImageBlob method is:
1927 % MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1928 % Image *image,Image *inject_image,const char *format,
1929 % ExceptionInfo *exception)
1931 % A description of each parameter follows:
1933 % o image_info: the image info..
1935 % o image: the image.
1937 % o inject_image: inject into the image stream.
1939 % o format: the image format.
1941 % o exception: return any errors or warnings in this structure.
1944 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1945 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1948 filename[MaxTextExtent];
1981 Write inject image to a temporary file.
1983 assert(image_info != (ImageInfo *) NULL);
1984 assert(image_info->signature == MagickSignature);
1985 assert(image != (Image *) NULL);
1986 assert(image->signature == MagickSignature);
1987 if (image->debug != MagickFalse)
1988 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1989 assert(inject_image != (Image *) NULL);
1990 assert(inject_image->signature == MagickSignature);
1991 assert(exception != (ExceptionInfo *) NULL);
1992 unique_file=(FILE *) NULL;
1993 file=AcquireUniqueFileResource(filename);
1995 unique_file=fdopen(file,"wb");
1996 if ((file == -1) || (unique_file == (FILE *) NULL))
1998 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1999 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2001 return(MagickFalse);
2003 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2004 if (byte_image == (Image *) NULL)
2006 (void) fclose(unique_file);
2007 (void) RelinquishUniqueFileResource(filename);
2008 return(MagickFalse);
2010 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
2012 DestroyBlob(byte_image);
2013 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2014 write_info=CloneImageInfo(image_info);
2015 SetImageInfoFile(write_info,unique_file);
2016 status=WriteImage(write_info,byte_image,exception);
2017 write_info=DestroyImageInfo(write_info);
2018 byte_image=DestroyImage(byte_image);
2019 (void) fclose(unique_file);
2020 if (status == MagickFalse)
2022 (void) RelinquishUniqueFileResource(filename);
2023 return(MagickFalse);
2026 Inject into image stream.
2028 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2031 (void) RelinquishUniqueFileResource(filename);
2032 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2033 image_info->filename);
2034 return(MagickFalse);
2036 quantum=(size_t) MagickMaxBufferExtent;
2037 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
2038 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2039 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2040 if (buffer == (unsigned char *) NULL)
2042 (void) RelinquishUniqueFileResource(filename);
2043 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2046 for (i=0; ; i+=count)
2048 count=read(file,buffer,quantum);
2055 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2060 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2061 (void) RelinquishUniqueFileResource(filename);
2062 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2071 + I s B l o b E x e m p t %
2075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2077 % IsBlobExempt() returns true if the blob is exempt.
2079 % The format of the IsBlobExempt method is:
2081 % MagickBooleanType IsBlobExempt(const Image *image)
2083 % A description of each parameter follows:
2085 % o image: the image.
2088 MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
2090 assert(image != (const Image *) NULL);
2091 assert(image->signature == MagickSignature);
2092 if (image->debug != MagickFalse)
2093 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2094 return(image->blob->exempt);
2098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2102 + I s B l o b S e e k a b l e %
2106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2108 % IsBlobSeekable() returns true if the blob is seekable.
2110 % The format of the IsBlobSeekable method is:
2112 % MagickBooleanType IsBlobSeekable(const Image *image)
2114 % A description of each parameter follows:
2116 % o image: the image.
2119 MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
2124 assert(image != (const Image *) NULL);
2125 assert(image->signature == MagickSignature);
2126 if (image->debug != MagickFalse)
2127 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2128 switch (image->blob->type)
2134 seekable=MagickTrue;
2139 seekable=MagickFalse;
2147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2151 + I s B l o b T e m p o r a r y %
2155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2157 % IsBlobTemporary() returns true if the blob is temporary.
2159 % The format of the IsBlobTemporary method is:
2161 % MagickBooleanType IsBlobTemporary(const Image *image)
2163 % A description of each parameter follows:
2165 % o image: the image.
2168 MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
2170 assert(image != (const Image *) NULL);
2171 assert(image->signature == MagickSignature);
2172 if (image->debug != MagickFalse)
2173 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2174 return(image->blob->temporary);
2178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2188 % MapBlob() creates a mapping from a file to a binary large object.
2190 % The format of the MapBlob method is:
2192 % unsigned char *MapBlob(int file,const MapMode mode,
2193 % const MagickOffsetType offset,const size_t length)
2195 % A description of each parameter follows:
2197 % o file: map this file descriptor.
2199 % o mode: ReadMode, WriteMode, or IOMode.
2201 % o offset: starting at this offset within the file.
2203 % o length: the length of the mapping is returned in this pointer.
2206 MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2207 const MagickOffsetType offset,const size_t length)
2209 #if defined(MAGICKCORE_HAVE_MMAP)
2222 #if defined(MAP_ANONYMOUS)
2223 flags|=MAP_ANONYMOUS;
2225 return((unsigned char *) NULL);
2232 protection=PROT_READ;
2238 protection=PROT_WRITE;
2244 protection=PROT_READ | PROT_WRITE;
2249 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2250 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2253 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
2254 MAP_HUGETLB,file,(off_t) offset);
2255 if (map == (unsigned char *) MAP_FAILED)
2256 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2259 if (map == (unsigned char *) MAP_FAILED)
2260 return((unsigned char *) NULL);
2267 return((unsigned char *) NULL);
2272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2276 + M S B O r d e r L o n g %
2280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282 % MSBOrderLong() converts a least-significant byte first buffer of integers to
2283 % most-significant byte first.
2285 % The format of the MSBOrderLong method is:
2287 % void MSBOrderLong(unsigned char *buffer,const size_t length)
2289 % A description of each parameter follows.
2291 % o buffer: Specifies a pointer to a buffer of integers.
2293 % o length: Specifies the length of the buffer.
2296 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2301 register unsigned char
2305 assert(buffer != (unsigned char *) NULL);
2312 *buffer++=(unsigned char) c;
2316 *buffer++=(unsigned char) c;
2322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2326 + M S B O r d e r S h o r t %
2330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2332 % MSBOrderShort() converts a least-significant byte first buffer of integers
2333 % to most-significant byte first.
2335 % The format of the MSBOrderShort method is:
2337 % void MSBOrderShort(unsigned char *p,const size_t length)
2339 % A description of each parameter follows.
2341 % o p: Specifies a pointer to a buffer of integers.
2343 % o length: Specifies the length of the buffer.
2346 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2351 register unsigned char
2354 assert(p != (unsigned char *) NULL);
2361 *p++=(unsigned char) c;
2366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2376 % OpenBlob() opens a file associated with the image. A file name of '-' sets
2377 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
2378 % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2379 % compressed for type 'w'. If the filename prefix is '|', it is piped to or
2380 % from a system command.
2382 % The format of the OpenBlob method is:
2384 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2385 % const BlobMode mode,ExceptionInfo *exception)
2387 % A description of each parameter follows:
2389 % o image_info: the image info.
2391 % o image: the image.
2393 % o mode: the mode for opening the file.
2396 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2397 Image *image,const BlobMode mode,ExceptionInfo *exception)
2400 extension[MaxTextExtent],
2401 filename[MaxTextExtent];
2412 assert(image_info != (ImageInfo *) NULL);
2413 assert(image_info->signature == MagickSignature);
2414 if (image_info->debug != MagickFalse)
2415 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2416 image_info->filename);
2417 assert(image != (Image *) NULL);
2418 assert(image->signature == MagickSignature);
2419 if (image_info->blob != (void *) NULL)
2421 if (image_info->stream != (StreamHandler) NULL)
2422 image->blob->stream=(StreamHandler) image_info->stream;
2423 AttachBlob(image->blob,image_info->blob,image_info->length);
2426 (void) DetachBlob(image->blob);
2429 default: type="r"; break;
2430 case ReadBlobMode: type="r"; break;
2431 case ReadBinaryBlobMode: type="rb"; break;
2432 case WriteBlobMode: type="w"; break;
2433 case WriteBinaryBlobMode: type="w+b"; break;
2434 case AppendBlobMode: type="a"; break;
2435 case AppendBinaryBlobMode: type="a+b"; break;
2438 image->blob->synchronize=image_info->synchronize;
2439 if (image_info->stream != (StreamHandler) NULL)
2441 image->blob->stream=(StreamHandler) image_info->stream;
2444 image->blob->type=FifoStream;
2452 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2453 rights=ReadPolicyRights;
2455 rights=WritePolicyRights;
2456 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2459 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2460 "NotAuthorized","`%s'",filename);
2461 return(MagickFalse);
2463 if ((LocaleCompare(filename,"-") == 0) ||
2464 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2466 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2467 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2468 if (strchr(type,'b') != (char *) NULL)
2469 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2471 image->blob->type=StandardStream;
2472 image->blob->exempt=MagickTrue;
2475 if (LocaleNCompare(filename,"fd:",3) == 0)
2478 mode[MaxTextExtent];
2482 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2483 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2484 if (strchr(type,'b') != (char *) NULL)
2485 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2487 image->blob->type=StandardStream;
2488 image->blob->exempt=MagickTrue;
2491 #if defined(MAGICKCORE_HAVE_POPEN)
2492 if (*filename == '|')
2495 mode[MaxTextExtent];
2498 Pipe image to or from a system command.
2500 #if defined(SIGPIPE)
2502 (void) signal(SIGPIPE,SIG_IGN);
2506 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2507 if (image->blob->file_info.file == (FILE *) NULL)
2509 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2510 return(MagickFalse);
2512 image->blob->type=PipeStream;
2513 image->blob->exempt=MagickTrue;
2517 status=GetPathAttributes(filename,&image->blob->properties);
2518 #if defined(S_ISFIFO)
2519 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
2521 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2522 if (image->blob->file_info.file == (FILE *) NULL)
2524 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2525 return(MagickFalse);
2527 image->blob->type=FileStream;
2528 image->blob->exempt=MagickTrue;
2532 GetPathComponent(image->filename,ExtensionPath,extension);
2535 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2536 if ((image_info->adjoin == MagickFalse) ||
2537 (strchr(filename,'%') != (char *) NULL))
2540 Form filename for multi-part images.
2542 (void) InterpretImageFilename(image_info,image,image->filename,(int)
2543 image->scene,filename,exception);
2544 if ((LocaleCompare(filename,image->filename) == 0) &&
2545 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2546 (GetNextImageInList(image) != (Image *) NULL)))
2549 path[MaxTextExtent];
2551 GetPathComponent(image->filename,RootPath,path);
2552 if (*extension == '\0')
2553 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
2554 path,(double) image->scene);
2556 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
2557 path,(double) image->scene,extension);
2559 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
2560 #if defined(macintosh)
2561 SetApplicationType(filename,image_info->magick,'8BIM');
2565 if (image_info->file != (FILE *) NULL)
2567 image->blob->file_info.file=image_info->file;
2568 image->blob->type=FileStream;
2569 image->blob->exempt=MagickTrue;
2574 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2575 if (image->blob->file_info.file != (FILE *) NULL)
2583 image->blob->type=FileStream;
2584 #if defined(MAGICKCORE_HAVE_SETVBUF)
2585 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2588 (void) ResetMagickMemory(magick,0,sizeof(magick));
2589 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2590 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
2591 (void) fflush(image->blob->file_info.file);
2592 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2593 " read %.20g magic header bytes",(double) count);
2594 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2595 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2596 ((int) magick[2] == 0x08))
2598 if (image->blob->file_info.file != (FILE *) NULL)
2599 (void) fclose(image->blob->file_info.file);
2600 image->blob->file_info.file=(FILE *) NULL;
2601 image->blob->file_info.gzfile=gzopen(filename,type);
2602 if (image->blob->file_info.gzfile != (gzFile) NULL)
2603 image->blob->type=ZipStream;
2606 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2607 if (strncmp((char *) magick,"BZh",3) == 0)
2609 if (image->blob->file_info.file != (FILE *) NULL)
2610 (void) fclose(image->blob->file_info.file);
2611 image->blob->file_info.file=(FILE *) NULL;
2612 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2613 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2614 image->blob->type=BZipStream;
2617 if (image->blob->type == FileStream)
2628 sans_exception=AcquireExceptionInfo();
2629 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2630 sans_exception=DestroyExceptionInfo(sans_exception);
2631 length=(size_t) image->blob->properties.st_size;
2632 if ((magick_info != (const MagickInfo *) NULL) &&
2633 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2634 (length <= MagickMaxBufferExtent) &&
2635 (AcquireMagickResource(MapResource,length) != MagickFalse))
2640 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2642 if (blob == (void *) NULL)
2643 RelinquishMagickResource(MapResource,length);
2647 Format supports blobs-- use memory-mapped I/O.
2649 if (image_info->file != (FILE *) NULL)
2650 image->blob->exempt=MagickFalse;
2653 (void) fclose(image->blob->file_info.file);
2654 image->blob->file_info.file=(FILE *) NULL;
2656 AttachBlob(image->blob,blob,length);
2657 image->blob->mapped=MagickTrue;
2664 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2665 if ((LocaleCompare(extension,"Z") == 0) ||
2666 (LocaleCompare(extension,"gz") == 0) ||
2667 (LocaleCompare(extension,"wmz") == 0) ||
2668 (LocaleCompare(extension,"svgz") == 0))
2670 if (mode == WriteBinaryBlobMode)
2672 image->blob->file_info.gzfile=gzopen(filename,type);
2673 if (image->blob->file_info.gzfile != (gzFile) NULL)
2674 image->blob->type=ZipStream;
2678 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2679 if (LocaleCompare(extension,"bz2") == 0)
2681 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2682 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2683 image->blob->type=BZipStream;
2688 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2689 if (image->blob->file_info.file != (FILE *) NULL)
2691 image->blob->type=FileStream;
2692 #if defined(MAGICKCORE_HAVE_SETVBUF)
2693 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2698 image->blob->status=MagickFalse;
2699 if (image->blob->type != UndefinedStream)
2700 image->blob->size=GetBlobSize(image);
2703 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2704 return(MagickFalse);
2710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2720 % PingBlob() returns all the attributes of an image or image sequence except
2721 % for the pixels. It is much faster and consumes far less memory than
2722 % BlobToImage(). On failure, a NULL image is returned and exception
2723 % describes the reason for the failure.
2725 % The format of the PingBlob method is:
2727 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
2728 % const size_t length,ExceptionInfo *exception)
2730 % A description of each parameter follows:
2732 % o image_info: the image info.
2734 % o blob: the address of a character stream in one of the image formats
2735 % understood by ImageMagick.
2737 % o length: This size_t integer reflects the length in bytes of the blob.
2739 % o exception: return any errors or warnings in this structure.
2743 #if defined(__cplusplus) || defined(c_plusplus)
2747 static size_t PingStream(const Image *magick_unused(image),
2748 const void *magick_unused(pixels),const size_t columns)
2753 #if defined(__cplusplus) || defined(c_plusplus)
2757 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2758 const size_t length,ExceptionInfo *exception)
2766 assert(image_info != (ImageInfo *) NULL);
2767 assert(image_info->signature == MagickSignature);
2768 if (image_info->debug != MagickFalse)
2769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2770 image_info->filename);
2771 assert(exception != (ExceptionInfo *) NULL);
2772 if ((blob == (const void *) NULL) || (length == 0))
2774 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2775 "UnrecognizedImageFormat","`%s'",image_info->magick);
2776 return((Image *) NULL);
2778 ping_info=CloneImageInfo(image_info);
2779 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2780 if (ping_info->blob == (const void *) NULL)
2782 (void) ThrowMagickException(exception,GetMagickModule(),
2783 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2784 return((Image *) NULL);
2786 (void) memcpy(ping_info->blob,blob,length);
2787 ping_info->length=length;
2788 ping_info->ping=MagickTrue;
2789 image=ReadStream(ping_info,&PingStream,exception);
2790 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2791 ping_info=DestroyImageInfo(ping_info);
2796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2806 % ReadBlob() reads data from the blob or image file and returns it. It
2807 % returns the number of bytes read. If length is zero, ReadBlob() returns
2808 % zero and has no other results. If length is greater than SSIZE_MAX, the
2809 % result is unspecified.
2811 % The format of the ReadBlob method is:
2813 % ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2815 % A description of each parameter follows:
2817 % o image: the image.
2819 % o length: Specifies an integer representing the number of bytes to read
2822 % o data: Specifies an area to place the information requested from the
2826 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2827 unsigned char *data)
2832 register unsigned char
2838 assert(image != (Image *) NULL);
2839 assert(image->signature == MagickSignature);
2840 assert(image->blob != (BlobInfo *) NULL);
2841 assert(image->blob->type != UndefinedStream);
2844 assert(data != (void *) NULL);
2847 switch (image->blob->type)
2849 case UndefinedStream:
2851 case StandardStream:
2856 for (i=0; i < (ssize_t) length; i+=count)
2858 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
2859 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2877 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
2882 c=getc(image->blob->file_info.file);
2885 *q++=(unsigned char) c;
2890 c=getc(image->blob->file_info.file);
2893 *q++=(unsigned char) c;
2903 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2908 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
2909 (unsigned int) length);
2914 c=gzgetc(image->blob->file_info.gzfile);
2917 *q++=(unsigned char) c;
2922 c=gzgetc(image->blob->file_info.gzfile);
2925 *q++=(unsigned char) c;
2936 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2937 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
2945 register const unsigned char
2948 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2950 image->blob->eof=MagickTrue;
2953 p=image->blob->data+image->blob->offset;
2954 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2955 image->blob->offset));
2956 image->blob->offset+=count;
2957 if (count != (ssize_t) length)
2958 image->blob->eof=MagickTrue;
2959 (void) memcpy(q,p,(size_t) count);
2967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2971 + R e a d B l o b B y t e %
2975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2977 % ReadBlobByte() reads a single byte from the image file and returns it.
2979 % The format of the ReadBlobByte method is:
2981 % int ReadBlobByte(Image *image)
2983 % A description of each parameter follows.
2985 % o image: the image.
2988 MagickExport int ReadBlobByte(Image *image)
2990 register const unsigned char
2999 assert(image != (Image *) NULL);
3000 assert(image->signature == MagickSignature);
3001 p=ReadBlobStream(image,1,buffer,&count);
3008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3012 + R e a d B l o b D o u b l e %
3016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3018 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3019 % specified by the endian member of the image structure.
3021 % The format of the ReadBlobDouble method is:
3023 % double ReadBlobDouble(Image *image)
3025 % A description of each parameter follows.
3027 % o image: the image.
3030 MagickExport double ReadBlobDouble(Image *image)
3041 quantum.double_value=0.0;
3042 quantum.unsigned_value=ReadBlobLongLong(image);
3043 return(quantum.double_value);
3047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3051 + R e a d B l o b F l o a t %
3055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3057 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3058 % specified by the endian member of the image structure.
3060 % The format of the ReadBlobFloat method is:
3062 % float ReadBlobFloat(Image *image)
3064 % A description of each parameter follows.
3066 % o image: the image.
3069 MagickExport float ReadBlobFloat(Image *image)
3080 quantum.float_value=0.0;
3081 quantum.unsigned_value=ReadBlobLong(image);
3082 return(quantum.float_value);
3086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3090 + R e a d B l o b L o n g %
3094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3096 % ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
3097 % specified by the endian member of the image structure.
3099 % The format of the ReadBlobLong method is:
3101 % unsigned int ReadBlobLong(Image *image)
3103 % A description of each parameter follows.
3105 % o image: the image.
3108 MagickExport unsigned int ReadBlobLong(Image *image)
3110 register const unsigned char
3122 assert(image != (Image *) NULL);
3123 assert(image->signature == MagickSignature);
3125 p=ReadBlobStream(image,4,buffer,&count);
3128 if (image->endian == LSBEndian)
3130 value=(unsigned int) (*p++);
3131 value|=((unsigned int) (*p++)) << 8;
3132 value|=((unsigned int) (*p++)) << 16;
3133 value|=((unsigned int) (*p++)) << 24;
3136 value=((unsigned int) (*p++)) << 24;
3137 value|=((unsigned int) (*p++)) << 16;
3138 value|=((unsigned int) (*p++)) << 8;
3139 value|=((unsigned int) (*p++));
3144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3148 + R e a d B l o b L o n g L o n g %
3152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3154 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3155 % byte-order specified by the endian member of the image structure.
3157 % The format of the ReadBlobLongLong method is:
3159 % MagickSizeType ReadBlobLongLong(Image *image)
3161 % A description of each parameter follows.
3163 % o image: the image.
3166 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3171 register const unsigned char
3180 assert(image != (Image *) NULL);
3181 assert(image->signature == MagickSignature);
3183 p=ReadBlobStream(image,8,buffer,&count);
3185 return(MagickULLConstant(0));
3186 if (image->endian == LSBEndian)
3188 value=(MagickSizeType) (*p++);
3189 value|=((MagickSizeType) (*p++)) << 8;
3190 value|=((MagickSizeType) (*p++)) << 16;
3191 value|=((MagickSizeType) (*p++)) << 24;
3192 value|=((MagickSizeType) (*p++)) << 32;
3193 value|=((MagickSizeType) (*p++)) << 40;
3194 value|=((MagickSizeType) (*p++)) << 48;
3195 value|=((MagickSizeType) (*p++)) << 56;
3196 return(value & MagickULLConstant(0xffffffffffffffff));
3198 value=((MagickSizeType) (*p++)) << 56;
3199 value|=((MagickSizeType) (*p++)) << 48;
3200 value|=((MagickSizeType) (*p++)) << 40;
3201 value|=((MagickSizeType) (*p++)) << 32;
3202 value|=((MagickSizeType) (*p++)) << 24;
3203 value|=((MagickSizeType) (*p++)) << 16;
3204 value|=((MagickSizeType) (*p++)) << 8;
3205 value|=((MagickSizeType) (*p++));
3206 return(value & MagickULLConstant(0xffffffffffffffff));
3210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3214 + R e a d B l o b S h o r t %
3218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3220 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3221 % specified by the endian member of the image structure.
3223 % The format of the ReadBlobShort method is:
3225 % unsigned short ReadBlobShort(Image *image)
3227 % A description of each parameter follows.
3229 % o image: the image.
3232 MagickExport unsigned short ReadBlobShort(Image *image)
3234 register const unsigned char
3237 register unsigned int
3246 assert(image != (Image *) NULL);
3247 assert(image->signature == MagickSignature);
3249 p=ReadBlobStream(image,2,buffer,&count);
3251 return((unsigned short) 0U);
3252 if (image->endian == LSBEndian)
3254 value=(unsigned int) (*p++);
3255 value|=((unsigned int) (*p++)) << 8;
3256 return((unsigned short) (value & 0xffff));
3258 value=(unsigned int) ((*p++) << 8);
3259 value|=(unsigned int) (*p++);
3260 return((unsigned short) (value & 0xffff));
3264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3268 + R e a d B l o b L S B L o n g %
3272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3274 % ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
3275 % least-significant byte first order.
3277 % The format of the ReadBlobLSBLong method is:
3279 % unsigned int ReadBlobLSBLong(Image *image)
3281 % A description of each parameter follows.
3283 % o image: the image.
3286 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3288 register const unsigned char
3291 register unsigned int
3300 assert(image != (Image *) NULL);
3301 assert(image->signature == MagickSignature);
3303 p=ReadBlobStream(image,4,buffer,&count);
3306 value=(unsigned int) (*p++);
3307 value|=((unsigned int) (*p++)) << 8;
3308 value|=((unsigned int) (*p++)) << 16;
3309 value|=((unsigned int) (*p++)) << 24;
3314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3318 + R e a d B l o b L S B S h o r t %
3322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3324 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3325 % least-significant byte first order.
3327 % The format of the ReadBlobLSBShort method is:
3329 % unsigned short ReadBlobLSBShort(Image *image)
3331 % A description of each parameter follows.
3333 % o image: the image.
3336 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3338 register const unsigned char
3341 register unsigned int
3350 assert(image != (Image *) NULL);
3351 assert(image->signature == MagickSignature);
3353 p=ReadBlobStream(image,2,buffer,&count);
3355 return((unsigned short) 0U);
3356 value=(unsigned int) (*p++);
3357 value|=((unsigned int) ((*p++)) << 8);
3358 return((unsigned short) (value & 0xffff));
3362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3366 + R e a d B l o b M S B L o n g %
3370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3372 % ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
3373 % most-significant byte first order.
3375 % The format of the ReadBlobMSBLong method is:
3377 % unsigned int ReadBlobMSBLong(Image *image)
3379 % A description of each parameter follows.
3381 % o image: the image.
3384 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3386 register const unsigned char
3389 register unsigned int
3398 assert(image != (Image *) NULL);
3399 assert(image->signature == MagickSignature);
3401 p=ReadBlobStream(image,4,buffer,&count);
3404 value=((unsigned int) (*p++) << 24);
3405 value|=((unsigned int) (*p++) << 16);
3406 value|=((unsigned int) (*p++) << 8);
3407 value|=(unsigned int) (*p++);
3412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3416 + R e a d B l o b M S B L o n g L o n g %
3420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3422 % ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
3423 % most-significant byte first order.
3425 % The format of the ReadBlobMSBLongLong method is:
3427 % unsigned int ReadBlobMSBLongLong(Image *image)
3429 % A description of each parameter follows.
3431 % o image: the image.
3434 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3436 register const unsigned char
3439 register MagickSizeType
3448 assert(image != (Image *) NULL);
3449 assert(image->signature == MagickSignature);
3451 p=ReadBlobStream(image,8,buffer,&count);
3453 return(MagickULLConstant(0));
3454 value=((MagickSizeType) (*p++)) << 56;
3455 value|=((MagickSizeType) (*p++)) << 48;
3456 value|=((MagickSizeType) (*p++)) << 40;
3457 value|=((MagickSizeType) (*p++)) << 32;
3458 value|=((MagickSizeType) (*p++)) << 24;
3459 value|=((MagickSizeType) (*p++)) << 16;
3460 value|=((MagickSizeType) (*p++)) << 8;
3461 value|=((MagickSizeType) (*p++));
3462 return(value & MagickULLConstant(0xffffffffffffffff));
3466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3470 + R e a d B l o b M S B S h o r t %
3474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3476 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3477 % most-significant byte first order.
3479 % The format of the ReadBlobMSBShort method is:
3481 % unsigned short ReadBlobMSBShort(Image *image)
3483 % A description of each parameter follows.
3485 % o image: the image.
3488 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3490 register const unsigned char
3493 register unsigned int
3502 assert(image != (Image *) NULL);
3503 assert(image->signature == MagickSignature);
3505 p=ReadBlobStream(image,2,buffer,&count);
3507 return((unsigned short) 0U);
3508 value=(unsigned int) ((*p++) << 8);
3509 value|=(unsigned int) (*p++);
3510 return((unsigned short) (value & 0xffff));
3514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3518 + R e a d B l o b S t r i n g %
3522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3524 % ReadBlobString() reads characters from a blob or file until a newline
3525 % character is read or an end-of-file condition is encountered.
3527 % The format of the ReadBlobString method is:
3529 % char *ReadBlobString(Image *image,char *string)
3531 % A description of each parameter follows:
3533 % o image: the image.
3535 % o string: the address of a character buffer.
3538 MagickExport char *ReadBlobString(Image *image,char *string)
3540 register const unsigned char
3552 assert(image != (Image *) NULL);
3553 assert(image->signature == MagickSignature);
3554 for (i=0; i < (MaxTextExtent-1L); i++)
3556 p=ReadBlobStream(image,1,buffer,&count);
3560 return((char *) NULL);
3563 string[i]=(char) (*p);
3564 if ((string[i] == '\r') || (string[i] == '\n'))
3567 if (string[i] == '\r')
3568 (void) ReadBlobStream(image,1,buffer,&count);
3574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3578 + R e f e r e n c e B l o b %
3582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3584 % ReferenceBlob() increments the reference count associated with the pixel
3585 % blob returning a pointer to the blob.
3587 % The format of the ReferenceBlob method is:
3589 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
3591 % A description of each parameter follows:
3593 % o blob_info: the blob_info.
3596 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3598 assert(blob != (BlobInfo *) NULL);
3599 assert(blob->signature == MagickSignature);
3600 if (blob->debug != MagickFalse)
3601 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3602 LockSemaphoreInfo(blob->semaphore);
3603 blob->reference_count++;
3604 UnlockSemaphoreInfo(blob->semaphore);
3609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3619 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
3620 % and returns the resulting offset.
3622 % The format of the SeekBlob method is:
3624 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3627 % A description of each parameter follows:
3629 % o image: the image.
3631 % o offset: Specifies an integer representing the offset in bytes.
3633 % o whence: Specifies an integer representing how the offset is
3634 % treated relative to the beginning of the blob as follows:
3636 % SEEK_SET Set position equal to offset bytes.
3637 % SEEK_CUR Set position to current location plus offset.
3638 % SEEK_END Set position to EOF plus offset.
3641 MagickExport MagickOffsetType SeekBlob(Image *image,
3642 const MagickOffsetType offset,const int whence)
3644 assert(image != (Image *) NULL);
3645 assert(image->signature == MagickSignature);
3646 if (image->debug != MagickFalse)
3647 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3648 assert(image->blob != (BlobInfo *) NULL);
3649 assert(image->blob->type != UndefinedStream);
3650 switch (image->blob->type)
3652 case UndefinedStream:
3654 case StandardStream:
3658 if ((whence == SEEK_SET) && (offset < 0))
3660 if (fseek(image->blob->file_info.file,offset,whence) < 0)
3662 image->blob->offset=TellBlob(image);
3668 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3669 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
3672 image->blob->offset=TellBlob(image);
3688 image->blob->offset=offset;
3693 if ((image->blob->offset+offset) < 0)
3695 image->blob->offset+=offset;
3700 if (((MagickOffsetType) image->blob->length+offset) < 0)
3702 image->blob->offset=image->blob->length+offset;
3706 if (image->blob->offset < (MagickOffsetType)
3707 ((off_t) image->blob->length))
3709 image->blob->eof=MagickFalse;
3712 if (image->blob->mapped != MagickFalse)
3714 if (image->blob->offset < (MagickOffsetType)
3715 ((off_t) image->blob->extent))
3717 image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
3718 image->blob->quantum<<=1;
3719 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3720 image->blob->extent+1,sizeof(*image->blob->data));
3721 (void) SyncBlob(image);
3722 if (image->blob->data == (unsigned char *) NULL)
3724 (void) DetachBlob(image->blob);
3730 return(image->blob->offset);
3734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3738 + S e t B l o b E x e m p t %
3742 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3744 % SetBlobExempt() sets the blob exempt status.
3746 % The format of the SetBlobExempt method is:
3748 % MagickBooleanType SetBlobExempt(const Image *image,
3749 % const MagickBooleanType exempt)
3751 % A description of each parameter follows:
3753 % o image: the image.
3755 % o exempt: Set to true if this blob is exempt from being closed.
3758 MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3760 assert(image != (const Image *) NULL);
3761 assert(image->signature == MagickSignature);
3762 if (image->debug != MagickFalse)
3763 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3764 image->blob->exempt=exempt;
3768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3772 + S e t B l o b E x t e n t %
3776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3778 % SetBlobExtent() ensures enough space is allocated for the blob. If the
3779 % method is successful, subsequent writes to bytes in the specified range are
3780 % guaranteed not to fail.
3782 % The format of the SetBlobExtent method is:
3784 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3786 % A description of each parameter follows:
3788 % o image: the image.
3790 % o extent: the blob maximum extent.
3793 MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
3794 const MagickSizeType extent)
3796 assert(image != (Image *) NULL);
3797 assert(image->signature == MagickSignature);
3798 if (image->debug != MagickFalse)
3799 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3800 assert(image->blob != (BlobInfo *) NULL);
3801 assert(image->blob->type != UndefinedStream);
3802 switch (image->blob->type)
3804 case UndefinedStream:
3806 case StandardStream:
3807 return(MagickFalse);
3816 if (extent != (MagickSizeType) ((off_t) extent))
3817 return(MagickFalse);
3818 offset=SeekBlob(image,0,SEEK_END);
3820 return(MagickFalse);
3821 if ((MagickSizeType) offset >= extent)
3823 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3824 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3825 image->blob->file_info.file);
3826 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3827 if (image->blob->synchronize != MagickFalse)
3832 file=fileno(image->blob->file_info.file);
3833 if ((file == -1) || (offset < 0))
3834 return(MagickFalse);
3835 (void) posix_fallocate(file,offset,extent-offset);
3838 offset=SeekBlob(image,offset,SEEK_SET);
3840 return(MagickFalse);
3845 return(MagickFalse);
3847 return(MagickFalse);
3849 return(MagickFalse);
3852 if (extent != (MagickSizeType) ((size_t) extent))
3853 return(MagickFalse);
3854 if (image->blob->mapped != MagickFalse)
3862 (void) UnmapBlob(image->blob->data,image->blob->length);
3863 RelinquishMagickResource(MapResource,image->blob->length);
3864 if (extent != (MagickSizeType) ((off_t) extent))
3865 return(MagickFalse);
3866 offset=SeekBlob(image,0,SEEK_END);
3868 return(MagickFalse);
3869 if ((MagickSizeType) offset >= extent)
3871 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3872 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3873 image->blob->file_info.file);
3874 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3875 if (image->blob->synchronize != MagickFalse)
3880 file=fileno(image->blob->file_info.file);
3881 if ((file == -1) || (offset < 0))
3882 return(MagickFalse);
3883 (void) posix_fallocate(file,offset,extent-offset);
3886 offset=SeekBlob(image,offset,SEEK_SET);
3888 return(MagickFalse);
3889 (void) AcquireMagickResource(MapResource,extent);
3890 image->blob->data=(unsigned char*) MapBlob(fileno(
3891 image->blob->file_info.file),WriteMode,0,(size_t) extent);
3892 image->blob->extent=(size_t) extent;
3893 image->blob->length=(size_t) extent;
3894 (void) SyncBlob(image);
3897 image->blob->extent=(size_t) extent;
3898 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3899 image->blob->extent+1,sizeof(*image->blob->data));
3900 (void) SyncBlob(image);
3901 if (image->blob->data == (unsigned char *) NULL)
3903 (void) DetachBlob(image->blob);
3904 return(MagickFalse);
3913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3923 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
3924 % attributes if it is an blob.
3926 % The format of the SyncBlob method is:
3928 % int SyncBlob(Image *image)
3930 % A description of each parameter follows:
3932 % o image: the image.
3935 static int SyncBlob(Image *image)
3940 assert(image != (Image *) NULL);
3941 assert(image->signature == MagickSignature);
3942 if (image->debug != MagickFalse)
3943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3944 assert(image->blob != (BlobInfo *) NULL);
3945 assert(image->blob->type != UndefinedStream);
3947 switch (image->blob->type)
3949 case UndefinedStream:
3950 case StandardStream:
3955 status=fflush(image->blob->file_info.file);
3960 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3961 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
3967 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3968 status=BZ2_bzflush(image->blob->file_info.bzfile);
3981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3991 % TellBlob() obtains the current value of the blob or file position.
3993 % The format of the TellBlob method is:
3995 % MagickOffsetType TellBlob(const Image *image)
3997 % A description of each parameter follows:
3999 % o image: the image.
4002 MagickExport MagickOffsetType TellBlob(const Image *image)
4007 assert(image != (Image *) NULL);
4008 assert(image->signature == MagickSignature);
4009 if (image->debug != MagickFalse)
4010 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4011 assert(image->blob != (BlobInfo *) NULL);
4012 assert(image->blob->type != UndefinedStream);
4014 switch (image->blob->type)
4016 case UndefinedStream:
4017 case StandardStream:
4021 offset=ftell(image->blob->file_info.file);
4028 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4029 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
4039 offset=image->blob->offset;
4047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4051 + U n m a p B l o b %
4055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4057 % UnmapBlob() deallocates the binary large object previously allocated with
4058 % the MapBlob method.
4060 % The format of the UnmapBlob method is:
4062 % MagickBooleanType UnmapBlob(void *map,const size_t length)
4064 % A description of each parameter follows:
4066 % o map: the address of the binary large object.
4068 % o length: the length of the binary large object.
4071 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4073 #if defined(MAGICKCORE_HAVE_MMAP)
4077 status=munmap(map,length);
4078 return(status == -1 ? MagickFalse : MagickTrue);
4082 return(MagickFalse);
4087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4091 + W r i t e B l o b %
4095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4097 % WriteBlob() writes data to a blob or image file. It returns the number of
4100 % The format of the WriteBlob method is:
4102 % ssize_t WriteBlob(Image *image,const size_t length,
4103 % const unsigned char *data)
4105 % A description of each parameter follows:
4107 % o image: the image.
4109 % o length: Specifies an integer representing the number of bytes to
4110 % write to the file.
4112 % o data: The address of the data to write to the blob or file.
4115 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4116 const unsigned char *data)
4121 register const unsigned char
4127 assert(image != (Image *) NULL);
4128 assert(image->signature == MagickSignature);
4129 assert(data != (const unsigned char *) NULL);
4130 assert(image->blob != (BlobInfo *) NULL);
4131 assert(image->blob->type != UndefinedStream);
4136 switch (image->blob->type)
4138 case UndefinedStream:
4140 case StandardStream:
4142 count=write(fileno(image->blob->file_info.file),data,length);
4152 count=(ssize_t) fwrite((const char *) data,1,length,
4153 image->blob->file_info.file);
4158 c=putc((int) *p++,image->blob->file_info.file);
4165 c=putc((int) *p++,image->blob->file_info.file);
4177 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4182 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
4183 (unsigned int) length);
4188 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4195 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4208 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4209 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
4216 count=(ssize_t) image->blob->stream(image,data,length);
4221 register unsigned char
4224 if ((image->blob->offset+(MagickOffsetType) length) >=
4225 (MagickOffsetType) image->blob->extent)
4227 if (image->blob->mapped != MagickFalse)
4229 image->blob->extent+=length+image->blob->quantum;
4230 image->blob->quantum<<=1;
4231 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4232 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4233 (void) SyncBlob(image);
4234 if (image->blob->data == (unsigned char *) NULL)
4236 (void) DetachBlob(image->blob);
4240 q=image->blob->data+image->blob->offset;
4241 (void) memcpy(q,p,length);
4242 image->blob->offset+=length;
4243 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4244 image->blob->length=(size_t) image->blob->offset;
4245 count=(ssize_t) length;
4252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4256 + W r i t e B l o b B y t e %
4260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4262 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
4263 % written (either 0 or 1);
4265 % The format of the WriteBlobByte method is:
4267 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
4269 % A description of each parameter follows.
4271 % o image: the image.
4273 % o value: Specifies the value to write.
4276 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4278 assert(image != (Image *) NULL);
4279 assert(image->signature == MagickSignature);
4280 return(WriteBlobStream(image,1,&value));
4284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4288 + W r i t e B l o b F l o a t %
4292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4294 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4295 % specified by the endian member of the image structure.
4297 % The format of the WriteBlobFloat method is:
4299 % ssize_t WriteBlobFloat(Image *image,const float value)
4301 % A description of each parameter follows.
4303 % o image: the image.
4305 % o value: Specifies the value to write.
4308 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4319 quantum.unsigned_value=0U;
4320 quantum.float_value=value;
4321 return(WriteBlobLong(image,quantum.unsigned_value));
4325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4329 + W r i t e B l o b L o n g %
4333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4335 % WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
4336 % specified by the endian member of the image structure.
4338 % The format of the WriteBlobLong method is:
4340 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
4342 % A description of each parameter follows.
4344 % o image: the image.
4346 % o value: Specifies the value to write.
4349 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4354 assert(image != (Image *) NULL);
4355 assert(image->signature == MagickSignature);
4356 if (image->endian == LSBEndian)
4358 buffer[0]=(unsigned char) value;
4359 buffer[1]=(unsigned char) (value >> 8);
4360 buffer[2]=(unsigned char) (value >> 16);
4361 buffer[3]=(unsigned char) (value >> 24);
4362 return(WriteBlobStream(image,4,buffer));
4364 buffer[0]=(unsigned char) (value >> 24);
4365 buffer[1]=(unsigned char) (value >> 16);
4366 buffer[2]=(unsigned char) (value >> 8);
4367 buffer[3]=(unsigned char) value;
4368 return(WriteBlobStream(image,4,buffer));
4372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4376 + W r i t e B l o b S h o r t %
4380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4382 % WriteBlobShort() writes a short value as a 16-bit quantity in the
4383 % byte-order specified by the endian member of the image structure.
4385 % The format of the WriteBlobShort method is:
4387 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
4389 % A description of each parameter follows.
4391 % o image: the image.
4393 % o value: Specifies the value to write.
4396 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4401 assert(image != (Image *) NULL);
4402 assert(image->signature == MagickSignature);
4403 if (image->endian == LSBEndian)
4405 buffer[0]=(unsigned char) value;
4406 buffer[1]=(unsigned char) (value >> 8);
4407 return(WriteBlobStream(image,2,buffer));
4409 buffer[0]=(unsigned char) (value >> 8);
4410 buffer[1]=(unsigned char) value;
4411 return(WriteBlobStream(image,2,buffer));
4415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4419 + W r i t e B l o b L S B L o n g %
4423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4425 % WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
4426 % least-significant byte first order.
4428 % The format of the WriteBlobLSBLong method is:
4430 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4432 % A description of each parameter follows.
4434 % o image: the image.
4436 % o value: Specifies the value to write.
4439 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4444 assert(image != (Image *) NULL);
4445 assert(image->signature == MagickSignature);
4446 buffer[0]=(unsigned char) value;
4447 buffer[1]=(unsigned char) (value >> 8);
4448 buffer[2]=(unsigned char) (value >> 16);
4449 buffer[3]=(unsigned char) (value >> 24);
4450 return(WriteBlobStream(image,4,buffer));
4454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4458 + W r i t e B l o b L S B S h o r t %
4462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4464 % WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
4465 % least-significant byte first order.
4467 % The format of the WriteBlobLSBShort method is:
4469 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4471 % A description of each parameter follows.
4473 % o image: the image.
4475 % o value: Specifies the value to write.
4478 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4483 assert(image != (Image *) NULL);
4484 assert(image->signature == MagickSignature);
4485 buffer[0]=(unsigned char) value;
4486 buffer[1]=(unsigned char) (value >> 8);
4487 return(WriteBlobStream(image,2,buffer));
4491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4495 + W r i t e B l o b M S B L o n g %
4499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4501 % WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
4502 % most-significant byte first order.
4504 % The format of the WriteBlobMSBLong method is:
4506 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4508 % A description of each parameter follows.
4510 % o value: Specifies the value to write.
4512 % o image: the image.
4515 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4520 assert(image != (Image *) NULL);
4521 assert(image->signature == MagickSignature);
4522 buffer[0]=(unsigned char) (value >> 24);
4523 buffer[1]=(unsigned char) (value >> 16);
4524 buffer[2]=(unsigned char) (value >> 8);
4525 buffer[3]=(unsigned char) value;
4526 return(WriteBlobStream(image,4,buffer));
4530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4534 + W r i t e B l o b M S B L o n g L o n g %
4538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4540 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4541 % most-significant byte first order.
4543 % The format of the WriteBlobMSBLongLong method is:
4545 % ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4547 % A description of each parameter follows.
4549 % o value: Specifies the value to write.
4551 % o image: the image.
4554 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4555 const MagickSizeType value)
4560 assert(image != (Image *) NULL);
4561 assert(image->signature == MagickSignature);
4562 buffer[0]=(unsigned char) (value >> 56);
4563 buffer[1]=(unsigned char) (value >> 48);
4564 buffer[2]=(unsigned char) (value >> 40);
4565 buffer[3]=(unsigned char) (value >> 32);
4566 buffer[4]=(unsigned char) (value >> 24);
4567 buffer[5]=(unsigned char) (value >> 16);
4568 buffer[6]=(unsigned char) (value >> 8);
4569 buffer[7]=(unsigned char) value;
4570 return(WriteBlobStream(image,8,buffer));
4574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4578 + W r i t e B l o b M S B S h o r t %
4582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4584 % WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
4585 % most-significant byte first order.
4587 % The format of the WriteBlobMSBShort method is:
4589 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4591 % A description of each parameter follows.
4593 % o value: Specifies the value to write.
4595 % o file: Specifies the file to write the data to.
4598 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4603 assert(image != (Image *) NULL);
4604 assert(image->signature == MagickSignature);
4605 buffer[0]=(unsigned char) (value >> 8);
4606 buffer[1]=(unsigned char) value;
4607 return(WriteBlobStream(image,2,buffer));
4611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4615 + W r i t e B l o b S t r i n g %
4619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4621 % WriteBlobString() write a string to a blob. It returns the number of
4622 % characters written.
4624 % The format of the WriteBlobString method is:
4626 % ssize_t WriteBlobString(Image *image,const char *string)
4628 % A description of each parameter follows.
4630 % o image: the image.
4632 % o string: Specifies the string to write.
4635 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4637 assert(image != (Image *) NULL);
4638 assert(image->signature == MagickSignature);
4639 assert(string != (const char *) NULL);
4640 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));