2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 % BBBB LLLLL OOO BBBB %
13 % MagickCore Binary Large OBjectS Methods %
20 % Copyright 1999-2018 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 % https://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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47 #include "MagickCore/studio.h"
48 #include "MagickCore/blob.h"
49 #include "MagickCore/blob-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image-private.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/locale_.h"
60 #include "MagickCore/log.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/memory-private.h"
64 #include "MagickCore/nt-base-private.h"
65 #include "MagickCore/option.h"
66 #include "MagickCore/policy.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/semaphore.h"
69 #include "MagickCore/string_.h"
70 #include "MagickCore/string-private.h"
71 #include "MagickCore/token.h"
72 #include "MagickCore/utility.h"
73 #include "MagickCore/utility-private.h"
74 #if defined(MAGICKCORE_ZLIB_DELEGATE)
77 #if defined(MAGICKCORE_BZLIB_DELEGATE)
84 #define MagickMaxBlobExtent (8*8192)
85 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
86 # define MAP_ANONYMOUS MAP_ANON
88 #if !defined(MAP_FAILED)
89 #define MAP_FAILED ((void *) -1)
93 #define _O_BINARY O_BINARY
99 typedef union FileInfo
104 #if defined(MAGICKCORE_ZLIB_DELEGATE)
109 #if defined(MAGICKCORE_BZLIB_DELEGATE)
175 struct _CustomStreamInfo
195 Forward declarations.
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205 + A c q u i r e C u s t o m S t r e a m I n f o %
209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211 % AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
213 % The format of the AcquireCustomStreamInfo method is:
215 % CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
217 % A description of each parameter follows:
219 % o exception: return any errors or warnings in this structure.
222 MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
223 ExceptionInfo *magick_unused(exception))
228 magick_unreferenced(exception);
229 custom_stream=(CustomStreamInfo *) AcquireCriticalMemory(
230 sizeof(*custom_stream));
231 (void) memset(custom_stream,0,sizeof(*custom_stream));
232 custom_stream->signature=MagickCoreSignature;
233 return(custom_stream);
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241 + A t t a c h B l o b %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 % AttachBlob() attaches a blob to the BlobInfo structure.
249 % The format of the AttachBlob method is:
251 % void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
253 % A description of each parameter follows:
255 % o blob_info: Specifies a pointer to a BlobInfo structure.
257 % o blob: the address of a character stream in one of the image formats
258 % understood by ImageMagick.
260 % o length: This size_t integer reflects the length in bytes of the blob.
263 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
266 assert(blob_info != (BlobInfo *) NULL);
267 if (blob_info->debug != MagickFalse)
268 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
269 blob_info->length=length;
270 blob_info->extent=length;
271 blob_info->quantum=(size_t) MagickMaxBlobExtent;
273 blob_info->type=BlobStream;
274 blob_info->file_info.file=(FILE *) NULL;
275 blob_info->data=(unsigned char *) blob;
276 blob_info->mapped=MagickFalse;
280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 + A t t a c h C u s t o m S t r e a m %
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290 % AttachCustomStream() attaches a CustomStreamInfo to the BlobInfo structure.
292 % The format of the AttachCustomStream method is:
294 % void AttachCustomStream(BlobInfo *blob_info,
295 % CustomStreamInfo *custom_stream)
297 % A description of each parameter follows:
299 % o blob_info: specifies a pointer to a BlobInfo structure.
301 % o custom_stream: the custom stream info.
304 MagickExport void AttachCustomStream(BlobInfo *blob_info,
305 CustomStreamInfo *custom_stream)
307 assert(blob_info != (BlobInfo *) NULL);
308 assert(custom_stream != (CustomStreamInfo *) NULL);
309 assert(custom_stream->signature == MagickCoreSignature);
310 if (blob_info->debug != MagickFalse)
311 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
312 blob_info->type=CustomStream;
313 blob_info->custom_stream=custom_stream;
317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321 + B l o b T o F i l e %
325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 % BlobToFile() writes a blob to a file. It returns MagickFalse if an error
328 % occurs otherwise MagickTrue.
330 % The format of the BlobToFile method is:
332 % MagickBooleanType BlobToFile(char *filename,const void *blob,
333 % const size_t length,ExceptionInfo *exception)
335 % A description of each parameter follows:
337 % o filename: Write the blob to this file.
339 % o blob: the address of a blob.
341 % o length: This length in bytes of the blob.
343 % o exception: return any errors or warnings in this structure.
346 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
347 const size_t length,ExceptionInfo *exception)
358 assert(filename != (const char *) NULL);
359 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
360 assert(blob != (const void *) NULL);
361 if (*filename == '\0')
362 file=AcquireUniqueFileResource(filename);
364 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
367 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
370 for (i=0; i < length; i+=count)
372 count=write(file,(const char *) blob+i,MagickMin(length-i,SSIZE_MAX));
381 if ((file == -1) || (i < length))
383 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394 % B l o b T o I m a g e %
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % BlobToImage() implements direct to memory image formats. It returns the
403 % The format of the BlobToImage method is:
405 % Image *BlobToImage(const ImageInfo *image_info,const void *blob,
406 % const size_t length,ExceptionInfo *exception)
408 % A description of each parameter follows:
410 % o image_info: the image info.
412 % o blob: the address of a character stream in one of the image formats
413 % understood by ImageMagick.
415 % o length: This size_t integer reflects the length in bytes of the blob.
417 % o exception: return any errors or warnings in this structure.
420 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
421 const size_t length,ExceptionInfo *exception)
436 assert(image_info != (ImageInfo *) NULL);
437 assert(image_info->signature == MagickCoreSignature);
438 if (image_info->debug != MagickFalse)
439 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
440 image_info->filename);
441 assert(exception != (ExceptionInfo *) NULL);
442 if ((blob == (const void *) NULL) || (length == 0))
444 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
445 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
446 return((Image *) NULL);
448 blob_info=CloneImageInfo(image_info);
449 blob_info->blob=(void *) blob;
450 blob_info->length=length;
451 if (*blob_info->magick == '\0')
452 (void) SetImageInfo(blob_info,0,exception);
453 magick_info=GetMagickInfo(blob_info->magick,exception);
454 if (magick_info == (const MagickInfo *) NULL)
456 (void) ThrowMagickException(exception,GetMagickModule(),
457 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
459 blob_info=DestroyImageInfo(blob_info);
460 return((Image *) NULL);
462 if (GetMagickBlobSupport(magick_info) != MagickFalse)
465 filename[MagickPathExtent];
468 Native blob support for this image format.
470 (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
471 (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
472 blob_info->magick,filename);
473 image=ReadImage(blob_info,exception);
474 if (image != (Image *) NULL)
475 (void) DetachBlob(image->blob);
476 blob_info=DestroyImageInfo(blob_info);
480 Write blob to a temporary file on disk.
482 blob_info->blob=(void *) NULL;
484 *blob_info->filename='\0';
485 status=BlobToFile(blob_info->filename,blob,length,exception);
486 if (status == MagickFalse)
488 (void) RelinquishUniqueFileResource(blob_info->filename);
489 blob_info=DestroyImageInfo(blob_info);
490 return((Image *) NULL);
492 clone_info=CloneImageInfo(blob_info);
493 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
494 blob_info->magick,blob_info->filename);
495 image=ReadImage(clone_info,exception);
496 if (image != (Image *) NULL)
502 Restore original filenames and image format.
504 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
506 (void) CopyMagickString(images->filename,image_info->filename,
508 (void) CopyMagickString(images->magick_filename,image_info->filename,
510 (void) CopyMagickString(images->magick,magick_info->name,
512 images=GetNextImageInList(images);
515 clone_info=DestroyImageInfo(clone_info);
516 (void) RelinquishUniqueFileResource(blob_info->filename);
517 blob_info=DestroyImageInfo(blob_info);
522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526 + C l o n e B l o b I n f o %
530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532 % CloneBlobInfo() makes a duplicate of the given blob info structure, or if
533 % blob info is NULL, a new one.
535 % The format of the CloneBlobInfo method is:
537 % BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
539 % A description of each parameter follows:
541 % o blob_info: the blob info.
544 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
549 clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
550 GetBlobInfo(clone_info);
551 if (blob_info == (BlobInfo *) NULL)
553 clone_info->length=blob_info->length;
554 clone_info->extent=blob_info->extent;
555 clone_info->synchronize=blob_info->synchronize;
556 clone_info->quantum=blob_info->quantum;
557 clone_info->mapped=blob_info->mapped;
558 clone_info->eof=blob_info->eof;
559 clone_info->offset=blob_info->offset;
560 clone_info->size=blob_info->size;
561 clone_info->exempt=blob_info->exempt;
562 clone_info->status=blob_info->status;
563 clone_info->temporary=blob_info->temporary;
564 clone_info->type=blob_info->type;
565 clone_info->file_info.file=blob_info->file_info.file;
566 clone_info->properties=blob_info->properties;
567 clone_info->stream=blob_info->stream;
568 clone_info->custom_stream=blob_info->custom_stream;
569 clone_info->data=blob_info->data;
570 clone_info->debug=IsEventLogging();
571 clone_info->reference_count=1;
576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 + C l o s e B l o b %
584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586 % CloseBlob() closes a stream associated with the image.
588 % The format of the CloseBlob method is:
590 % MagickBooleanType CloseBlob(Image *image)
592 % A description of each parameter follows:
594 % o image: the image.
597 MagickExport MagickBooleanType CloseBlob(Image *image)
600 *magick_restrict blob_info;
608 assert(image != (Image *) NULL);
609 assert(image->signature == MagickCoreSignature);
610 if (image->debug != MagickFalse)
611 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
612 blob_info=image->blob;
613 if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
615 status=SyncBlob(image);
616 switch (blob_info->type)
618 case UndefinedStream:
624 if (blob_info->synchronize != MagickFalse)
625 status=fsync(fileno(blob_info->file_info.file));
626 status=ferror(blob_info->file_info.file);
631 #if defined(MAGICKCORE_ZLIB_DELEGATE)
632 (void) gzerror(blob_info->file_info.gzfile,&status);
638 #if defined(MAGICKCORE_BZLIB_DELEGATE)
639 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
647 if (blob_info->file_info.file != (FILE *) NULL)
649 if (blob_info->synchronize != MagickFalse)
650 status=fsync(fileno(blob_info->file_info.file));
651 status=ferror(blob_info->file_info.file);
658 blob_info->status=status < 0 ? MagickTrue : MagickFalse;
659 blob_info->size=GetBlobSize(image);
660 image->extent=blob_info->size;
661 blob_info->eof=MagickFalse;
663 blob_info->mode=UndefinedBlobMode;
664 if (blob_info->exempt != MagickFalse)
666 blob_info->type=UndefinedStream;
667 return(blob_info->status);
669 switch (blob_info->type)
671 case UndefinedStream:
676 status=fclose(blob_info->file_info.file);
681 #if defined(MAGICKCORE_HAVE_PCLOSE)
682 status=pclose(blob_info->file_info.file);
688 #if defined(MAGICKCORE_ZLIB_DELEGATE)
689 status=gzclose(blob_info->file_info.gzfile);
695 #if defined(MAGICKCORE_BZLIB_DELEGATE)
696 BZ2_bzclose(blob_info->file_info.bzfile);
704 if (blob_info->file_info.file != (FILE *) NULL)
705 status=fclose(blob_info->file_info.file);
711 (void) DetachBlob(blob_info);
712 blob_info->status=status < 0 ? MagickTrue : MagickFalse;
713 return(blob_info->status);
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 % C u s t o m S t r e a m T o I m a g e %
725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727 % CustomStreamToImage() is the equivalent of ReadImage(), but reads the
728 % formatted "file" from the suplied method rather than to an actual file.
730 % The format of the CustomStreamToImage method is:
732 % Image *CustomStreamToImage(const ImageInfo *image_info,
733 % ExceptionInfo *exception)
735 % A description of each parameter follows:
737 % o image_info: the image info.
739 % o exception: return any errors or warnings in this structure.
742 MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
743 ExceptionInfo *exception)
754 assert(image_info != (ImageInfo *) NULL);
755 assert(image_info->signature == MagickCoreSignature);
756 if (image_info->debug != MagickFalse)
757 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
758 image_info->filename);
759 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
760 assert(image_info->custom_stream->signature == MagickCoreSignature);
761 assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
762 assert(exception != (ExceptionInfo *) NULL);
763 blob_info=CloneImageInfo(image_info);
764 if (*blob_info->magick == '\0')
765 (void) SetImageInfo(blob_info,0,exception);
766 magick_info=GetMagickInfo(blob_info->magick,exception);
767 if (magick_info == (const MagickInfo *) NULL)
769 (void) ThrowMagickException(exception,GetMagickModule(),
770 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
772 blob_info=DestroyImageInfo(blob_info);
773 return((Image *) NULL);
775 image=(Image *) NULL;
776 if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
777 (*blob_info->filename != '\0'))
780 filename[MagickPathExtent];
783 Native blob support for this image format or SetImageInfo changed the
786 (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
787 (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
788 blob_info->magick,filename);
789 image=ReadImage(blob_info,exception);
790 if (image != (Image *) NULL)
791 (void) CloseBlob(image);
796 unique[MagickPathExtent];
808 Write data to file on disk.
810 blob_info->custom_stream=(CustomStreamInfo *) NULL;
811 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
813 if (blob == (unsigned char *) NULL)
815 ThrowFileException(exception,BlobError,"UnableToReadBlob",
816 image_info->filename);
817 blob_info=DestroyImageInfo(blob_info);
818 return((Image *) NULL);
820 file=AcquireUniqueFileResource(unique);
823 ThrowFileException(exception,BlobError,"UnableToReadBlob",
824 image_info->filename);
825 blob=(unsigned char *) RelinquishMagickMemory(blob);
826 blob_info=DestroyImageInfo(blob_info);
827 return((Image *) NULL);
829 clone_info=CloneImageInfo(blob_info);
830 blob_info->file=fdopen(file,"wb+");
831 if (blob_info->file != (FILE *) NULL)
836 count=(ssize_t) MagickMaxBufferExtent;
837 while (count == (ssize_t) MagickMaxBufferExtent)
839 count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
840 image_info->custom_stream->data);
841 count=(ssize_t) write(file,(const char *) blob,(size_t) count);
843 (void) fclose(blob_info->file);
844 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
845 "%s:%s",blob_info->magick,unique);
846 image=ReadImage(clone_info,exception);
847 if (image != (Image *) NULL)
853 Restore original filenames and image format.
855 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
857 (void) CopyMagickString(images->filename,image_info->filename,
859 (void) CopyMagickString(images->magick_filename,
860 image_info->filename,MagickPathExtent);
861 (void) CopyMagickString(images->magick,magick_info->name,
863 (void) CloseBlob(images);
864 images=GetNextImageInList(images);
868 clone_info=DestroyImageInfo(clone_info);
869 blob=(unsigned char *) RelinquishMagickMemory(blob);
870 (void) RelinquishUniqueFileResource(unique);
872 blob_info=DestroyImageInfo(blob_info);
877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 + D e s t r o y B l o b %
885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887 % DestroyBlob() deallocates memory associated with a blob.
889 % The format of the DestroyBlob method is:
891 % void DestroyBlob(Image *image)
893 % A description of each parameter follows:
895 % o image: the image.
898 MagickExport void DestroyBlob(Image *image)
901 *magick_restrict blob_info;
906 assert(image != (Image *) NULL);
907 assert(image->signature == MagickCoreSignature);
908 if (image->debug != MagickFalse)
909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
910 assert(image->blob != (BlobInfo *) NULL);
911 assert(image->blob->signature == MagickCoreSignature);
912 blob_info=image->blob;
914 LockSemaphoreInfo(blob_info->semaphore);
915 blob_info->reference_count--;
916 assert(blob_info->reference_count >= 0);
917 if (blob_info->reference_count == 0)
919 UnlockSemaphoreInfo(blob_info->semaphore);
920 if (destroy == MagickFalse)
922 (void) CloseBlob(image);
923 if (blob_info->mapped != MagickFalse)
925 (void) UnmapBlob(blob_info->data,blob_info->length);
926 RelinquishMagickResource(MapResource,blob_info->length);
928 if (blob_info->semaphore != (SemaphoreInfo *) NULL)
929 RelinquishSemaphoreInfo(&blob_info->semaphore);
930 blob_info->signature=(~MagickCoreSignature);
931 image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939 + D e s t r o y C u s t o m S t r e a m I n f o %
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 % DestroyCustomStreamInfo() destroys memory associated with the
946 % CustomStreamInfo structure.
948 % The format of the DestroyCustomStreamInfo method is:
950 % CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
952 % A description of each parameter follows:
954 % o custom_stream: the custom stream info.
957 MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
958 CustomStreamInfo *custom_stream)
960 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
961 assert(custom_stream != (CustomStreamInfo *) NULL);
962 assert(custom_stream->signature == MagickCoreSignature);
963 custom_stream->signature=(~MagickCoreSignature);
964 custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
965 return(custom_stream);
969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973 + D e t a c h B l o b %
977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979 % DetachBlob() detaches a blob from the BlobInfo structure.
981 % The format of the DetachBlob method is:
983 % void *DetachBlob(BlobInfo *blob_info)
985 % A description of each parameter follows:
987 % o blob_info: Specifies a pointer to a BlobInfo structure.
990 MagickExport void *DetachBlob(BlobInfo *blob_info)
995 assert(blob_info != (BlobInfo *) NULL);
996 if (blob_info->debug != MagickFalse)
997 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
998 if (blob_info->mapped != MagickFalse)
1000 (void) UnmapBlob(blob_info->data,blob_info->length);
1001 blob_info->data=(unsigned char *) NULL;
1002 RelinquishMagickResource(MapResource,blob_info->length);
1004 blob_info->mapped=MagickFalse;
1005 blob_info->length=0;
1006 blob_info->offset=0;
1007 blob_info->eof=MagickFalse;
1009 blob_info->exempt=MagickFalse;
1010 blob_info->type=UndefinedStream;
1011 blob_info->file_info.file=(FILE *) NULL;
1012 data=blob_info->data;
1013 blob_info->data=(unsigned char *) NULL;
1014 blob_info->stream=(StreamHandler) NULL;
1015 blob_info->custom_stream=(CustomStreamInfo *) NULL;
1020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024 + D i s a s s o c i a t e B l o b %
1028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 % DisassociateBlob() disassociates the image stream. It checks if the
1031 % blob of the specified image is referenced by other images. If the reference
1032 % count is higher then 1 a new blob is assigned to the specified image.
1034 % The format of the DisassociateBlob method is:
1036 % void DisassociateBlob(const Image *image)
1038 % A description of each parameter follows:
1040 % o image: the image.
1043 MagickExport void DisassociateBlob(Image *image)
1046 *magick_restrict blob_info,
1052 assert(image != (Image *) NULL);
1053 assert(image->signature == MagickCoreSignature);
1054 if (image->debug != MagickFalse)
1055 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1056 assert(image->blob != (BlobInfo *) NULL);
1057 assert(image->blob->signature == MagickCoreSignature);
1058 blob_info=image->blob;
1060 LockSemaphoreInfo(blob_info->semaphore);
1061 assert(blob_info->reference_count >= 0);
1062 if (blob_info->reference_count > 1)
1064 UnlockSemaphoreInfo(blob_info->semaphore);
1065 if (clone == MagickFalse)
1067 clone_info=CloneBlobInfo(blob_info);
1069 image->blob=clone_info;
1073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1077 + D i s c a r d B l o b B y t e s %
1081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083 % DiscardBlobBytes() discards bytes in a blob.
1085 % The format of the DiscardBlobBytes method is:
1087 % MagickBooleanType DiscardBlobBytes(Image *image,
1088 % const MagickSizeType length)
1090 % A description of each parameter follows.
1092 % o image: the image.
1094 % o length: the number of bytes to skip.
1097 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
1098 const MagickSizeType length)
1100 register MagickOffsetType
1112 assert(image != (Image *) NULL);
1113 assert(image->signature == MagickCoreSignature);
1114 if (length != (MagickSizeType) ((MagickOffsetType) length))
1115 return(MagickFalse);
1117 for (i=0; i < (MagickOffsetType) length; i+=count)
1119 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
1120 (void) ReadBlobStream(image,quantum,buffer,&count);
1128 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
1132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1136 + D u p l i c a t e s B l o b %
1140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1142 % DuplicateBlob() duplicates a blob descriptor.
1144 % The format of the DuplicateBlob method is:
1146 % void DuplicateBlob(Image *image,const Image *duplicate)
1148 % A description of each parameter follows:
1150 % o image: the image.
1152 % o duplicate: the duplicate image.
1155 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
1157 assert(image != (Image *) NULL);
1158 assert(image->signature == MagickCoreSignature);
1159 if (image->debug != MagickFalse)
1160 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1161 assert(duplicate != (Image *) NULL);
1162 assert(duplicate->signature == MagickCoreSignature);
1164 image->blob=ReferenceBlob(duplicate->blob);
1168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1178 % EOFBlob() returns a non-zero value when EOF has been detected reading from
1181 % The format of the EOFBlob method is:
1183 % int EOFBlob(const Image *image)
1185 % A description of each parameter follows:
1187 % o image: the image.
1190 MagickExport int EOFBlob(const Image *image)
1193 *magick_restrict blob_info;
1195 assert(image != (Image *) NULL);
1196 assert(image->signature == MagickCoreSignature);
1197 if (image->debug != MagickFalse)
1198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1199 assert(image->blob != (BlobInfo *) NULL);
1200 assert(image->blob->type != UndefinedStream);
1201 blob_info=image->blob;
1202 switch (blob_info->type)
1204 case UndefinedStream:
1205 case StandardStream:
1210 blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
1216 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1217 blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
1224 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1229 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
1230 blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
1236 blob_info->eof=MagickFalse;
1244 return((int) blob_info->eof);
1248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252 + E r r o r B l o b %
1256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258 % ErrorBlob() returns a non-zero value when an error has been detected reading
1259 % from a blob or file.
1261 % The format of the ErrorBlob method is:
1263 % int ErrorBlob(const Image *image)
1265 % A description of each parameter follows:
1267 % o image: the image.
1270 MagickExport int ErrorBlob(const Image *image)
1273 *magick_restrict blob_info;
1275 assert(image != (Image *) NULL);
1276 assert(image->signature == MagickCoreSignature);
1277 if (image->debug != MagickFalse)
1278 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1279 assert(image->blob != (BlobInfo *) NULL);
1280 assert(image->blob->type != UndefinedStream);
1281 blob_info=image->blob;
1282 switch (blob_info->type)
1284 case UndefinedStream:
1285 case StandardStream:
1290 blob_info->error=ferror(blob_info->file_info.file);
1295 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1296 (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1302 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1303 (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1317 return(blob_info->error);
1321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1325 % F i l e T o B l o b %
1329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331 % FileToBlob() returns the contents of a file as a buffer terminated with
1332 % the '\0' character. The length of the buffer (not including the extra
1333 % terminating '\0' character) is returned via the 'length' parameter. Free
1334 % the buffer with RelinquishMagickMemory().
1336 % The format of the FileToBlob method is:
1338 % void *FileToBlob(const char *filename,const size_t extent,
1339 % size_t *length,ExceptionInfo *exception)
1341 % A description of each parameter follows:
1343 % o blob: FileToBlob() returns the contents of a file as a blob. If
1344 % an error occurs NULL is returned.
1346 % o filename: the filename.
1348 % o extent: The maximum length of the blob.
1350 % o length: On return, this reflects the actual length of the blob.
1352 % o exception: return any errors or warnings in this structure.
1355 MagickExport void *FileToBlob(const char *filename,const size_t extent,
1356 size_t *length,ExceptionInfo *exception)
1382 assert(filename != (const char *) NULL);
1383 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1384 assert(exception != (ExceptionInfo *) NULL);
1386 status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1387 if (status == MagickFalse)
1390 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1391 "NotAuthorized","`%s'",filename);
1395 if (LocaleCompare(filename,"-") != 0)
1397 status=GetPathAttributes(filename,&attributes);
1398 if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1400 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1403 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1407 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1410 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1412 if ((file == fileno(stdin)) || (offset < 0) ||
1413 (offset != (MagickOffsetType) ((ssize_t) offset)))
1422 Stream is not seekable.
1424 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1425 quantum=(size_t) MagickMaxBufferExtent;
1426 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1427 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1428 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1429 for (i=0; blob != (unsigned char *) NULL; i+=count)
1431 count=read(file,blob+i,quantum);
1438 if (~((size_t) i) < (quantum+1))
1440 blob=(unsigned char *) RelinquishMagickMemory(blob);
1443 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1445 if ((size_t) (i+count) >= extent)
1448 if (LocaleCompare(filename,"-") != 0)
1450 if (blob == (unsigned char *) NULL)
1452 (void) ThrowMagickException(exception,GetMagickModule(),
1453 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1458 blob=(unsigned char *) RelinquishMagickMemory(blob);
1459 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1462 *length=(size_t) MagickMin(i+count,extent);
1466 *length=(size_t) MagickMin(offset,(MagickOffsetType)
1467 MagickMin(extent,SSIZE_MAX));
1468 blob=(unsigned char *) NULL;
1469 if (~(*length) >= (MagickPathExtent-1))
1470 blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1472 if (blob == (unsigned char *) NULL)
1475 (void) ThrowMagickException(exception,GetMagickModule(),
1476 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1479 map=MapBlob(file,ReadMode,0,*length);
1480 if (map != (unsigned char *) NULL)
1482 (void) memcpy(blob,map,*length);
1483 (void) UnmapBlob(map,*length);
1487 (void) lseek(file,0,SEEK_SET);
1488 for (i=0; i < *length; i+=count)
1490 count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
1501 blob=(unsigned char *) RelinquishMagickMemory(blob);
1502 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1507 if (LocaleCompare(filename,"-") != 0)
1511 blob=(unsigned char *) RelinquishMagickMemory(blob);
1512 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1522 % F i l e T o I m a g e %
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528 % FileToImage() write the contents of a file to an image.
1530 % The format of the FileToImage method is:
1532 % MagickBooleanType FileToImage(Image *,const char *filename)
1534 % A description of each parameter follows:
1536 % o image: the image.
1538 % o filename: the filename.
1542 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1546 *magick_restrict blob_info;
1551 register unsigned char
1554 assert(image->blob != (BlobInfo *) NULL);
1555 assert(image->blob->type != UndefinedStream);
1556 assert(data != NULL);
1557 blob_info=image->blob;
1558 if (blob_info->type != BlobStream)
1559 return(WriteBlob(image,length,(const unsigned char *) data));
1560 extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1561 if (extent >= blob_info->extent)
1563 extent=blob_info->extent+blob_info->quantum+length;
1564 blob_info->quantum<<=1;
1565 if (SetBlobExtent(image,extent) == MagickFalse)
1568 q=blob_info->data+blob_info->offset;
1569 (void) memcpy(q,data,length);
1570 blob_info->offset+=length;
1571 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1572 blob_info->length=(size_t) blob_info->offset;
1573 return((ssize_t) length);
1576 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1577 ExceptionInfo *exception)
1598 assert(image != (const Image *) NULL);
1599 assert(image->signature == MagickCoreSignature);
1600 assert(filename != (const char *) NULL);
1601 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1602 status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename);
1603 if (status == MagickFalse)
1606 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1607 "NotAuthorized","`%s'",filename);
1608 return(MagickFalse);
1611 if (LocaleCompare(filename,"-") != 0)
1612 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1615 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1616 return(MagickFalse);
1618 quantum=(size_t) MagickMaxBufferExtent;
1619 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1620 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1621 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1622 if (blob == (unsigned char *) NULL)
1625 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1627 return(MagickFalse);
1631 count=read(file,blob,quantum);
1638 length=(size_t) count;
1639 count=WriteBlobStream(image,length,blob);
1640 if (count != (ssize_t) length)
1642 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1648 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1649 blob=(unsigned char *) RelinquishMagickMemory(blob);
1654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658 + G e t B l o b E r r o r %
1662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1664 % GetBlobError() returns MagickTrue if the blob associated with the specified
1665 % image encountered an error.
1667 % The format of the GetBlobError method is:
1669 % MagickBooleanType GetBlobError(const Image *image)
1671 % A description of each parameter follows:
1673 % o image: the image.
1676 MagickExport MagickBooleanType GetBlobError(const Image *image)
1678 assert(image != (const Image *) NULL);
1679 assert(image->signature == MagickCoreSignature);
1680 if (image->debug != MagickFalse)
1681 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1682 return(image->blob->status);
1686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1690 + G e t B l o b F i l e H a n d l e %
1694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1696 % GetBlobFileHandle() returns the file handle associated with the image blob.
1698 % The format of the GetBlobFile method is:
1700 % FILE *GetBlobFileHandle(const Image *image)
1702 % A description of each parameter follows:
1704 % o image: the image.
1707 MagickExport FILE *GetBlobFileHandle(const Image *image)
1709 assert(image != (const Image *) NULL);
1710 assert(image->signature == MagickCoreSignature);
1711 return(image->blob->file_info.file);
1715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1719 + G e t B l o b I n f o %
1723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 % GetBlobInfo() initializes the BlobInfo structure.
1727 % The format of the GetBlobInfo method is:
1729 % void GetBlobInfo(BlobInfo *blob_info)
1731 % A description of each parameter follows:
1733 % o blob_info: Specifies a pointer to a BlobInfo structure.
1736 MagickExport void GetBlobInfo(BlobInfo *blob_info)
1738 assert(blob_info != (BlobInfo *) NULL);
1739 (void) memset(blob_info,0,sizeof(*blob_info));
1740 blob_info->type=UndefinedStream;
1741 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1742 blob_info->properties.st_mtime=time((time_t *) NULL);
1743 blob_info->properties.st_ctime=time((time_t *) NULL);
1744 blob_info->debug=IsEventLogging();
1745 blob_info->reference_count=1;
1746 blob_info->semaphore=AcquireSemaphoreInfo();
1747 blob_info->signature=MagickCoreSignature;
1751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1755 % G e t B l o b P r o p e r t i e s %
1759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1761 % GetBlobProperties() returns information about an image blob.
1763 % The format of the GetBlobProperties method is:
1765 % const struct stat *GetBlobProperties(const Image *image)
1767 % A description of each parameter follows:
1769 % o image: the image.
1772 MagickExport const struct stat *GetBlobProperties(const Image *image)
1774 assert(image != (Image *) NULL);
1775 assert(image->signature == MagickCoreSignature);
1776 if (image->debug != MagickFalse)
1777 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1778 return(&image->blob->properties);
1782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1786 + G e t B l o b S i z e %
1790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1792 % GetBlobSize() returns the current length of the image file or blob; zero is
1793 % returned if the size cannot be determined.
1795 % The format of the GetBlobSize method is:
1797 % MagickSizeType GetBlobSize(const Image *image)
1799 % A description of each parameter follows:
1801 % o image: the image.
1804 MagickExport MagickSizeType GetBlobSize(const Image *image)
1807 *magick_restrict blob_info;
1812 assert(image != (Image *) NULL);
1813 assert(image->signature == MagickCoreSignature);
1814 if (image->debug != MagickFalse)
1815 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1816 assert(image->blob != (BlobInfo *) NULL);
1817 blob_info=image->blob;
1819 switch (blob_info->type)
1821 case UndefinedStream:
1822 case StandardStream:
1824 extent=blob_info->size;
1829 if (fstat(fileno(blob_info->file_info.file),&blob_info->properties) == 0)
1830 extent=(MagickSizeType) blob_info->properties.st_size;
1835 extent=blob_info->size;
1844 status=GetPathAttributes(image->filename,&blob_info->properties);
1845 if (status != MagickFalse)
1846 extent=(MagickSizeType) blob_info->properties.st_size;
1853 extent=(MagickSizeType) blob_info->length;
1858 if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
1859 (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
1864 offset=blob_info->custom_stream->teller(
1865 blob_info->custom_stream->data);
1866 extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
1867 blob_info->custom_stream->data);
1868 (void) blob_info->custom_stream->seeker(offset,SEEK_SET,
1869 blob_info->custom_stream->data);
1878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1882 + G e t B l o b S t r e a m D a t a %
1886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1888 % GetBlobStreamData() returns the stream data for the image.
1890 % The format of the GetBlobStreamData method is:
1892 % void *GetBlobStreamData(const Image *image)
1894 % A description of each parameter follows:
1896 % o image: the image.
1899 MagickExport void *GetBlobStreamData(const Image *image)
1901 assert(image != (const Image *) NULL);
1902 assert(image->signature == MagickCoreSignature);
1903 return(image->blob->data);
1907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1911 + G e t B l o b S t r e a m H a n d l e r %
1915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1917 % GetBlobStreamHandler() returns the stream handler for the image.
1919 % The format of the GetBlobStreamHandler method is:
1921 % StreamHandler GetBlobStreamHandler(const Image *image)
1923 % A description of each parameter follows:
1925 % o image: the image.
1928 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1930 assert(image != (const Image *) NULL);
1931 assert(image->signature == MagickCoreSignature);
1932 if (image->debug != MagickFalse)
1933 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1934 return(image->blob->stream);
1938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1942 % I m a g e T o B l o b %
1946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1948 % ImageToBlob() implements direct to memory image formats. It returns the
1949 % image as a formatted blob and its length. The magick member of the Image
1950 % structure determines the format of the returned blob (GIF, JPEG, PNG,
1951 % etc.). This method is the equivalent of WriteImage(), but writes the
1952 % formatted "file" to a memory buffer rather than to an actual file.
1954 % The format of the ImageToBlob method is:
1956 % void *ImageToBlob(const ImageInfo *image_info,Image *image,
1957 % size_t *length,ExceptionInfo *exception)
1959 % A description of each parameter follows:
1961 % o image_info: the image info.
1963 % o image: the image.
1965 % o length: return the actual length of the blob.
1967 % o exception: return any errors or warnings in this structure.
1970 MagickExport void *ImageToBlob(const ImageInfo *image_info,
1971 Image *image,size_t *length,ExceptionInfo *exception)
1985 assert(image_info != (const ImageInfo *) NULL);
1986 assert(image_info->signature == MagickCoreSignature);
1987 if (image_info->debug != MagickFalse)
1988 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1989 image_info->filename);
1990 assert(image != (Image *) NULL);
1991 assert(image->signature == MagickCoreSignature);
1992 assert(exception != (ExceptionInfo *) NULL);
1994 blob=(unsigned char *) NULL;
1995 blob_info=CloneImageInfo(image_info);
1996 blob_info->adjoin=MagickFalse;
1997 (void) SetImageInfo(blob_info,1,exception);
1998 if (*blob_info->magick != '\0')
1999 (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
2000 magick_info=GetMagickInfo(image->magick,exception);
2001 if (magick_info == (const MagickInfo *) NULL)
2003 (void) ThrowMagickException(exception,GetMagickModule(),
2004 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2006 blob_info=DestroyImageInfo(blob_info);
2009 (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
2010 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2013 Native blob support for this image format.
2015 blob_info->length=0;
2016 blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2017 sizeof(unsigned char));
2018 if (blob_info->blob == NULL)
2019 (void) ThrowMagickException(exception,GetMagickModule(),
2020 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2023 (void) CloseBlob(image);
2024 image->blob->exempt=MagickTrue;
2025 *image->filename='\0';
2026 status=WriteImage(blob_info,image,exception);
2027 *length=image->blob->length;
2028 blob=DetachBlob(image->blob);
2029 if (blob == (void *) NULL)
2030 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2031 else if (status == MagickFalse)
2032 blob=RelinquishMagickMemory(blob);
2034 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2040 unique[MagickPathExtent];
2046 Write file to disk in blob image format.
2048 file=AcquireUniqueFileResource(unique);
2051 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2052 image_info->filename);
2056 blob_info->file=fdopen(file,"wb");
2057 if (blob_info->file != (FILE *) NULL)
2059 (void) FormatLocaleString(image->filename,MagickPathExtent,
2060 "%s:%s",image->magick,unique);
2061 status=WriteImage(blob_info,image,exception);
2062 (void) CloseBlob(image);
2063 (void) fclose(blob_info->file);
2064 if (status != MagickFalse)
2065 blob=FileToBlob(unique,~0UL,length,exception);
2067 (void) RelinquishUniqueFileResource(unique);
2070 blob_info=DestroyImageInfo(blob_info);
2075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2079 + I m a g e T o C u s t o m S t r e a m %
2083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2085 % ImageToCustomStream() is the equivalent of WriteImage(), but writes the
2086 % formatted "file" to the custom stream rather than to an actual file.
2088 % The format of the ImageToCustomStream method is:
2090 % void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2091 % ExceptionInfo *exception)
2093 % A description of each parameter follows:
2095 % o image_info: the image info.
2097 % o image: the image.
2099 % o exception: return any errors or warnings in this structure.
2102 MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2103 ExceptionInfo *exception)
2115 assert(image_info != (const ImageInfo *) NULL);
2116 assert(image_info->signature == MagickCoreSignature);
2117 if (image_info->debug != MagickFalse)
2118 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2119 image_info->filename);
2120 assert(image != (Image *) NULL);
2121 assert(image->signature == MagickCoreSignature);
2122 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2123 assert(image_info->custom_stream->signature == MagickCoreSignature);
2124 assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2125 assert(exception != (ExceptionInfo *) NULL);
2126 clone_info=CloneImageInfo(image_info);
2127 clone_info->adjoin=MagickFalse;
2128 (void) SetImageInfo(clone_info,1,exception);
2129 if (*clone_info->magick != '\0')
2130 (void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
2131 magick_info=GetMagickInfo(image->magick,exception);
2132 if (magick_info == (const MagickInfo *) NULL)
2134 (void) ThrowMagickException(exception,GetMagickModule(),
2135 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2137 clone_info=DestroyImageInfo(clone_info);
2140 (void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
2141 blob_support=GetMagickBlobSupport(magick_info);
2142 if ((blob_support != MagickFalse) &&
2143 (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2145 if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2146 (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2147 blob_support=MagickFalse;
2149 if (blob_support != MagickFalse)
2152 Native blob support for this image format.
2154 (void) CloseBlob(image);
2155 *image->filename='\0';
2156 (void) WriteImage(clone_info,image,exception);
2157 (void) CloseBlob(image);
2162 unique[MagickPathExtent];
2171 Write file to disk in blob image format.
2173 clone_info->custom_stream=(CustomStreamInfo *) NULL;
2174 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2176 if (blob == (unsigned char *) NULL)
2178 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2179 image_info->filename);
2180 clone_info=DestroyImageInfo(clone_info);
2183 file=AcquireUniqueFileResource(unique);
2186 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2187 image_info->filename);
2188 blob=(unsigned char *) RelinquishMagickMemory(blob);
2189 clone_info=DestroyImageInfo(clone_info);
2192 clone_info->file=fdopen(file,"wb+");
2193 if (clone_info->file != (FILE *) NULL)
2198 (void) FormatLocaleString(image->filename,MagickPathExtent,
2199 "%s:%s",image->magick,unique);
2200 status=WriteImage(clone_info,image,exception);
2201 (void) CloseBlob(image);
2202 if (status != MagickFalse)
2204 (void) fseek(clone_info->file,0,SEEK_SET);
2205 count=(ssize_t) MagickMaxBufferExtent;
2206 while (count == (ssize_t) MagickMaxBufferExtent)
2208 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2210 (void) image_info->custom_stream->writer(blob,(size_t) count,
2211 image_info->custom_stream->data);
2214 (void) fclose(clone_info->file);
2216 blob=(unsigned char *) RelinquishMagickMemory(blob);
2217 (void) RelinquishUniqueFileResource(unique);
2219 clone_info=DestroyImageInfo(clone_info);
2223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2227 % I m a g e T o F i l e %
2231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2233 % ImageToFile() writes an image to a file. It returns MagickFalse if an error
2234 % occurs otherwise MagickTrue.
2236 % The format of the ImageToFile method is:
2238 % MagickBooleanType ImageToFile(Image *image,char *filename,
2239 % ExceptionInfo *exception)
2241 % A description of each parameter follows:
2243 % o image: the image.
2245 % o filename: Write the image to this file.
2247 % o exception: return any errors or warnings in this structure.
2250 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
2251 ExceptionInfo *exception)
2256 register const unsigned char
2275 assert(image != (Image *) NULL);
2276 assert(image->signature == MagickCoreSignature);
2277 assert(image->blob != (BlobInfo *) NULL);
2278 assert(image->blob->type != UndefinedStream);
2279 if (image->debug != MagickFalse)
2280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
2281 assert(filename != (const char *) NULL);
2282 if (*filename == '\0')
2283 file=AcquireUniqueFileResource(filename);
2285 if (LocaleCompare(filename,"-") == 0)
2286 file=fileno(stdout);
2288 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
2291 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2292 return(MagickFalse);
2294 quantum=(size_t) MagickMaxBufferExtent;
2295 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2296 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2297 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2298 if (buffer == (unsigned char *) NULL)
2301 (void) ThrowMagickException(exception,GetMagickModule(),
2302 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
2303 return(MagickFalse);
2306 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2307 for (i=0; count > 0; )
2309 length=(size_t) count;
2310 for (i=0; i < length; i+=count)
2312 count=write(file,p+i,(size_t) (length-i));
2322 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2324 if (LocaleCompare(filename,"-") != 0)
2326 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2327 if ((file == -1) || (i < length))
2331 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2332 return(MagickFalse);
2338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2342 % I m a g e s T o B l o b %
2346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2348 % ImagesToBlob() implements direct to memory image formats. It returns the
2349 % image sequence as a blob and its length. The magick member of the ImageInfo
2350 % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
2352 % Note, some image formats do not permit multiple images to the same image
2353 % stream (e.g. JPEG). in this instance, just the first image of the
2354 % sequence is returned as a blob.
2356 % The format of the ImagesToBlob method is:
2358 % void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2359 % size_t *length,ExceptionInfo *exception)
2361 % A description of each parameter follows:
2363 % o image_info: the image info.
2365 % o images: the image list.
2367 % o length: return the actual length of the blob.
2369 % o exception: return any errors or warnings in this structure.
2372 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2373 size_t *length,ExceptionInfo *exception)
2387 assert(image_info != (const ImageInfo *) NULL);
2388 assert(image_info->signature == MagickCoreSignature);
2389 if (image_info->debug != MagickFalse)
2390 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2391 image_info->filename);
2392 assert(images != (Image *) NULL);
2393 assert(images->signature == MagickCoreSignature);
2394 assert(exception != (ExceptionInfo *) NULL);
2396 blob=(unsigned char *) NULL;
2397 clone_info=CloneImageInfo(image_info);
2398 (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2400 if (*clone_info->magick != '\0')
2401 (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2402 magick_info=GetMagickInfo(images->magick,exception);
2403 if (magick_info == (const MagickInfo *) NULL)
2405 (void) ThrowMagickException(exception,GetMagickModule(),
2406 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2408 clone_info=DestroyImageInfo(clone_info);
2411 if (GetMagickAdjoin(magick_info) == MagickFalse)
2413 clone_info=DestroyImageInfo(clone_info);
2414 return(ImageToBlob(image_info,images,length,exception));
2416 (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2417 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2420 Native blob support for this images format.
2422 clone_info->length=0;
2423 clone_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2424 sizeof(unsigned char));
2425 if (clone_info->blob == (void *) NULL)
2426 (void) ThrowMagickException(exception,GetMagickModule(),
2427 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2430 (void) CloseBlob(images);
2431 images->blob->exempt=MagickTrue;
2432 *images->filename='\0';
2433 status=WriteImages(clone_info,images,images->filename,exception);
2434 *length=images->blob->length;
2435 blob=DetachBlob(images->blob);
2436 if (blob == (void *) NULL)
2437 clone_info->blob=RelinquishMagickMemory(clone_info->blob);
2438 else if (status == MagickFalse)
2439 blob=RelinquishMagickMemory(blob);
2441 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2447 filename[MagickPathExtent],
2448 unique[MagickPathExtent];
2454 Write file to disk in blob images format.
2456 file=AcquireUniqueFileResource(unique);
2459 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2460 image_info->filename);
2464 clone_info->file=fdopen(file,"wb");
2465 if (clone_info->file != (FILE *) NULL)
2467 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2468 images->magick,unique);
2469 status=WriteImages(clone_info,images,filename,exception);
2470 (void) CloseBlob(images);
2471 (void) fclose(clone_info->file);
2472 if (status != MagickFalse)
2473 blob=FileToBlob(unique,~0UL,length,exception);
2475 (void) RelinquishUniqueFileResource(unique);
2478 clone_info=DestroyImageInfo(clone_info);
2483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2487 + I m a g e s T o C u s t o m B l o b %
2491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2493 % ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2494 % formatted "file" to the custom stream rather than to an actual file.
2496 % The format of the ImageToCustomStream method is:
2498 % void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2499 % ExceptionInfo *exception)
2501 % A description of each parameter follows:
2503 % o image_info: the image info.
2505 % o images: the image list.
2507 % o exception: return any errors or warnings in this structure.
2510 MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2511 Image *images,ExceptionInfo *exception)
2523 assert(image_info != (const ImageInfo *) NULL);
2524 assert(image_info->signature == MagickCoreSignature);
2525 if (image_info->debug != MagickFalse)
2526 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2527 image_info->filename);
2528 assert(images != (Image *) NULL);
2529 assert(images->signature == MagickCoreSignature);
2530 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2531 assert(image_info->custom_stream->signature == MagickCoreSignature);
2532 assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
2533 assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2534 assert(exception != (ExceptionInfo *) NULL);
2535 clone_info=CloneImageInfo(image_info);
2536 (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2538 if (*clone_info->magick != '\0')
2539 (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2540 magick_info=GetMagickInfo(images->magick,exception);
2541 if (magick_info == (const MagickInfo *) NULL)
2543 (void) ThrowMagickException(exception,GetMagickModule(),
2544 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2546 clone_info=DestroyImageInfo(clone_info);
2549 (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2550 blob_support=GetMagickBlobSupport(magick_info);
2551 if ((blob_support != MagickFalse) &&
2552 (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2554 if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2555 (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2556 blob_support=MagickFalse;
2558 if (blob_support != MagickFalse)
2561 Native blob support for this image format.
2563 (void) CloseBlob(images);
2564 *images->filename='\0';
2565 (void) WriteImages(clone_info,images,images->filename,exception);
2566 (void) CloseBlob(images);
2571 filename[MagickPathExtent],
2572 unique[MagickPathExtent];
2581 Write file to disk in blob image format.
2583 clone_info->custom_stream=(CustomStreamInfo *) NULL;
2584 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2586 if (blob == (unsigned char *) NULL)
2588 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2589 image_info->filename);
2590 clone_info=DestroyImageInfo(clone_info);
2593 file=AcquireUniqueFileResource(unique);
2596 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2597 image_info->filename);
2598 blob=(unsigned char *) RelinquishMagickMemory(blob);
2599 clone_info=DestroyImageInfo(clone_info);
2602 clone_info->file=fdopen(file,"wb+");
2603 if (clone_info->file != (FILE *) NULL)
2608 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2609 images->magick,unique);
2610 status=WriteImages(clone_info,images,filename,exception);
2611 (void) CloseBlob(images);
2612 if (status != MagickFalse)
2614 (void) fseek(clone_info->file,0,SEEK_SET);
2615 count=(ssize_t) MagickMaxBufferExtent;
2616 while (count == (ssize_t) MagickMaxBufferExtent)
2618 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2620 (void) image_info->custom_stream->writer(blob,(size_t) count,
2621 image_info->custom_stream->data);
2624 (void) fclose(clone_info->file);
2626 blob=(unsigned char *) RelinquishMagickMemory(blob);
2627 (void) RelinquishUniqueFileResource(unique);
2629 clone_info=DestroyImageInfo(clone_info);
2633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2637 % I n j e c t I m a g e B l o b %
2641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2643 % InjectImageBlob() injects the image with a copy of itself in the specified
2644 % format (e.g. inject JPEG into a PDF image).
2646 % The format of the InjectImageBlob method is:
2648 % MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2649 % Image *image,Image *inject_image,const char *format,
2650 % ExceptionInfo *exception)
2652 % A description of each parameter follows:
2654 % o image_info: the image info..
2656 % o image: the image.
2658 % o inject_image: inject into the image stream.
2660 % o format: the image format.
2662 % o exception: return any errors or warnings in this structure.
2665 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2666 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2669 filename[MagickPathExtent];
2702 Write inject image to a temporary file.
2704 assert(image_info != (ImageInfo *) NULL);
2705 assert(image_info->signature == MagickCoreSignature);
2706 assert(image != (Image *) NULL);
2707 assert(image->signature == MagickCoreSignature);
2708 if (image->debug != MagickFalse)
2709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2710 assert(inject_image != (Image *) NULL);
2711 assert(inject_image->signature == MagickCoreSignature);
2712 assert(exception != (ExceptionInfo *) NULL);
2713 unique_file=(FILE *) NULL;
2714 file=AcquireUniqueFileResource(filename);
2716 unique_file=fdopen(file,"wb");
2717 if ((file == -1) || (unique_file == (FILE *) NULL))
2719 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2720 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2722 return(MagickFalse);
2724 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2725 if (byte_image == (Image *) NULL)
2727 (void) fclose(unique_file);
2728 (void) RelinquishUniqueFileResource(filename);
2729 return(MagickFalse);
2731 (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2733 DestroyBlob(byte_image);
2734 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2735 write_info=CloneImageInfo(image_info);
2736 SetImageInfoFile(write_info,unique_file);
2737 status=WriteImage(write_info,byte_image,exception);
2738 write_info=DestroyImageInfo(write_info);
2739 byte_image=DestroyImage(byte_image);
2740 (void) fclose(unique_file);
2741 if (status == MagickFalse)
2743 (void) RelinquishUniqueFileResource(filename);
2744 return(MagickFalse);
2747 Inject into image stream.
2749 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2752 (void) RelinquishUniqueFileResource(filename);
2753 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2754 image_info->filename);
2755 return(MagickFalse);
2757 quantum=(size_t) MagickMaxBufferExtent;
2758 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2759 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2760 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2761 if (buffer == (unsigned char *) NULL)
2763 (void) RelinquishUniqueFileResource(filename);
2765 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2768 for (i=0; ; i+=count)
2770 count=read(file,buffer,quantum);
2777 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2782 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2783 (void) RelinquishUniqueFileResource(filename);
2784 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2793 % I s B l o b E x e m p t %
2797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2799 % IsBlobExempt() returns true if the blob is exempt.
2801 % The format of the IsBlobExempt method is:
2803 % MagickBooleanType IsBlobExempt(const Image *image)
2805 % A description of each parameter follows:
2807 % o image: the image.
2810 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2812 assert(image != (const Image *) NULL);
2813 assert(image->signature == MagickCoreSignature);
2814 if (image->debug != MagickFalse)
2815 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2816 return(image->blob->exempt);
2820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2824 % I s B l o b S e e k a b l e %
2828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2830 % IsBlobSeekable() returns true if the blob is seekable.
2832 % The format of the IsBlobSeekable method is:
2834 % MagickBooleanType IsBlobSeekable(const Image *image)
2836 % A description of each parameter follows:
2838 % o image: the image.
2841 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2844 *magick_restrict blob_info;
2846 assert(image != (const Image *) NULL);
2847 assert(image->signature == MagickCoreSignature);
2848 if (image->debug != MagickFalse)
2849 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2850 blob_info=image->blob;
2851 switch (blob_info->type)
2860 if (blob_info->file_info.file == (FILE *) NULL)
2861 return(MagickFalse);
2862 status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2863 return(status == -1 ? MagickFalse : MagickTrue);
2867 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2871 if (blob_info->file_info.gzfile == (gzFile) NULL)
2872 return(MagickFalse);
2873 status=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2874 return(status == -1 ? MagickFalse : MagickTrue);
2879 case UndefinedStream:
2883 case StandardStream:
2887 if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
2888 (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
2895 return(MagickFalse);
2899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2903 % I s B l o b T e m p o r a r y %
2907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2909 % IsBlobTemporary() returns true if the blob is temporary.
2911 % The format of the IsBlobTemporary method is:
2913 % MagickBooleanType IsBlobTemporary(const Image *image)
2915 % A description of each parameter follows:
2917 % o image: the image.
2920 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2922 assert(image != (const Image *) NULL);
2923 assert(image->signature == MagickCoreSignature);
2924 if (image->debug != MagickFalse)
2925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2926 return(image->blob->temporary);
2930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2940 % MapBlob() creates a mapping from a file to a binary large object.
2942 % The format of the MapBlob method is:
2944 % void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2945 % const size_t length)
2947 % A description of each parameter follows:
2949 % o file: map this file descriptor.
2951 % o mode: ReadMode, WriteMode, or IOMode.
2953 % o offset: starting at this offset within the file.
2955 % o length: the length of the mapping is returned in this pointer.
2958 MagickExport void *MapBlob(int file,const MapMode mode,
2959 const MagickOffsetType offset,const size_t length)
2961 #if defined(MAGICKCORE_HAVE_MMAP)
2974 #if defined(MAP_ANONYMOUS)
2975 flags|=MAP_ANONYMOUS;
2984 protection=PROT_READ;
2990 protection=PROT_WRITE;
2996 protection=PROT_READ | PROT_WRITE;
3001 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
3002 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
3004 map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
3006 if (map == MAP_FAILED)
3007 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
3009 if (map == MAP_FAILED)
3022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3026 + M S B O r d e r L o n g %
3030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3032 % MSBOrderLong() converts a least-significant byte first buffer of integers to
3033 % most-significant byte first.
3035 % The format of the MSBOrderLong method is:
3037 % void MSBOrderLong(unsigned char *buffer,const size_t length)
3039 % A description of each parameter follows.
3041 % o buffer: Specifies a pointer to a buffer of integers.
3043 % o length: Specifies the length of the buffer.
3046 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
3051 register unsigned char
3055 assert(buffer != (unsigned char *) NULL);
3062 *buffer++=(unsigned char) c;
3066 *buffer++=(unsigned char) c;
3072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3076 + M S B O r d e r S h o r t %
3080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3082 % MSBOrderShort() converts a least-significant byte first buffer of integers
3083 % to most-significant byte first.
3085 % The format of the MSBOrderShort method is:
3087 % void MSBOrderShort(unsigned char *p,const size_t length)
3089 % A description of each parameter follows.
3091 % o p: Specifies a pointer to a buffer of integers.
3093 % o length: Specifies the length of the buffer.
3096 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
3101 register unsigned char
3104 assert(p != (unsigned char *) NULL);
3111 *p++=(unsigned char) c;
3116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3126 % OpenBlob() opens a file associated with the image. A file name of '-' sets
3127 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
3128 % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
3129 % compressed for type 'w'. If the filename prefix is '|', it is piped to or
3130 % from a system command.
3132 % The format of the OpenBlob method is:
3134 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
3135 % const BlobMode mode,ExceptionInfo *exception)
3137 % A description of each parameter follows:
3139 % o image_info: the image info.
3141 % o image: the image.
3143 % o mode: the mode for opening the file.
3147 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
3160 option=GetImageOption(image_info,"stream:buffer-size");
3161 if (option != (const char *) NULL)
3162 size=StringToUnsignedLong(option);
3163 status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
3164 _IONBF : _IOFBF,size);
3165 return(status == 0 ? MagickTrue : MagickFalse);
3168 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
3169 Image *image,const BlobMode mode,ExceptionInfo *exception)
3172 *magick_restrict blob_info;
3175 extension[MagickPathExtent],
3176 filename[MagickPathExtent];
3187 assert(image_info != (ImageInfo *) NULL);
3188 assert(image_info->signature == MagickCoreSignature);
3189 if (image_info->debug != MagickFalse)
3190 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3191 image_info->filename);
3192 assert(image != (Image *) NULL);
3193 assert(image->signature == MagickCoreSignature);
3194 blob_info=image->blob;
3195 if (image_info->blob != (void *) NULL)
3197 if (image_info->stream != (StreamHandler) NULL)
3198 blob_info->stream=(StreamHandler) image_info->stream;
3199 AttachBlob(blob_info,image_info->blob,image_info->length);
3202 if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3203 (*image->filename == '\0'))
3205 blob_info->type=CustomStream;
3206 blob_info->custom_stream=image_info->custom_stream;
3209 (void) DetachBlob(blob_info);
3210 blob_info->mode=mode;
3213 default: type="r"; break;
3214 case ReadBlobMode: type="r"; break;
3215 case ReadBinaryBlobMode: type="rb"; break;
3216 case WriteBlobMode: type="w"; break;
3217 case WriteBinaryBlobMode: type="w+b"; break;
3218 case AppendBlobMode: type="a"; break;
3219 case AppendBinaryBlobMode: type="a+b"; break;
3222 blob_info->synchronize=image_info->synchronize;
3223 if (image_info->stream != (StreamHandler) NULL)
3225 blob_info->stream=image_info->stream;
3228 blob_info->type=FifoStream;
3236 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3237 rights=ReadPolicyRights;
3239 rights=WritePolicyRights;
3240 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
3243 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
3244 "NotAuthorized","`%s'",filename);
3245 return(MagickFalse);
3247 if ((LocaleCompare(filename,"-") == 0) ||
3248 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3250 blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3251 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3252 if (strchr(type,'b') != (char *) NULL)
3253 setmode(fileno(blob_info->file_info.file),_O_BINARY);
3255 blob_info->type=StandardStream;
3256 blob_info->exempt=MagickTrue;
3257 return(SetStreamBuffering(image_info,image));
3259 if ((LocaleNCompare(filename,"fd:",3) == 0) &&
3260 (IsGeometry(filename+3) != MagickFalse))
3263 fileMode[MagickPathExtent];
3267 blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
3268 if (blob_info->file_info.file == (FILE *) NULL)
3270 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3271 return(MagickFalse);
3273 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3274 if (strchr(type,'b') != (char *) NULL)
3275 setmode(fileno(blob_info->file_info.file),_O_BINARY);
3277 blob_info->type=FileStream;
3278 blob_info->exempt=MagickTrue;
3279 return(SetStreamBuffering(image_info,image));
3281 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3282 if (*filename == '|')
3285 fileMode[MagickPathExtent],
3289 Pipe image to or from a system command.
3291 #if defined(SIGPIPE)
3293 (void) signal(SIGPIPE,SIG_IGN);
3297 sanitize_command=SanitizeString(filename+1);
3298 blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3299 sanitize_command=DestroyString(sanitize_command);
3300 if (blob_info->file_info.file == (FILE *) NULL)
3302 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3303 return(MagickFalse);
3305 blob_info->type=PipeStream;
3306 blob_info->exempt=MagickTrue;
3307 return(SetStreamBuffering(image_info,image));
3310 status=GetPathAttributes(filename,&blob_info->properties);
3311 #if defined(S_ISFIFO)
3312 if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3314 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3315 if (blob_info->file_info.file == (FILE *) NULL)
3317 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3318 return(MagickFalse);
3320 blob_info->type=FileStream;
3321 blob_info->exempt=MagickTrue;
3322 return(SetStreamBuffering(image_info,image));
3325 GetPathComponent(image->filename,ExtensionPath,extension);
3328 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3329 if ((image_info->adjoin == MagickFalse) ||
3330 (strchr(filename,'%') != (char *) NULL))
3333 Form filename for multi-part images.
3335 (void) InterpretImageFilename(image_info,image,image->filename,(int)
3336 image->scene,filename,exception);
3337 if ((LocaleCompare(filename,image->filename) == 0) &&
3338 ((GetPreviousImageInList(image) != (Image *) NULL) ||
3339 (GetNextImageInList(image) != (Image *) NULL)))
3342 path[MagickPathExtent];
3344 GetPathComponent(image->filename,RootPath,path);
3345 if (*extension == '\0')
3346 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
3347 path,(double) image->scene);
3349 (void) FormatLocaleString(filename,MagickPathExtent,
3350 "%s-%.20g.%s",path,(double) image->scene,extension);
3352 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3353 #if defined(macintosh)
3354 SetApplicationType(filename,image_info->magick,'8BIM');
3358 if (image_info->file != (FILE *) NULL)
3360 blob_info->file_info.file=image_info->file;
3361 blob_info->type=FileStream;
3362 blob_info->exempt=MagickTrue;
3367 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3368 if (blob_info->file_info.file != (FILE *) NULL)
3376 blob_info->type=FileStream;
3377 (void) SetStreamBuffering(image_info,image);
3378 (void) memset(magick,0,sizeof(magick));
3379 count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3380 (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3381 #if defined(MAGICKCORE_POSIX_SUPPORT)
3382 (void) fflush(blob_info->file_info.file);
3384 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
3385 " read %.20g magic header bytes",(double) count);
3386 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3387 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3388 ((int) magick[2] == 0x08))
3390 if (blob_info->file_info.file != (FILE *) NULL)
3391 (void) fclose(blob_info->file_info.file);
3392 blob_info->file_info.file=(FILE *) NULL;
3393 blob_info->file_info.gzfile=gzopen(filename,"rb");
3394 if (blob_info->file_info.gzfile != (gzFile) NULL)
3395 blob_info->type=ZipStream;
3398 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3399 if (strncmp((char *) magick,"BZh",3) == 0)
3401 if (blob_info->file_info.file != (FILE *) NULL)
3402 (void) fclose(blob_info->file_info.file);
3403 blob_info->file_info.file=(FILE *) NULL;
3404 blob_info->file_info.bzfile=BZ2_bzopen(filename,"r");
3405 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3406 blob_info->type=BZipStream;
3409 if (blob_info->type == FileStream)
3420 sans_exception=AcquireExceptionInfo();
3421 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3422 sans_exception=DestroyExceptionInfo(sans_exception);
3423 length=(size_t) blob_info->properties.st_size;
3424 if ((magick_info != (const MagickInfo *) NULL) &&
3425 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3426 (length > MagickMaxBufferExtent) &&
3427 (AcquireMagickResource(MapResource,length) != MagickFalse))
3432 blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3434 if (blob == (void *) NULL)
3435 RelinquishMagickResource(MapResource,length);
3439 Format supports blobs-- use memory-mapped I/O.
3441 if (image_info->file != (FILE *) NULL)
3442 blob_info->exempt=MagickFalse;
3445 (void) fclose(blob_info->file_info.file);
3446 blob_info->file_info.file=(FILE *) NULL;
3448 AttachBlob(blob_info,blob,length);
3449 blob_info->mapped=MagickTrue;
3456 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3457 if ((LocaleCompare(extension,"Z") == 0) ||
3458 (LocaleCompare(extension,"gz") == 0) ||
3459 (LocaleCompare(extension,"wmz") == 0) ||
3460 (LocaleCompare(extension,"svgz") == 0))
3462 blob_info->file_info.gzfile=gzopen(filename,"wb");
3463 if (blob_info->file_info.gzfile != (gzFile) NULL)
3464 blob_info->type=ZipStream;
3468 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3469 if (LocaleCompare(extension,"bz2") == 0)
3471 blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
3472 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3473 blob_info->type=BZipStream;
3478 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3479 if (blob_info->file_info.file != (FILE *) NULL)
3481 blob_info->type=FileStream;
3482 (void) SetStreamBuffering(image_info,image);
3485 blob_info->status=MagickFalse;
3486 if (blob_info->type != UndefinedStream)
3487 blob_info->size=GetBlobSize(image);
3490 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3491 return(MagickFalse);
3497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3507 % PingBlob() returns all the attributes of an image or image sequence except
3508 % for the pixels. It is much faster and consumes far less memory than
3509 % BlobToImage(). On failure, a NULL image is returned and exception
3510 % describes the reason for the failure.
3512 % The format of the PingBlob method is:
3514 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
3515 % const size_t length,ExceptionInfo *exception)
3517 % A description of each parameter follows:
3519 % o image_info: the image info.
3521 % o blob: the address of a character stream in one of the image formats
3522 % understood by ImageMagick.
3524 % o length: This size_t integer reflects the length in bytes of the blob.
3526 % o exception: return any errors or warnings in this structure.
3530 #if defined(__cplusplus) || defined(c_plusplus)
3534 static size_t PingStream(const Image *magick_unused(image),
3535 const void *magick_unused(pixels),const size_t columns)
3537 magick_unreferenced(image);
3538 magick_unreferenced(pixels);
3542 #if defined(__cplusplus) || defined(c_plusplus)
3546 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3547 const size_t length,ExceptionInfo *exception)
3562 assert(image_info != (ImageInfo *) NULL);
3563 assert(image_info->signature == MagickCoreSignature);
3564 if (image_info->debug != MagickFalse)
3565 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3566 image_info->filename);
3567 assert(exception != (ExceptionInfo *) NULL);
3568 if ((blob == (const void *) NULL) || (length == 0))
3570 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3571 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3572 return((Image *) NULL);
3574 ping_info=CloneImageInfo(image_info);
3575 ping_info->blob=(void *) blob;
3576 ping_info->length=length;
3577 ping_info->ping=MagickTrue;
3578 if (*ping_info->magick == '\0')
3579 (void) SetImageInfo(ping_info,0,exception);
3580 magick_info=GetMagickInfo(ping_info->magick,exception);
3581 if (magick_info == (const MagickInfo *) NULL)
3583 (void) ThrowMagickException(exception,GetMagickModule(),
3584 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3586 ping_info=DestroyImageInfo(ping_info);
3587 return((Image *) NULL);
3589 if (GetMagickBlobSupport(magick_info) != MagickFalse)
3592 filename[MagickPathExtent];
3595 Native blob support for this image format.
3597 (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3598 (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3599 ping_info->magick,filename);
3600 image=ReadStream(ping_info,&PingStream,exception);
3601 if (image != (Image *) NULL)
3602 (void) DetachBlob(image->blob);
3603 ping_info=DestroyImageInfo(ping_info);
3607 Write blob to a temporary file on disk.
3609 ping_info->blob=(void *) NULL;
3610 ping_info->length=0;
3611 *ping_info->filename='\0';
3612 status=BlobToFile(ping_info->filename,blob,length,exception);
3613 if (status == MagickFalse)
3615 (void) RelinquishUniqueFileResource(ping_info->filename);
3616 ping_info=DestroyImageInfo(ping_info);
3617 return((Image *) NULL);
3619 clone_info=CloneImageInfo(ping_info);
3620 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3621 ping_info->magick,ping_info->filename);
3622 image=ReadStream(clone_info,&PingStream,exception);
3623 if (image != (Image *) NULL)
3629 Restore original filenames and image format.
3631 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3633 (void) CopyMagickString(images->filename,image_info->filename,
3635 (void) CopyMagickString(images->magick_filename,image_info->filename,
3637 (void) CopyMagickString(images->magick,magick_info->name,
3639 images=GetNextImageInList(images);
3642 clone_info=DestroyImageInfo(clone_info);
3643 (void) RelinquishUniqueFileResource(ping_info->filename);
3644 ping_info=DestroyImageInfo(ping_info);
3649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3659 % ReadBlob() reads data from the blob or image file and returns it. It
3660 % returns the number of bytes read. If length is zero, ReadBlob() returns
3661 % zero and has no other results. If length is greater than SSIZE_MAX, the
3662 % result is unspecified.
3664 % The format of the ReadBlob method is:
3666 % ssize_t ReadBlob(Image *image,const size_t length,void *data)
3668 % A description of each parameter follows:
3670 % o image: the image.
3672 % o length: Specifies an integer representing the number of bytes to read
3675 % o data: Specifies an area to place the information requested from the
3679 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3682 *magick_restrict blob_info;
3687 register unsigned char
3693 assert(image != (Image *) NULL);
3694 assert(image->signature == MagickCoreSignature);
3695 assert(image->blob != (BlobInfo *) NULL);
3696 assert(image->blob->type != UndefinedStream);
3699 assert(data != (void *) NULL);
3700 blob_info=image->blob;
3702 q=(unsigned char *) data;
3703 switch (blob_info->type)
3705 case UndefinedStream:
3707 case StandardStream:
3715 count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3720 c=getc(blob_info->file_info.file);
3723 *q++=(unsigned char) c;
3728 c=getc(blob_info->file_info.file);
3731 *q++=(unsigned char) c;
3736 c=getc(blob_info->file_info.file);
3739 *q++=(unsigned char) c;
3744 c=getc(blob_info->file_info.file);
3747 *q++=(unsigned char) c;
3757 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3765 for (i=0; i < (ssize_t) length; i+=count)
3767 count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3768 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3781 c=gzgetc(blob_info->file_info.gzfile);
3784 *q++=(unsigned char) c;
3789 c=gzgetc(blob_info->file_info.gzfile);
3792 *q++=(unsigned char) c;
3797 c=gzgetc(blob_info->file_info.gzfile);
3800 *q++=(unsigned char) c;
3805 c=gzgetc(blob_info->file_info.gzfile);
3808 *q++=(unsigned char) c;
3819 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3823 for (i=0; i < (ssize_t) length; i+=count)
3825 count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
3826 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3842 register const unsigned char
3845 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3847 blob_info->eof=MagickTrue;
3850 p=blob_info->data+blob_info->offset;
3851 count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3852 blob_info->length-blob_info->offset);
3853 blob_info->offset+=count;
3854 if (count != (ssize_t) length)
3855 blob_info->eof=MagickTrue;
3856 (void) memcpy(q,p,(size_t) count);
3861 if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
3862 count=blob_info->custom_stream->reader(q,length,
3863 blob_info->custom_stream->data);
3871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3875 + R e a d B l o b B y t e %
3879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3881 % ReadBlobByte() reads a single byte from the image file and returns it.
3883 % The format of the ReadBlobByte method is:
3885 % int ReadBlobByte(Image *image)
3887 % A description of each parameter follows.
3889 % o image: the image.
3892 MagickExport int ReadBlobByte(Image *image)
3895 *magick_restrict blob_info;
3897 register const unsigned char
3903 assert(image != (Image *) NULL);
3904 assert(image->signature == MagickCoreSignature);
3905 assert(image->blob != (BlobInfo *) NULL);
3906 assert(image->blob->type != UndefinedStream);
3907 blob_info=image->blob;
3908 switch (blob_info->type)
3910 case StandardStream:
3917 p=(const unsigned char *) buffer;
3918 c=getc(blob_info->file_info.file);
3921 *buffer=(unsigned char) c;
3929 p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3939 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3943 + R e a d B l o b D o u b l e %
3947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3949 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3950 % specified by the endian member of the image structure.
3952 % The format of the ReadBlobDouble method is:
3954 % double ReadBlobDouble(Image *image)
3956 % A description of each parameter follows.
3958 % o image: the image.
3961 MagickExport double ReadBlobDouble(Image *image)
3972 quantum.double_value=0.0;
3973 quantum.unsigned_value=ReadBlobLongLong(image);
3974 return(quantum.double_value);
3978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3982 + R e a d B l o b F l o a t %
3986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3988 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3989 % specified by the endian member of the image structure.
3991 % The format of the ReadBlobFloat method is:
3993 % float ReadBlobFloat(Image *image)
3995 % A description of each parameter follows.
3997 % o image: the image.
4000 MagickExport float ReadBlobFloat(Image *image)
4011 quantum.float_value=0.0;
4012 quantum.unsigned_value=ReadBlobLong(image);
4013 return(quantum.float_value);
4017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4021 + R e a d B l o b L o n g %
4025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4027 % ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
4028 % byte-order specified by the endian member of the image structure.
4030 % The format of the ReadBlobLong method is:
4032 % unsigned int ReadBlobLong(Image *image)
4034 % A description of each parameter follows.
4036 % o image: the image.
4039 MagickExport unsigned int ReadBlobLong(Image *image)
4041 register const unsigned char
4053 assert(image != (Image *) NULL);
4054 assert(image->signature == MagickCoreSignature);
4056 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4059 if (image->endian == LSBEndian)
4061 value=(unsigned int) (*p++);
4062 value|=(unsigned int) (*p++) << 8;
4063 value|=(unsigned int) (*p++) << 16;
4064 value|=(unsigned int) (*p++) << 24;
4067 value=(unsigned int) (*p++) << 24;
4068 value|=(unsigned int) (*p++) << 16;
4069 value|=(unsigned int) (*p++) << 8;
4070 value|=(unsigned int) (*p++);
4075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4079 + R e a d B l o b L o n g L o n g %
4083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4085 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
4086 % byte-order specified by the endian member of the image structure.
4088 % The format of the ReadBlobLongLong method is:
4090 % MagickSizeType ReadBlobLongLong(Image *image)
4092 % A description of each parameter follows.
4094 % o image: the image.
4097 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
4102 register const unsigned char
4111 assert(image != (Image *) NULL);
4112 assert(image->signature == MagickCoreSignature);
4114 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4116 return(MagickULLConstant(0));
4117 if (image->endian == LSBEndian)
4119 value=(MagickSizeType) (*p++);
4120 value|=(MagickSizeType) (*p++) << 8;
4121 value|=(MagickSizeType) (*p++) << 16;
4122 value|=(MagickSizeType) (*p++) << 24;
4123 value|=(MagickSizeType) (*p++) << 32;
4124 value|=(MagickSizeType) (*p++) << 40;
4125 value|=(MagickSizeType) (*p++) << 48;
4126 value|=(MagickSizeType) (*p++) << 56;
4129 value=(MagickSizeType) (*p++) << 56;
4130 value|=(MagickSizeType) (*p++) << 48;
4131 value|=(MagickSizeType) (*p++) << 40;
4132 value|=(MagickSizeType) (*p++) << 32;
4133 value|=(MagickSizeType) (*p++) << 24;
4134 value|=(MagickSizeType) (*p++) << 16;
4135 value|=(MagickSizeType) (*p++) << 8;
4136 value|=(MagickSizeType) (*p++);
4141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4145 + R e a d B l o b S h o r t %
4149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4151 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
4152 % specified by the endian member of the image structure.
4154 % The format of the ReadBlobShort method is:
4156 % unsigned short ReadBlobShort(Image *image)
4158 % A description of each parameter follows.
4160 % o image: the image.
4163 MagickExport unsigned short ReadBlobShort(Image *image)
4165 register const unsigned char
4168 register unsigned short
4177 assert(image != (Image *) NULL);
4178 assert(image->signature == MagickCoreSignature);
4180 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4182 return((unsigned short) 0U);
4183 if (image->endian == LSBEndian)
4185 value=(unsigned short) (*p++);
4186 value|=(unsigned short) (*p++) << 8;
4189 value=(unsigned short) ((unsigned short) (*p++) << 8);
4190 value|=(unsigned short) (*p++);
4195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4199 + R e a d B l o b L S B L o n g %
4203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4205 % ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
4206 % least-significant byte first order.
4208 % The format of the ReadBlobLSBLong method is:
4210 % unsigned int ReadBlobLSBLong(Image *image)
4212 % A description of each parameter follows.
4214 % o image: the image.
4217 MagickExport unsigned int ReadBlobLSBLong(Image *image)
4219 register const unsigned char
4222 register unsigned int
4231 assert(image != (Image *) NULL);
4232 assert(image->signature == MagickCoreSignature);
4234 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4237 value=(unsigned int) (*p++);
4238 value|=(unsigned int) (*p++) << 8;
4239 value|=(unsigned int) (*p++) << 16;
4240 value|=(unsigned int) (*p++) << 24;
4245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4249 + R e a d B l o b L S B S i g n e d L o n g %
4253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4255 % ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
4256 % least-significant byte first order.
4258 % The format of the ReadBlobLSBSignedLong method is:
4260 % signed int ReadBlobLSBSignedLong(Image *image)
4262 % A description of each parameter follows.
4264 % o image: the image.
4267 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
4278 quantum.unsigned_value=ReadBlobLSBLong(image);
4279 return(quantum.signed_value);
4283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4287 + R e a d B l o b L S B S h o r t %
4291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4293 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4294 % least-significant byte first order.
4296 % The format of the ReadBlobLSBShort method is:
4298 % unsigned short ReadBlobLSBShort(Image *image)
4300 % A description of each parameter follows.
4302 % o image: the image.
4305 MagickExport unsigned short ReadBlobLSBShort(Image *image)
4307 register const unsigned char
4310 register unsigned short
4319 assert(image != (Image *) NULL);
4320 assert(image->signature == MagickCoreSignature);
4322 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4324 return((unsigned short) 0U);
4325 value=(unsigned short) (*p++);
4326 value|=(unsigned short) (*p++) << 8;
4331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4335 + R e a d B l o b L S B S i g n e d S h o r t %
4339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4341 % ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4342 % least-significant byte-order.
4344 % The format of the ReadBlobLSBSignedShort method is:
4346 % signed short ReadBlobLSBSignedShort(Image *image)
4348 % A description of each parameter follows.
4350 % o image: the image.
4353 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
4364 quantum.unsigned_value=ReadBlobLSBShort(image);
4365 return(quantum.signed_value);
4369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4373 + R e a d B l o b M S B L o n g %
4377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4379 % ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4380 % most-significant byte first order.
4382 % The format of the ReadBlobMSBLong method is:
4384 % unsigned int ReadBlobMSBLong(Image *image)
4386 % A description of each parameter follows.
4388 % o image: the image.
4391 MagickExport unsigned int ReadBlobMSBLong(Image *image)
4393 register const unsigned char
4396 register unsigned int
4405 assert(image != (Image *) NULL);
4406 assert(image->signature == MagickCoreSignature);
4408 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4411 value=(unsigned int) (*p++) << 24;
4412 value|=(unsigned int) (*p++) << 16;
4413 value|=(unsigned int) (*p++) << 8;
4414 value|=(unsigned int) (*p++);
4419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4423 + R e a d B l o b M S B L o n g L o n g %
4427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4429 % ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4430 % in most-significant byte first order.
4432 % The format of the ReadBlobMSBLongLong method is:
4434 % unsigned int ReadBlobMSBLongLong(Image *image)
4436 % A description of each parameter follows.
4438 % o image: the image.
4441 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
4443 register const unsigned char
4446 register MagickSizeType
4455 assert(image != (Image *) NULL);
4456 assert(image->signature == MagickCoreSignature);
4458 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4460 return(MagickULLConstant(0));
4461 value=(MagickSizeType) (*p++) << 56;
4462 value|=(MagickSizeType) (*p++) << 48;
4463 value|=(MagickSizeType) (*p++) << 40;
4464 value|=(MagickSizeType) (*p++) << 32;
4465 value|=(MagickSizeType) (*p++) << 24;
4466 value|=(MagickSizeType) (*p++) << 16;
4467 value|=(MagickSizeType) (*p++) << 8;
4468 value|=(MagickSizeType) (*p++);
4473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4477 + R e a d B l o b M S B S h o r t %
4481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4483 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4484 % most-significant byte first order.
4486 % The format of the ReadBlobMSBShort method is:
4488 % unsigned short ReadBlobMSBShort(Image *image)
4490 % A description of each parameter follows.
4492 % o image: the image.
4495 MagickExport unsigned short ReadBlobMSBShort(Image *image)
4497 register const unsigned char
4500 register unsigned short
4509 assert(image != (Image *) NULL);
4510 assert(image->signature == MagickCoreSignature);
4512 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4514 return((unsigned short) 0U);
4515 value=(unsigned short) ((*p++) << 8);
4516 value|=(unsigned short) (*p++);
4517 return((unsigned short) (value & 0xffff));
4521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4525 + R e a d B l o b M S B S i g n e d L o n g %
4529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4531 % ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4532 % most-significant byte-order.
4534 % The format of the ReadBlobMSBSignedLong method is:
4536 % signed int ReadBlobMSBSignedLong(Image *image)
4538 % A description of each parameter follows.
4540 % o image: the image.
4543 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4554 quantum.unsigned_value=ReadBlobMSBLong(image);
4555 return(quantum.signed_value);
4559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4563 + R e a d B l o b M S B S i g n e d S h o r t %
4567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4569 % ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4570 % most-significant byte-order.
4572 % The format of the ReadBlobMSBSignedShort method is:
4574 % signed short ReadBlobMSBSignedShort(Image *image)
4576 % A description of each parameter follows.
4578 % o image: the image.
4581 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4592 quantum.unsigned_value=ReadBlobMSBShort(image);
4593 return(quantum.signed_value);
4597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4601 + R e a d B l o b S i g n e d L o n g %
4605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4607 % ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4608 % byte-order specified by the endian member of the image structure.
4610 % The format of the ReadBlobSignedLong method is:
4612 % signed int ReadBlobSignedLong(Image *image)
4614 % A description of each parameter follows.
4616 % o image: the image.
4619 MagickExport signed int ReadBlobSignedLong(Image *image)
4630 quantum.unsigned_value=ReadBlobLong(image);
4631 return(quantum.signed_value);
4635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4639 + R e a d B l o b S i g n e d S h o r t %
4643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4645 % ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4646 % byte-order specified by the endian member of the image structure.
4648 % The format of the ReadBlobSignedShort method is:
4650 % signed short ReadBlobSignedShort(Image *image)
4652 % A description of each parameter follows.
4654 % o image: the image.
4657 MagickExport signed short ReadBlobSignedShort(Image *image)
4668 quantum.unsigned_value=ReadBlobShort(image);
4669 return(quantum.signed_value);
4673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4677 + R e a d B l o b S t r e a m %
4681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4683 % ReadBlobStream() reads data from the blob or image file and returns it. It
4684 % returns a pointer to the data buffer you supply or to the image memory
4685 % buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4686 % returns a count of zero and has no other results. If length is greater than
4687 % SSIZE_MAX, the result is unspecified.
4689 % The format of the ReadBlobStream method is:
4691 % const void *ReadBlobStream(Image *image,const size_t length,void *data,
4694 % A description of each parameter follows:
4696 % o image: the image.
4698 % o length: Specifies an integer representing the number of bytes to read
4701 % o count: returns the number of bytes read.
4703 % o data: Specifies an area to place the information requested from the
4707 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
4708 void *data,ssize_t *count)
4711 *magick_restrict blob_info;
4713 assert(image != (Image *) NULL);
4714 assert(image->signature == MagickCoreSignature);
4715 assert(image->blob != (BlobInfo *) NULL);
4716 assert(image->blob->type != UndefinedStream);
4717 assert(count != (ssize_t *) NULL);
4718 blob_info=image->blob;
4719 if (blob_info->type != BlobStream)
4721 assert(data != NULL);
4722 *count=ReadBlob(image,length,(unsigned char *) data);
4725 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4728 blob_info->eof=MagickTrue;
4731 data=blob_info->data+blob_info->offset;
4732 *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4733 blob_info->length-blob_info->offset);
4734 blob_info->offset+=(*count);
4735 if (*count != (ssize_t) length)
4736 blob_info->eof=MagickTrue;
4741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4745 + R e a d B l o b S t r i n g %
4749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4751 % ReadBlobString() reads characters from a blob or file until a newline
4752 % character is read or an end-of-file condition is encountered.
4754 % The format of the ReadBlobString method is:
4756 % char *ReadBlobString(Image *image,char *string)
4758 % A description of each parameter follows:
4760 % o image: the image.
4762 % o string: the address of a character buffer.
4765 MagickExport char *ReadBlobString(Image *image,char *string)
4773 assert(image != (Image *) NULL);
4774 assert(image->signature == MagickCoreSignature);
4775 for (i=0; i < (MagickPathExtent-1L); i++)
4777 c=ReadBlobByte(image);
4781 return((char *) NULL);
4787 if ((i > 0) && (string[i-1] == '\r'))
4797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4801 + R e f e r e n c e B l o b %
4805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4807 % ReferenceBlob() increments the reference count associated with the pixel
4808 % blob returning a pointer to the blob.
4810 % The format of the ReferenceBlob method is:
4812 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
4814 % A description of each parameter follows:
4816 % o blob_info: the blob_info.
4819 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4821 assert(blob != (BlobInfo *) NULL);
4822 assert(blob->signature == MagickCoreSignature);
4823 if (blob->debug != MagickFalse)
4824 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4825 LockSemaphoreInfo(blob->semaphore);
4826 blob->reference_count++;
4827 UnlockSemaphoreInfo(blob->semaphore);
4832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4842 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
4843 % and returns the resulting offset.
4845 % The format of the SeekBlob method is:
4847 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4850 % A description of each parameter follows:
4852 % o image: the image.
4854 % o offset: Specifies an integer representing the offset in bytes.
4856 % o whence: Specifies an integer representing how the offset is
4857 % treated relative to the beginning of the blob as follows:
4859 % SEEK_SET Set position equal to offset bytes.
4860 % SEEK_CUR Set position to current location plus offset.
4861 % SEEK_END Set position to EOF plus offset.
4864 MagickExport MagickOffsetType SeekBlob(Image *image,
4865 const MagickOffsetType offset,const int whence)
4868 *magick_restrict blob_info;
4870 assert(image != (Image *) NULL);
4871 assert(image->signature == MagickCoreSignature);
4872 if (image->debug != MagickFalse)
4873 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4874 assert(image->blob != (BlobInfo *) NULL);
4875 assert(image->blob->type != UndefinedStream);
4876 blob_info=image->blob;
4877 switch (blob_info->type)
4879 case UndefinedStream:
4881 case StandardStream:
4886 if ((offset < 0) && (whence == SEEK_SET))
4888 if (fseek(blob_info->file_info.file,offset,whence) < 0)
4890 blob_info->offset=TellBlob(image);
4895 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4896 if (gzseek(blob_info->file_info.gzfile,(off_t) offset,whence) < 0)
4899 blob_info->offset=TellBlob(image);
4915 blob_info->offset=offset;
4920 if ((blob_info->offset+offset) < 0)
4922 blob_info->offset+=offset;
4927 if (((MagickOffsetType) blob_info->length+offset) < 0)
4929 blob_info->offset=blob_info->length+offset;
4933 if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
4935 blob_info->eof=MagickFalse;
4938 if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
4944 if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
4946 blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
4947 blob_info->custom_stream->data);
4951 return(blob_info->offset);
4955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4959 + S e t B l o b E x e m p t %
4963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4965 % SetBlobExempt() sets the blob exempt status.
4967 % The format of the SetBlobExempt method is:
4969 % MagickBooleanType SetBlobExempt(const Image *image,
4970 % const MagickBooleanType exempt)
4972 % A description of each parameter follows:
4974 % o image: the image.
4976 % o exempt: Set to true if this blob is exempt from being closed.
4979 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4981 assert(image != (const Image *) NULL);
4982 assert(image->signature == MagickCoreSignature);
4983 if (image->debug != MagickFalse)
4984 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4985 image->blob->exempt=exempt;
4989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4993 + S e t B l o b E x t e n t %
4997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4999 % SetBlobExtent() ensures enough space is allocated for the blob. If the
5000 % method is successful, subsequent writes to bytes in the specified range are
5001 % guaranteed not to fail.
5003 % The format of the SetBlobExtent method is:
5005 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
5007 % A description of each parameter follows:
5009 % o image: the image.
5011 % o extent: the blob maximum extent.
5014 MagickExport MagickBooleanType SetBlobExtent(Image *image,
5015 const MagickSizeType extent)
5018 *magick_restrict blob_info;
5020 assert(image != (Image *) NULL);
5021 assert(image->signature == MagickCoreSignature);
5022 if (image->debug != MagickFalse)
5023 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5024 assert(image->blob != (BlobInfo *) NULL);
5025 assert(image->blob->type != UndefinedStream);
5026 blob_info=image->blob;
5027 switch (blob_info->type)
5029 case UndefinedStream:
5031 case StandardStream:
5032 return(MagickFalse);
5041 if (extent != (MagickSizeType) ((off_t) extent))
5042 return(MagickFalse);
5043 offset=SeekBlob(image,0,SEEK_END);
5045 return(MagickFalse);
5046 if ((MagickSizeType) offset >= extent)
5048 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5051 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5052 blob_info->file_info.file);
5053 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5054 if (blob_info->synchronize != MagickFalse)
5059 file=fileno(blob_info->file_info.file);
5060 if ((file == -1) || (offset < 0))
5061 return(MagickFalse);
5062 (void) posix_fallocate(file,offset,extent-offset);
5065 offset=SeekBlob(image,offset,SEEK_SET);
5067 return(MagickFalse);
5072 return(MagickFalse);
5074 return(MagickFalse);
5076 return(MagickFalse);
5079 if (extent != (MagickSizeType) ((size_t) extent))
5080 return(MagickFalse);
5081 if (blob_info->mapped != MagickFalse)
5089 (void) UnmapBlob(blob_info->data,blob_info->length);
5090 RelinquishMagickResource(MapResource,blob_info->length);
5091 if (extent != (MagickSizeType) ((off_t) extent))
5092 return(MagickFalse);
5093 offset=SeekBlob(image,0,SEEK_END);
5095 return(MagickFalse);
5096 if ((MagickSizeType) offset >= extent)
5098 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5099 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5100 blob_info->file_info.file);
5101 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5102 if (blob_info->synchronize != MagickFalse)
5107 file=fileno(blob_info->file_info.file);
5108 if ((file == -1) || (offset < 0))
5109 return(MagickFalse);
5110 (void) posix_fallocate(file,offset,extent-offset);
5113 offset=SeekBlob(image,offset,SEEK_SET);
5115 return(MagickFalse);
5116 (void) AcquireMagickResource(MapResource,extent);
5117 blob_info->data=(unsigned char*) MapBlob(fileno(
5118 blob_info->file_info.file),WriteMode,0,(size_t) extent);
5119 blob_info->extent=(size_t) extent;
5120 blob_info->length=(size_t) extent;
5121 (void) SyncBlob(image);
5124 blob_info->extent=(size_t) extent;
5125 blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
5126 blob_info->extent+1,sizeof(*blob_info->data));
5127 (void) SyncBlob(image);
5128 if (blob_info->data == (unsigned char *) NULL)
5130 (void) DetachBlob(blob_info);
5131 return(MagickFalse);
5142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5146 + S e t C u s t o m S t r e a m D a t a %
5150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5152 % SetCustomStreamData() sets the stream info data member.
5154 % The format of the SetCustomStreamData method is:
5156 % void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
5158 % A description of each parameter follows:
5160 % o custom_stream: the custom stream info.
5162 % o data: an object containing information about the custom stream.
5165 MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
5168 assert(custom_stream != (CustomStreamInfo *) NULL);
5169 assert(custom_stream->signature == MagickCoreSignature);
5170 custom_stream->data=data;
5174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5178 + S e t C u s t o m S t r e a m R e a d e r %
5182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5184 % SetCustomStreamReader() sets the stream info reader member.
5186 % The format of the SetCustomStreamReader method is:
5188 % void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5189 % CustomStreamHandler reader)
5191 % A description of each parameter follows:
5193 % o custom_stream: the custom stream info.
5195 % o reader: a function to read from the stream.
5198 MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5199 CustomStreamHandler reader)
5201 assert(custom_stream != (CustomStreamInfo *) NULL);
5202 assert(custom_stream->signature == MagickCoreSignature);
5203 custom_stream->reader=reader;
5207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5211 + S e t C u s t o m S t r e a m S e e k e r %
5215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5217 % SetCustomStreamSeeker() sets the stream info seeker member.
5219 % The format of the SetCustomStreamReader method is:
5221 % void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5222 % CustomStreamSeeker seeker)
5224 % A description of each parameter follows:
5226 % o custom_stream: the custom stream info.
5228 % o seeker: a function to seek in the custom stream.
5231 MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5232 CustomStreamSeeker seeker)
5234 assert(custom_stream != (CustomStreamInfo *) NULL);
5235 assert(custom_stream->signature == MagickCoreSignature);
5236 custom_stream->seeker=seeker;
5240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5244 + S e t C u s t o m S t r e a m T e l l e r %
5248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5250 % SetCustomStreamTeller() sets the stream info teller member.
5252 % The format of the SetCustomStreamTeller method is:
5254 % void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5255 % CustomStreamTeller *teller)
5257 % A description of each parameter follows:
5259 % o custom_stream: the custom stream info.
5261 % o teller: a function to set the position in the stream.
5264 MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5265 CustomStreamTeller teller)
5267 assert(custom_stream != (CustomStreamInfo *) NULL);
5268 assert(custom_stream->signature == MagickCoreSignature);
5269 custom_stream->teller=teller;
5273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5277 + S e t C u s t o m S t r e a m W r i t e r %
5281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5283 % SetCustomStreamWriter() sets the stream info writer member.
5285 % The format of the SetCustomStreamWriter method is:
5287 % void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5288 % CustomStreamHandler *writer)
5290 % A description of each parameter follows:
5292 % o custom_stream: the custom stream info.
5294 % o writer: a function to write to the custom stream.
5297 MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5298 CustomStreamHandler writer)
5300 assert(custom_stream != (CustomStreamInfo *) NULL);
5301 assert(custom_stream->signature == MagickCoreSignature);
5302 custom_stream->writer=writer;
5306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5316 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
5317 % attributes if it is an blob.
5319 % The format of the SyncBlob method is:
5321 % int SyncBlob(Image *image)
5323 % A description of each parameter follows:
5325 % o image: the image.
5328 static int SyncBlob(Image *image)
5331 *magick_restrict blob_info;
5336 assert(image != (Image *) NULL);
5337 assert(image->signature == MagickCoreSignature);
5338 if (image->debug != MagickFalse)
5339 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5340 assert(image->blob != (BlobInfo *) NULL);
5341 assert(image->blob->type != UndefinedStream);
5342 blob_info=image->blob;
5344 switch (blob_info->type)
5346 case UndefinedStream:
5347 case StandardStream:
5352 status=fflush(blob_info->file_info.file);
5357 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5358 status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5364 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5365 status=BZ2_bzflush(blob_info->file_info.bzfile);
5380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5390 % TellBlob() obtains the current value of the blob or file position.
5392 % The format of the TellBlob method is:
5394 % MagickOffsetType TellBlob(const Image *image)
5396 % A description of each parameter follows:
5398 % o image: the image.
5401 MagickExport MagickOffsetType TellBlob(const Image *image)
5404 *magick_restrict blob_info;
5409 assert(image != (Image *) NULL);
5410 assert(image->signature == MagickCoreSignature);
5411 if (image->debug != MagickFalse)
5412 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5413 assert(image->blob != (BlobInfo *) NULL);
5414 assert(image->blob->type != UndefinedStream);
5415 blob_info=image->blob;
5417 switch (blob_info->type)
5419 case UndefinedStream:
5420 case StandardStream:
5424 offset=ftell(blob_info->file_info.file);
5431 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5432 offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5442 offset=blob_info->offset;
5447 if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5448 offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5460 + U n m a p B l o b %
5464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5466 % UnmapBlob() deallocates the binary large object previously allocated with
5467 % the MapBlob method.
5469 % The format of the UnmapBlob method is:
5471 % MagickBooleanType UnmapBlob(void *map,const size_t length)
5473 % A description of each parameter follows:
5475 % o map: the address of the binary large object.
5477 % o length: the length of the binary large object.
5480 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5482 #if defined(MAGICKCORE_HAVE_MMAP)
5486 status=munmap(map,length);
5487 return(status == -1 ? MagickFalse : MagickTrue);
5491 return(MagickFalse);
5496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5500 + W r i t e B l o b %
5504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5506 % WriteBlob() writes data to a blob or image file. It returns the number of
5509 % The format of the WriteBlob method is:
5511 % ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5513 % A description of each parameter follows:
5515 % o image: the image.
5517 % o length: Specifies an integer representing the number of bytes to
5518 % write to the file.
5520 % o data: The address of the data to write to the blob or file.
5523 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5527 *magick_restrict blob_info;
5532 register const unsigned char
5535 register unsigned char
5541 assert(image != (Image *) NULL);
5542 assert(image->signature == MagickCoreSignature);
5543 assert(image->blob != (BlobInfo *) NULL);
5544 assert(image->blob->type != UndefinedStream);
5547 assert(data != (const void *) NULL);
5548 blob_info=image->blob;
5550 p=(const unsigned char *) data;
5551 q=(unsigned char *) data;
5552 switch (blob_info->type)
5554 case UndefinedStream:
5556 case StandardStream:
5564 count=(ssize_t) fwrite((const char *) data,1,length,
5565 blob_info->file_info.file);
5570 c=putc((int) *p++,blob_info->file_info.file);
5577 c=putc((int) *p++,blob_info->file_info.file);
5584 c=putc((int) *p++,blob_info->file_info.file);
5591 c=putc((int) *p++,blob_info->file_info.file);
5603 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5611 for (i=0; i < (ssize_t) length; i+=count)
5613 count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
5614 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
5627 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5634 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5641 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5648 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5661 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5665 for (i=0; i < (ssize_t) length; i+=count)
5667 count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5668 (int) MagickMin(length-i,MagickMaxBufferExtent));
5682 count=(ssize_t) blob_info->stream(image,data,length);
5687 if ((blob_info->offset+(MagickOffsetType) length) >=
5688 (MagickOffsetType) blob_info->extent)
5690 if (blob_info->mapped != MagickFalse)
5692 blob_info->extent+=length+blob_info->quantum;
5693 blob_info->quantum<<=1;
5694 blob_info->data=(unsigned char *) ResizeQuantumMemory(
5695 blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5696 (void) SyncBlob(image);
5697 if (blob_info->data == (unsigned char *) NULL)
5699 (void) DetachBlob(blob_info);
5703 q=blob_info->data+blob_info->offset;
5704 (void) memcpy(q,p,length);
5705 blob_info->offset+=length;
5706 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5707 blob_info->length=(size_t) blob_info->offset;
5708 count=(ssize_t) length;
5713 if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
5714 count=blob_info->custom_stream->writer((unsigned char *) data,
5715 length,blob_info->custom_stream->data);
5723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5727 + W r i t e B l o b B y t e %
5731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5733 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
5734 % written (either 0 or 1);
5736 % The format of the WriteBlobByte method is:
5738 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
5740 % A description of each parameter follows.
5742 % o image: the image.
5744 % o value: Specifies the value to write.
5747 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5750 *magick_restrict blob_info;
5755 assert(image != (Image *) NULL);
5756 assert(image->signature == MagickCoreSignature);
5757 assert(image->blob != (BlobInfo *) NULL);
5758 assert(image->blob->type != UndefinedStream);
5759 blob_info=image->blob;
5761 switch (blob_info->type)
5763 case StandardStream:
5770 c=putc((int) value,blob_info->file_info.file);
5778 count=WriteBlobStream(image,1,&value);
5786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5790 + W r i t e B l o b F l o a t %
5794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5796 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5797 % specified by the endian member of the image structure.
5799 % The format of the WriteBlobFloat method is:
5801 % ssize_t WriteBlobFloat(Image *image,const float value)
5803 % A description of each parameter follows.
5805 % o image: the image.
5807 % o value: Specifies the value to write.
5810 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5821 quantum.unsigned_value=0U;
5822 quantum.float_value=value;
5823 return(WriteBlobLong(image,quantum.unsigned_value));
5827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5831 + W r i t e B l o b L o n g %
5835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5837 % WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5838 % byte-order specified by the endian member of the image structure.
5840 % The format of the WriteBlobLong method is:
5842 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
5844 % A description of each parameter follows.
5846 % o image: the image.
5848 % o value: Specifies the value to write.
5851 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5856 assert(image != (Image *) NULL);
5857 assert(image->signature == MagickCoreSignature);
5858 if (image->endian == LSBEndian)
5860 buffer[0]=(unsigned char) value;
5861 buffer[1]=(unsigned char) (value >> 8);
5862 buffer[2]=(unsigned char) (value >> 16);
5863 buffer[3]=(unsigned char) (value >> 24);
5864 return(WriteBlobStream(image,4,buffer));
5866 buffer[0]=(unsigned char) (value >> 24);
5867 buffer[1]=(unsigned char) (value >> 16);
5868 buffer[2]=(unsigned char) (value >> 8);
5869 buffer[3]=(unsigned char) value;
5870 return(WriteBlobStream(image,4,buffer));
5874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5878 + W r i t e B l o b L o n g L o n g %
5882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5884 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
5885 % byte-order specified by the endian member of the image structure.
5887 % The format of the WriteBlobLongLong method is:
5889 % ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5891 % A description of each parameter follows.
5893 % o value: Specifies the value to write.
5895 % o image: the image.
5898 MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5903 assert(image != (Image *) NULL);
5904 assert(image->signature == MagickCoreSignature);
5905 if (image->endian == LSBEndian)
5907 buffer[0]=(unsigned char) value;
5908 buffer[1]=(unsigned char) (value >> 8);
5909 buffer[2]=(unsigned char) (value >> 16);
5910 buffer[3]=(unsigned char) (value >> 24);
5911 buffer[4]=(unsigned char) (value >> 32);
5912 buffer[5]=(unsigned char) (value >> 40);
5913 buffer[6]=(unsigned char) (value >> 48);
5914 buffer[7]=(unsigned char) (value >> 56);
5915 return(WriteBlobStream(image,8,buffer));
5917 buffer[0]=(unsigned char) (value >> 56);
5918 buffer[1]=(unsigned char) (value >> 48);
5919 buffer[2]=(unsigned char) (value >> 40);
5920 buffer[3]=(unsigned char) (value >> 32);
5921 buffer[4]=(unsigned char) (value >> 24);
5922 buffer[5]=(unsigned char) (value >> 16);
5923 buffer[6]=(unsigned char) (value >> 8);
5924 buffer[7]=(unsigned char) value;
5925 return(WriteBlobStream(image,8,buffer));
5929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5933 + W r i t e B l o b S h o r t %
5937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5939 % WriteBlobShort() writes a short value as a 16-bit quantity in the
5940 % byte-order specified by the endian member of the image structure.
5942 % The format of the WriteBlobShort method is:
5944 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
5946 % A description of each parameter follows.
5948 % o image: the image.
5950 % o value: Specifies the value to write.
5953 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5958 assert(image != (Image *) NULL);
5959 assert(image->signature == MagickCoreSignature);
5960 if (image->endian == LSBEndian)
5962 buffer[0]=(unsigned char) value;
5963 buffer[1]=(unsigned char) (value >> 8);
5964 return(WriteBlobStream(image,2,buffer));
5966 buffer[0]=(unsigned char) (value >> 8);
5967 buffer[1]=(unsigned char) value;
5968 return(WriteBlobStream(image,2,buffer));
5972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5976 + W r i t e B l o b S i g n e d L o n g %
5980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5982 % WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
5983 % byte-order specified by the endian member of the image structure.
5985 % The format of the WriteBlobSignedLong method is:
5987 % ssize_t WriteBlobSignedLong(Image *image,const signed int value)
5989 % A description of each parameter follows.
5991 % o image: the image.
5993 % o value: Specifies the value to write.
5996 MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6010 assert(image != (Image *) NULL);
6011 assert(image->signature == MagickCoreSignature);
6012 quantum.signed_value=value;
6013 if (image->endian == LSBEndian)
6015 buffer[0]=(unsigned char) quantum.unsigned_value;
6016 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6017 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6018 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6019 return(WriteBlobStream(image,4,buffer));
6021 buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
6022 buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
6023 buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
6024 buffer[3]=(unsigned char) quantum.unsigned_value;
6025 return(WriteBlobStream(image,4,buffer));
6029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6033 + W r i t e B l o b L S B L o n g %
6037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6039 % WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
6040 % least-significant byte first order.
6042 % The format of the WriteBlobLSBLong method is:
6044 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6046 % A description of each parameter follows.
6048 % o image: the image.
6050 % o value: Specifies the value to write.
6053 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6058 assert(image != (Image *) NULL);
6059 assert(image->signature == MagickCoreSignature);
6060 buffer[0]=(unsigned char) value;
6061 buffer[1]=(unsigned char) (value >> 8);
6062 buffer[2]=(unsigned char) (value >> 16);
6063 buffer[3]=(unsigned char) (value >> 24);
6064 return(WriteBlobStream(image,4,buffer));
6068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6072 + W r i t e B l o b L S B S h o r t %
6076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6078 % WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
6079 % least-significant byte first order.
6081 % The format of the WriteBlobLSBShort method is:
6083 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6085 % A description of each parameter follows.
6087 % o image: the image.
6089 % o value: Specifies the value to write.
6092 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6097 assert(image != (Image *) NULL);
6098 assert(image->signature == MagickCoreSignature);
6099 buffer[0]=(unsigned char) value;
6100 buffer[1]=(unsigned char) (value >> 8);
6101 return(WriteBlobStream(image,2,buffer));
6105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6109 + W r i t e B l o b L S B S i g n e d L o n g %
6113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6115 % WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
6116 % least-significant byte first order.
6118 % The format of the WriteBlobLSBSignedLong method is:
6120 % ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6122 % A description of each parameter follows.
6124 % o image: the image.
6126 % o value: Specifies the value to write.
6129 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6143 assert(image != (Image *) NULL);
6144 assert(image->signature == MagickCoreSignature);
6145 quantum.signed_value=value;
6146 buffer[0]=(unsigned char) quantum.unsigned_value;
6147 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6148 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6149 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6150 return(WriteBlobStream(image,4,buffer));
6154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6158 + W r i t e B l o b L S B S i g n e d S h o r t %
6162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6164 % WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
6165 % in least-significant byte first order.
6167 % The format of the WriteBlobLSBSignedShort method is:
6169 % ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
6171 % A description of each parameter follows.
6173 % o image: the image.
6175 % o value: Specifies the value to write.
6178 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
6179 const signed short value)
6193 assert(image != (Image *) NULL);
6194 assert(image->signature == MagickCoreSignature);
6195 quantum.signed_value=value;
6196 buffer[0]=(unsigned char) quantum.unsigned_value;
6197 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6198 return(WriteBlobStream(image,2,buffer));
6202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6206 + W r i t e B l o b M S B L o n g %
6210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6212 % WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
6213 % most-significant byte first order.
6215 % The format of the WriteBlobMSBLong method is:
6217 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6219 % A description of each parameter follows.
6221 % o value: Specifies the value to write.
6223 % o image: the image.
6226 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6231 assert(image != (Image *) NULL);
6232 assert(image->signature == MagickCoreSignature);
6233 buffer[0]=(unsigned char) (value >> 24);
6234 buffer[1]=(unsigned char) (value >> 16);
6235 buffer[2]=(unsigned char) (value >> 8);
6236 buffer[3]=(unsigned char) value;
6237 return(WriteBlobStream(image,4,buffer));
6241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6245 + W r i t e B l o b M S B S i g n e d S h o r t %
6249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6251 % WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
6252 % in most-significant byte first order.
6254 % The format of the WriteBlobMSBSignedShort method is:
6256 % ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
6258 % A description of each parameter follows.
6260 % o image: the image.
6262 % o value: Specifies the value to write.
6265 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
6266 const signed short value)
6280 assert(image != (Image *) NULL);
6281 assert(image->signature == MagickCoreSignature);
6282 quantum.signed_value=value;
6283 buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
6284 buffer[1]=(unsigned char) quantum.unsigned_value;
6285 return(WriteBlobStream(image,2,buffer));
6289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6293 + W r i t e B l o b M S B S h o r t %
6297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6299 % WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6300 % most-significant byte first order.
6302 % The format of the WriteBlobMSBShort method is:
6304 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6306 % A description of each parameter follows.
6308 % o value: Specifies the value to write.
6310 % o file: Specifies the file to write the data to.
6313 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6318 assert(image != (Image *) NULL);
6319 assert(image->signature == MagickCoreSignature);
6320 buffer[0]=(unsigned char) (value >> 8);
6321 buffer[1]=(unsigned char) value;
6322 return(WriteBlobStream(image,2,buffer));
6326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6330 + W r i t e B l o b S t r i n g %
6334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6336 % WriteBlobString() write a string to a blob. It returns the number of
6337 % characters written.
6339 % The format of the WriteBlobString method is:
6341 % ssize_t WriteBlobString(Image *image,const char *string)
6343 % A description of each parameter follows.
6345 % o image: the image.
6347 % o string: Specifies the string to write.
6350 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6352 assert(image != (Image *) NULL);
6353 assert(image->signature == MagickCoreSignature);
6354 assert(string != (const char *) NULL);
6355 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));