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://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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);
1223 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1228 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
1229 blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
1235 blob_info->eof=MagickFalse;
1243 return((int) blob_info->eof);
1247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1251 + E r r o r B l o b %
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1257 % ErrorBlob() returns a non-zero value when an error has been detected reading
1258 % from a blob or file.
1260 % The format of the ErrorBlob method is:
1262 % int ErrorBlob(const Image *image)
1264 % A description of each parameter follows:
1266 % o image: the image.
1269 MagickExport int ErrorBlob(const Image *image)
1272 *magick_restrict blob_info;
1274 assert(image != (Image *) NULL);
1275 assert(image->signature == MagickCoreSignature);
1276 if (image->debug != MagickFalse)
1277 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1278 assert(image->blob != (BlobInfo *) NULL);
1279 assert(image->blob->type != UndefinedStream);
1280 blob_info=image->blob;
1281 switch (blob_info->type)
1283 case UndefinedStream:
1284 case StandardStream:
1289 blob_info->error=ferror(blob_info->file_info.file);
1294 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1295 (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1301 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1302 (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1316 return(blob_info->error);
1320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1324 % F i l e T o B l o b %
1328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1330 % FileToBlob() returns the contents of a file as a buffer terminated with
1331 % the '\0' character. The length of the buffer (not including the extra
1332 % terminating '\0' character) is returned via the 'length' parameter. Free
1333 % the buffer with RelinquishMagickMemory().
1335 % The format of the FileToBlob method is:
1337 % void *FileToBlob(const char *filename,const size_t extent,
1338 % size_t *length,ExceptionInfo *exception)
1340 % A description of each parameter follows:
1342 % o blob: FileToBlob() returns the contents of a file as a blob. If
1343 % an error occurs NULL is returned.
1345 % o filename: the filename.
1347 % o extent: The maximum length of the blob.
1349 % o length: On return, this reflects the actual length of the blob.
1351 % o exception: return any errors or warnings in this structure.
1354 MagickExport void *FileToBlob(const char *filename,const size_t extent,
1355 size_t *length,ExceptionInfo *exception)
1381 assert(filename != (const char *) NULL);
1382 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1383 assert(exception != (ExceptionInfo *) NULL);
1385 status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1386 if (status == MagickFalse)
1389 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1390 "NotAuthorized","`%s'",filename);
1394 if (LocaleCompare(filename,"-") != 0)
1396 status=GetPathAttributes(filename,&attributes);
1397 if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1399 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1402 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1406 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1409 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1411 if ((file == fileno(stdin)) || (offset < 0) ||
1412 (offset != (MagickOffsetType) ((ssize_t) offset)))
1421 Stream is not seekable.
1423 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1424 quantum=(size_t) MagickMaxBufferExtent;
1425 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1426 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1427 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1428 for (i=0; blob != (unsigned char *) NULL; i+=count)
1430 count=read(file,blob+i,quantum);
1437 if (~((size_t) i) < (quantum+1))
1439 blob=(unsigned char *) RelinquishMagickMemory(blob);
1442 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1444 if ((size_t) (i+count) >= extent)
1447 if (LocaleCompare(filename,"-") != 0)
1449 if (blob == (unsigned char *) NULL)
1451 (void) ThrowMagickException(exception,GetMagickModule(),
1452 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1457 blob=(unsigned char *) RelinquishMagickMemory(blob);
1458 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1461 *length=(size_t) MagickMin(i+count,extent);
1465 *length=(size_t) MagickMin(offset,(MagickOffsetType)
1466 MagickMin(extent,SSIZE_MAX));
1467 blob=(unsigned char *) NULL;
1468 if (~(*length) >= (MagickPathExtent-1))
1469 blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1471 if (blob == (unsigned char *) NULL)
1474 (void) ThrowMagickException(exception,GetMagickModule(),
1475 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1478 map=MapBlob(file,ReadMode,0,*length);
1479 if (map != (unsigned char *) NULL)
1481 (void) memcpy(blob,map,*length);
1482 (void) UnmapBlob(map,*length);
1486 (void) lseek(file,0,SEEK_SET);
1487 for (i=0; i < *length; i+=count)
1489 count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
1500 blob=(unsigned char *) RelinquishMagickMemory(blob);
1501 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1506 if (LocaleCompare(filename,"-") != 0)
1510 blob=(unsigned char *) RelinquishMagickMemory(blob);
1511 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1521 % F i l e T o I m a g e %
1525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 % FileToImage() write the contents of a file to an image.
1529 % The format of the FileToImage method is:
1531 % MagickBooleanType FileToImage(Image *,const char *filename)
1533 % A description of each parameter follows:
1535 % o image: the image.
1537 % o filename: the filename.
1541 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1545 *magick_restrict blob_info;
1550 register unsigned char
1553 assert(image->blob != (BlobInfo *) NULL);
1554 assert(image->blob->type != UndefinedStream);
1555 assert(data != NULL);
1556 blob_info=image->blob;
1557 if (blob_info->type != BlobStream)
1558 return(WriteBlob(image,length,(const unsigned char *) data));
1559 extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1560 if (extent >= blob_info->extent)
1562 extent=blob_info->extent+blob_info->quantum+length;
1563 blob_info->quantum<<=1;
1564 if (SetBlobExtent(image,extent) == MagickFalse)
1567 q=blob_info->data+blob_info->offset;
1568 (void) memcpy(q,data,length);
1569 blob_info->offset+=length;
1570 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1571 blob_info->length=(size_t) blob_info->offset;
1572 return((ssize_t) length);
1575 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1576 ExceptionInfo *exception)
1597 assert(image != (const Image *) NULL);
1598 assert(image->signature == MagickCoreSignature);
1599 assert(filename != (const char *) NULL);
1600 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1601 status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename);
1602 if (status == MagickFalse)
1605 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1606 "NotAuthorized","`%s'",filename);
1607 return(MagickFalse);
1610 if (LocaleCompare(filename,"-") != 0)
1611 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1614 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1615 return(MagickFalse);
1617 quantum=(size_t) MagickMaxBufferExtent;
1618 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1619 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1620 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1621 if (blob == (unsigned char *) NULL)
1624 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1626 return(MagickFalse);
1630 count=read(file,blob,quantum);
1637 length=(size_t) count;
1638 count=WriteBlobStream(image,length,blob);
1639 if (count != (ssize_t) length)
1641 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1647 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1648 blob=(unsigned char *) RelinquishMagickMemory(blob);
1653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1657 + G e t B l o b E r r o r %
1661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1663 % GetBlobError() returns MagickTrue if the blob associated with the specified
1664 % image encountered an error.
1666 % The format of the GetBlobError method is:
1668 % MagickBooleanType GetBlobError(const Image *image)
1670 % A description of each parameter follows:
1672 % o image: the image.
1675 MagickExport MagickBooleanType GetBlobError(const Image *image)
1677 assert(image != (const Image *) NULL);
1678 assert(image->signature == MagickCoreSignature);
1679 if (image->debug != MagickFalse)
1680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1681 return(image->blob->status);
1685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1689 + G e t B l o b F i l e H a n d l e %
1693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1695 % GetBlobFileHandle() returns the file handle associated with the image blob.
1697 % The format of the GetBlobFile method is:
1699 % FILE *GetBlobFileHandle(const Image *image)
1701 % A description of each parameter follows:
1703 % o image: the image.
1706 MagickExport FILE *GetBlobFileHandle(const Image *image)
1708 assert(image != (const Image *) NULL);
1709 assert(image->signature == MagickCoreSignature);
1710 return(image->blob->file_info.file);
1714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718 + G e t B l o b I n f o %
1722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724 % GetBlobInfo() initializes the BlobInfo structure.
1726 % The format of the GetBlobInfo method is:
1728 % void GetBlobInfo(BlobInfo *blob_info)
1730 % A description of each parameter follows:
1732 % o blob_info: Specifies a pointer to a BlobInfo structure.
1735 MagickExport void GetBlobInfo(BlobInfo *blob_info)
1737 assert(blob_info != (BlobInfo *) NULL);
1738 (void) memset(blob_info,0,sizeof(*blob_info));
1739 blob_info->type=UndefinedStream;
1740 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1741 blob_info->properties.st_mtime=time((time_t *) NULL);
1742 blob_info->properties.st_ctime=time((time_t *) NULL);
1743 blob_info->debug=IsEventLogging();
1744 blob_info->reference_count=1;
1745 blob_info->semaphore=AcquireSemaphoreInfo();
1746 blob_info->signature=MagickCoreSignature;
1750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1754 % G e t B l o b P r o p e r t i e s %
1758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1760 % GetBlobProperties() returns information about an image blob.
1762 % The format of the GetBlobProperties method is:
1764 % const struct stat *GetBlobProperties(const Image *image)
1766 % A description of each parameter follows:
1768 % o image: the image.
1771 MagickExport const struct stat *GetBlobProperties(const Image *image)
1773 assert(image != (Image *) NULL);
1774 assert(image->signature == MagickCoreSignature);
1775 if (image->debug != MagickFalse)
1776 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1777 return(&image->blob->properties);
1781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1785 + G e t B l o b S i z e %
1789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1791 % GetBlobSize() returns the current length of the image file or blob; zero is
1792 % returned if the size cannot be determined.
1794 % The format of the GetBlobSize method is:
1796 % MagickSizeType GetBlobSize(const Image *image)
1798 % A description of each parameter follows:
1800 % o image: the image.
1803 MagickExport MagickSizeType GetBlobSize(const Image *image)
1806 *magick_restrict blob_info;
1811 assert(image != (Image *) NULL);
1812 assert(image->signature == MagickCoreSignature);
1813 if (image->debug != MagickFalse)
1814 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1815 assert(image->blob != (BlobInfo *) NULL);
1816 blob_info=image->blob;
1818 switch (blob_info->type)
1820 case UndefinedStream:
1821 case StandardStream:
1823 extent=blob_info->size;
1828 if (fstat(fileno(blob_info->file_info.file),&blob_info->properties) == 0)
1829 extent=(MagickSizeType) blob_info->properties.st_size;
1834 extent=blob_info->size;
1843 status=GetPathAttributes(image->filename,&blob_info->properties);
1844 if (status != MagickFalse)
1845 extent=(MagickSizeType) blob_info->properties.st_size;
1852 extent=(MagickSizeType) blob_info->length;
1857 if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
1858 (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
1863 offset=blob_info->custom_stream->teller(
1864 blob_info->custom_stream->data);
1865 extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
1866 blob_info->custom_stream->data);
1867 (void) blob_info->custom_stream->seeker(offset,SEEK_SET,
1868 blob_info->custom_stream->data);
1877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1881 + G e t B l o b S t r e a m D a t a %
1885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1887 % GetBlobStreamData() returns the stream data for the image.
1889 % The format of the GetBlobStreamData method is:
1891 % void *GetBlobStreamData(const Image *image)
1893 % A description of each parameter follows:
1895 % o image: the image.
1898 MagickExport void *GetBlobStreamData(const Image *image)
1900 assert(image != (const Image *) NULL);
1901 assert(image->signature == MagickCoreSignature);
1902 return(image->blob->data);
1906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1910 + G e t B l o b S t r e a m H a n d l e r %
1914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1916 % GetBlobStreamHandler() returns the stream handler for the image.
1918 % The format of the GetBlobStreamHandler method is:
1920 % StreamHandler GetBlobStreamHandler(const Image *image)
1922 % A description of each parameter follows:
1924 % o image: the image.
1927 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1929 assert(image != (const Image *) NULL);
1930 assert(image->signature == MagickCoreSignature);
1931 if (image->debug != MagickFalse)
1932 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1933 return(image->blob->stream);
1937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1941 % I m a g e T o B l o b %
1945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1947 % ImageToBlob() implements direct to memory image formats. It returns the
1948 % image as a formatted blob and its length. The magick member of the Image
1949 % structure determines the format of the returned blob (GIF, JPEG, PNG,
1950 % etc.). This method is the equivalent of WriteImage(), but writes the
1951 % formatted "file" to a memory buffer rather than to an actual file.
1953 % The format of the ImageToBlob method is:
1955 % void *ImageToBlob(const ImageInfo *image_info,Image *image,
1956 % size_t *length,ExceptionInfo *exception)
1958 % A description of each parameter follows:
1960 % o image_info: the image info.
1962 % o image: the image.
1964 % o length: return the actual length of the blob.
1966 % o exception: return any errors or warnings in this structure.
1969 MagickExport void *ImageToBlob(const ImageInfo *image_info,
1970 Image *image,size_t *length,ExceptionInfo *exception)
1984 assert(image_info != (const ImageInfo *) NULL);
1985 assert(image_info->signature == MagickCoreSignature);
1986 if (image_info->debug != MagickFalse)
1987 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1988 image_info->filename);
1989 assert(image != (Image *) NULL);
1990 assert(image->signature == MagickCoreSignature);
1991 assert(exception != (ExceptionInfo *) NULL);
1993 blob=(unsigned char *) NULL;
1994 blob_info=CloneImageInfo(image_info);
1995 blob_info->adjoin=MagickFalse;
1996 (void) SetImageInfo(blob_info,1,exception);
1997 if (*blob_info->magick != '\0')
1998 (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1999 magick_info=GetMagickInfo(image->magick,exception);
2000 if (magick_info == (const MagickInfo *) NULL)
2002 (void) ThrowMagickException(exception,GetMagickModule(),
2003 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2005 blob_info=DestroyImageInfo(blob_info);
2008 (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
2009 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2012 Native blob support for this image format.
2014 blob_info->length=0;
2015 blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2016 sizeof(unsigned char));
2017 if (blob_info->blob == NULL)
2018 (void) ThrowMagickException(exception,GetMagickModule(),
2019 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2022 (void) CloseBlob(image);
2023 image->blob->exempt=MagickTrue;
2024 *image->filename='\0';
2025 status=WriteImage(blob_info,image,exception);
2026 *length=image->blob->length;
2027 blob=DetachBlob(image->blob);
2028 if (blob == (void *) NULL)
2029 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2030 else if (status == MagickFalse)
2031 blob=RelinquishMagickMemory(blob);
2033 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2039 unique[MagickPathExtent];
2045 Write file to disk in blob image format.
2047 file=AcquireUniqueFileResource(unique);
2050 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2051 image_info->filename);
2055 blob_info->file=fdopen(file,"wb");
2056 if (blob_info->file != (FILE *) NULL)
2058 (void) FormatLocaleString(image->filename,MagickPathExtent,
2059 "%s:%s",image->magick,unique);
2060 status=WriteImage(blob_info,image,exception);
2061 (void) CloseBlob(image);
2062 (void) fclose(blob_info->file);
2063 if (status != MagickFalse)
2064 blob=FileToBlob(unique,~0UL,length,exception);
2066 (void) RelinquishUniqueFileResource(unique);
2069 blob_info=DestroyImageInfo(blob_info);
2074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2078 + I m a g e T o C u s t o m S t r e a m %
2082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2084 % ImageToCustomStream() is the equivalent of WriteImage(), but writes the
2085 % formatted "file" to the custom stream rather than to an actual file.
2087 % The format of the ImageToCustomStream method is:
2089 % void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2090 % ExceptionInfo *exception)
2092 % A description of each parameter follows:
2094 % o image_info: the image info.
2096 % o image: the image.
2098 % o exception: return any errors or warnings in this structure.
2101 MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2102 ExceptionInfo *exception)
2114 assert(image_info != (const ImageInfo *) NULL);
2115 assert(image_info->signature == MagickCoreSignature);
2116 if (image_info->debug != MagickFalse)
2117 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2118 image_info->filename);
2119 assert(image != (Image *) NULL);
2120 assert(image->signature == MagickCoreSignature);
2121 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2122 assert(image_info->custom_stream->signature == MagickCoreSignature);
2123 assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2124 assert(exception != (ExceptionInfo *) NULL);
2125 clone_info=CloneImageInfo(image_info);
2126 clone_info->adjoin=MagickFalse;
2127 (void) SetImageInfo(clone_info,1,exception);
2128 if (*clone_info->magick != '\0')
2129 (void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
2130 magick_info=GetMagickInfo(image->magick,exception);
2131 if (magick_info == (const MagickInfo *) NULL)
2133 (void) ThrowMagickException(exception,GetMagickModule(),
2134 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2136 clone_info=DestroyImageInfo(clone_info);
2139 (void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
2140 blob_support=GetMagickBlobSupport(magick_info);
2141 if ((blob_support != MagickFalse) &&
2142 (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2144 if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2145 (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2146 blob_support=MagickFalse;
2148 if (blob_support != MagickFalse)
2151 Native blob support for this image format.
2153 (void) CloseBlob(image);
2154 *image->filename='\0';
2155 (void) WriteImage(clone_info,image,exception);
2156 (void) CloseBlob(image);
2161 unique[MagickPathExtent];
2170 Write file to disk in blob image format.
2172 clone_info->custom_stream=(CustomStreamInfo *) NULL;
2173 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2175 if (blob == (unsigned char *) NULL)
2177 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2178 image_info->filename);
2179 clone_info=DestroyImageInfo(clone_info);
2182 file=AcquireUniqueFileResource(unique);
2185 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2186 image_info->filename);
2187 blob=(unsigned char *) RelinquishMagickMemory(blob);
2188 clone_info=DestroyImageInfo(clone_info);
2191 clone_info->file=fdopen(file,"wb+");
2192 if (clone_info->file != (FILE *) NULL)
2197 (void) FormatLocaleString(image->filename,MagickPathExtent,
2198 "%s:%s",image->magick,unique);
2199 status=WriteImage(clone_info,image,exception);
2200 (void) CloseBlob(image);
2201 if (status != MagickFalse)
2203 (void) fseek(clone_info->file,0,SEEK_SET);
2204 count=(ssize_t) MagickMaxBufferExtent;
2205 while (count == (ssize_t) MagickMaxBufferExtent)
2207 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2209 (void) image_info->custom_stream->writer(blob,(size_t) count,
2210 image_info->custom_stream->data);
2213 (void) fclose(clone_info->file);
2215 blob=(unsigned char *) RelinquishMagickMemory(blob);
2216 (void) RelinquishUniqueFileResource(unique);
2218 clone_info=DestroyImageInfo(clone_info);
2222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2226 % I m a g e T o F i l e %
2230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2232 % ImageToFile() writes an image to a file. It returns MagickFalse if an error
2233 % occurs otherwise MagickTrue.
2235 % The format of the ImageToFile method is:
2237 % MagickBooleanType ImageToFile(Image *image,char *filename,
2238 % ExceptionInfo *exception)
2240 % A description of each parameter follows:
2242 % o image: the image.
2244 % o filename: Write the image to this file.
2246 % o exception: return any errors or warnings in this structure.
2249 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
2250 ExceptionInfo *exception)
2255 register const unsigned char
2274 assert(image != (Image *) NULL);
2275 assert(image->signature == MagickCoreSignature);
2276 assert(image->blob != (BlobInfo *) NULL);
2277 assert(image->blob->type != UndefinedStream);
2278 if (image->debug != MagickFalse)
2279 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
2280 assert(filename != (const char *) NULL);
2281 if (*filename == '\0')
2282 file=AcquireUniqueFileResource(filename);
2284 if (LocaleCompare(filename,"-") == 0)
2285 file=fileno(stdout);
2287 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
2290 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2291 return(MagickFalse);
2293 quantum=(size_t) MagickMaxBufferExtent;
2294 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2295 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2296 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2297 if (buffer == (unsigned char *) NULL)
2300 (void) ThrowMagickException(exception,GetMagickModule(),
2301 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
2302 return(MagickFalse);
2305 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2306 for (i=0; count > 0; )
2308 length=(size_t) count;
2309 for (i=0; i < length; i+=count)
2311 count=write(file,p+i,(size_t) (length-i));
2321 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2323 if (LocaleCompare(filename,"-") != 0)
2325 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2326 if ((file == -1) || (i < length))
2330 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2331 return(MagickFalse);
2337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2341 % I m a g e s T o B l o b %
2345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2347 % ImagesToBlob() implements direct to memory image formats. It returns the
2348 % image sequence as a blob and its length. The magick member of the ImageInfo
2349 % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
2351 % Note, some image formats do not permit multiple images to the same image
2352 % stream (e.g. JPEG). in this instance, just the first image of the
2353 % sequence is returned as a blob.
2355 % The format of the ImagesToBlob method is:
2357 % void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2358 % size_t *length,ExceptionInfo *exception)
2360 % A description of each parameter follows:
2362 % o image_info: the image info.
2364 % o images: the image list.
2366 % o length: return the actual length of the blob.
2368 % o exception: return any errors or warnings in this structure.
2371 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2372 size_t *length,ExceptionInfo *exception)
2386 assert(image_info != (const ImageInfo *) NULL);
2387 assert(image_info->signature == MagickCoreSignature);
2388 if (image_info->debug != MagickFalse)
2389 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2390 image_info->filename);
2391 assert(images != (Image *) NULL);
2392 assert(images->signature == MagickCoreSignature);
2393 assert(exception != (ExceptionInfo *) NULL);
2395 blob=(unsigned char *) NULL;
2396 clone_info=CloneImageInfo(image_info);
2397 (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2399 if (*clone_info->magick != '\0')
2400 (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2401 magick_info=GetMagickInfo(images->magick,exception);
2402 if (magick_info == (const MagickInfo *) NULL)
2404 (void) ThrowMagickException(exception,GetMagickModule(),
2405 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2407 clone_info=DestroyImageInfo(clone_info);
2410 if (GetMagickAdjoin(magick_info) == MagickFalse)
2412 clone_info=DestroyImageInfo(clone_info);
2413 return(ImageToBlob(image_info,images,length,exception));
2415 (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2416 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2419 Native blob support for this images format.
2421 clone_info->length=0;
2422 clone_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2423 sizeof(unsigned char));
2424 if (clone_info->blob == (void *) NULL)
2425 (void) ThrowMagickException(exception,GetMagickModule(),
2426 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2429 (void) CloseBlob(images);
2430 images->blob->exempt=MagickTrue;
2431 *images->filename='\0';
2432 status=WriteImages(clone_info,images,images->filename,exception);
2433 *length=images->blob->length;
2434 blob=DetachBlob(images->blob);
2435 if (blob == (void *) NULL)
2436 clone_info->blob=RelinquishMagickMemory(clone_info->blob);
2437 else if (status == MagickFalse)
2438 blob=RelinquishMagickMemory(blob);
2440 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2446 filename[MagickPathExtent],
2447 unique[MagickPathExtent];
2453 Write file to disk in blob images format.
2455 file=AcquireUniqueFileResource(unique);
2458 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2459 image_info->filename);
2463 clone_info->file=fdopen(file,"wb");
2464 if (clone_info->file != (FILE *) NULL)
2466 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2467 images->magick,unique);
2468 status=WriteImages(clone_info,images,filename,exception);
2469 (void) CloseBlob(images);
2470 (void) fclose(clone_info->file);
2471 if (status != MagickFalse)
2472 blob=FileToBlob(unique,~0UL,length,exception);
2474 (void) RelinquishUniqueFileResource(unique);
2477 clone_info=DestroyImageInfo(clone_info);
2482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2486 + I m a g e s T o C u s t o m B l o b %
2490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2492 % ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2493 % formatted "file" to the custom stream rather than to an actual file.
2495 % The format of the ImageToCustomStream method is:
2497 % void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2498 % ExceptionInfo *exception)
2500 % A description of each parameter follows:
2502 % o image_info: the image info.
2504 % o images: the image list.
2506 % o exception: return any errors or warnings in this structure.
2509 MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2510 Image *images,ExceptionInfo *exception)
2522 assert(image_info != (const ImageInfo *) NULL);
2523 assert(image_info->signature == MagickCoreSignature);
2524 if (image_info->debug != MagickFalse)
2525 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2526 image_info->filename);
2527 assert(images != (Image *) NULL);
2528 assert(images->signature == MagickCoreSignature);
2529 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2530 assert(image_info->custom_stream->signature == MagickCoreSignature);
2531 assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
2532 assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2533 assert(exception != (ExceptionInfo *) NULL);
2534 clone_info=CloneImageInfo(image_info);
2535 (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2537 if (*clone_info->magick != '\0')
2538 (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2539 magick_info=GetMagickInfo(images->magick,exception);
2540 if (magick_info == (const MagickInfo *) NULL)
2542 (void) ThrowMagickException(exception,GetMagickModule(),
2543 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2545 clone_info=DestroyImageInfo(clone_info);
2548 (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2549 blob_support=GetMagickBlobSupport(magick_info);
2550 if ((blob_support != MagickFalse) &&
2551 (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2553 if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2554 (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2555 blob_support=MagickFalse;
2557 if (blob_support != MagickFalse)
2560 Native blob support for this image format.
2562 (void) CloseBlob(images);
2563 *images->filename='\0';
2564 (void) WriteImages(clone_info,images,images->filename,exception);
2565 (void) CloseBlob(images);
2570 filename[MagickPathExtent],
2571 unique[MagickPathExtent];
2580 Write file to disk in blob image format.
2582 clone_info->custom_stream=(CustomStreamInfo *) NULL;
2583 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2585 if (blob == (unsigned char *) NULL)
2587 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2588 image_info->filename);
2589 clone_info=DestroyImageInfo(clone_info);
2592 file=AcquireUniqueFileResource(unique);
2595 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2596 image_info->filename);
2597 blob=(unsigned char *) RelinquishMagickMemory(blob);
2598 clone_info=DestroyImageInfo(clone_info);
2601 clone_info->file=fdopen(file,"wb+");
2602 if (clone_info->file != (FILE *) NULL)
2607 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2608 images->magick,unique);
2609 status=WriteImages(clone_info,images,filename,exception);
2610 (void) CloseBlob(images);
2611 if (status != MagickFalse)
2613 (void) fseek(clone_info->file,0,SEEK_SET);
2614 count=(ssize_t) MagickMaxBufferExtent;
2615 while (count == (ssize_t) MagickMaxBufferExtent)
2617 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2619 (void) image_info->custom_stream->writer(blob,(size_t) count,
2620 image_info->custom_stream->data);
2623 (void) fclose(clone_info->file);
2625 blob=(unsigned char *) RelinquishMagickMemory(blob);
2626 (void) RelinquishUniqueFileResource(unique);
2628 clone_info=DestroyImageInfo(clone_info);
2632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2636 % I n j e c t I m a g e B l o b %
2640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642 % InjectImageBlob() injects the image with a copy of itself in the specified
2643 % format (e.g. inject JPEG into a PDF image).
2645 % The format of the InjectImageBlob method is:
2647 % MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2648 % Image *image,Image *inject_image,const char *format,
2649 % ExceptionInfo *exception)
2651 % A description of each parameter follows:
2653 % o image_info: the image info..
2655 % o image: the image.
2657 % o inject_image: inject into the image stream.
2659 % o format: the image format.
2661 % o exception: return any errors or warnings in this structure.
2664 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2665 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2668 filename[MagickPathExtent];
2701 Write inject image to a temporary file.
2703 assert(image_info != (ImageInfo *) NULL);
2704 assert(image_info->signature == MagickCoreSignature);
2705 assert(image != (Image *) NULL);
2706 assert(image->signature == MagickCoreSignature);
2707 if (image->debug != MagickFalse)
2708 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2709 assert(inject_image != (Image *) NULL);
2710 assert(inject_image->signature == MagickCoreSignature);
2711 assert(exception != (ExceptionInfo *) NULL);
2712 unique_file=(FILE *) NULL;
2713 file=AcquireUniqueFileResource(filename);
2715 unique_file=fdopen(file,"wb");
2716 if ((file == -1) || (unique_file == (FILE *) NULL))
2718 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2719 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2721 return(MagickFalse);
2723 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2724 if (byte_image == (Image *) NULL)
2726 (void) fclose(unique_file);
2727 (void) RelinquishUniqueFileResource(filename);
2728 return(MagickFalse);
2730 (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2732 DestroyBlob(byte_image);
2733 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2734 write_info=CloneImageInfo(image_info);
2735 SetImageInfoFile(write_info,unique_file);
2736 status=WriteImage(write_info,byte_image,exception);
2737 write_info=DestroyImageInfo(write_info);
2738 byte_image=DestroyImage(byte_image);
2739 (void) fclose(unique_file);
2740 if (status == MagickFalse)
2742 (void) RelinquishUniqueFileResource(filename);
2743 return(MagickFalse);
2746 Inject into image stream.
2748 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2751 (void) RelinquishUniqueFileResource(filename);
2752 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2753 image_info->filename);
2754 return(MagickFalse);
2756 quantum=(size_t) MagickMaxBufferExtent;
2757 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2758 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2759 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2760 if (buffer == (unsigned char *) NULL)
2762 (void) RelinquishUniqueFileResource(filename);
2764 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2767 for (i=0; ; i+=count)
2769 count=read(file,buffer,quantum);
2776 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2781 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2782 (void) RelinquishUniqueFileResource(filename);
2783 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2792 % I s B l o b E x e m p t %
2796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2798 % IsBlobExempt() returns true if the blob is exempt.
2800 % The format of the IsBlobExempt method is:
2802 % MagickBooleanType IsBlobExempt(const Image *image)
2804 % A description of each parameter follows:
2806 % o image: the image.
2809 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2811 assert(image != (const Image *) NULL);
2812 assert(image->signature == MagickCoreSignature);
2813 if (image->debug != MagickFalse)
2814 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2815 return(image->blob->exempt);
2819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2823 % I s B l o b S e e k a b l e %
2827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2829 % IsBlobSeekable() returns true if the blob is seekable.
2831 % The format of the IsBlobSeekable method is:
2833 % MagickBooleanType IsBlobSeekable(const Image *image)
2835 % A description of each parameter follows:
2837 % o image: the image.
2840 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2843 *magick_restrict blob_info;
2845 assert(image != (const Image *) NULL);
2846 assert(image->signature == MagickCoreSignature);
2847 if (image->debug != MagickFalse)
2848 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2849 blob_info=image->blob;
2850 switch (blob_info->type)
2859 if (blob_info->file_info.file == (FILE *) NULL)
2860 return(MagickFalse);
2861 status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2862 return(status == -1 ? MagickFalse : MagickTrue);
2866 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2870 if (blob_info->file_info.gzfile == (gzFile) NULL)
2871 return(MagickFalse);
2872 status=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2873 return(status == -1 ? MagickFalse : MagickTrue);
2878 case UndefinedStream:
2882 case StandardStream:
2886 if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
2887 (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
2894 return(MagickFalse);
2898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902 % I s B l o b T e m p o r a r y %
2906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2908 % IsBlobTemporary() returns true if the blob is temporary.
2910 % The format of the IsBlobTemporary method is:
2912 % MagickBooleanType IsBlobTemporary(const Image *image)
2914 % A description of each parameter follows:
2916 % o image: the image.
2919 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2921 assert(image != (const Image *) NULL);
2922 assert(image->signature == MagickCoreSignature);
2923 if (image->debug != MagickFalse)
2924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2925 return(image->blob->temporary);
2929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2939 % MapBlob() creates a mapping from a file to a binary large object.
2941 % The format of the MapBlob method is:
2943 % void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2944 % const size_t length)
2946 % A description of each parameter follows:
2948 % o file: map this file descriptor.
2950 % o mode: ReadMode, WriteMode, or IOMode.
2952 % o offset: starting at this offset within the file.
2954 % o length: the length of the mapping is returned in this pointer.
2957 MagickExport void *MapBlob(int file,const MapMode mode,
2958 const MagickOffsetType offset,const size_t length)
2960 #if defined(MAGICKCORE_HAVE_MMAP)
2973 #if defined(MAP_ANONYMOUS)
2974 flags|=MAP_ANONYMOUS;
2983 protection=PROT_READ;
2989 protection=PROT_WRITE;
2995 protection=PROT_READ | PROT_WRITE;
3000 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
3001 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
3003 map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
3005 if (map == MAP_FAILED)
3006 map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
3008 if (map == MAP_FAILED)
3021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3025 + M S B O r d e r L o n g %
3029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3031 % MSBOrderLong() converts a least-significant byte first buffer of integers to
3032 % most-significant byte first.
3034 % The format of the MSBOrderLong method is:
3036 % void MSBOrderLong(unsigned char *buffer,const size_t length)
3038 % A description of each parameter follows.
3040 % o buffer: Specifies a pointer to a buffer of integers.
3042 % o length: Specifies the length of the buffer.
3045 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
3050 register unsigned char
3054 assert(buffer != (unsigned char *) NULL);
3061 *buffer++=(unsigned char) c;
3065 *buffer++=(unsigned char) c;
3071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3075 + M S B O r d e r S h o r t %
3079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3081 % MSBOrderShort() converts a least-significant byte first buffer of integers
3082 % to most-significant byte first.
3084 % The format of the MSBOrderShort method is:
3086 % void MSBOrderShort(unsigned char *p,const size_t length)
3088 % A description of each parameter follows.
3090 % o p: Specifies a pointer to a buffer of integers.
3092 % o length: Specifies the length of the buffer.
3095 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
3100 register unsigned char
3103 assert(p != (unsigned char *) NULL);
3110 *p++=(unsigned char) c;
3115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3125 % OpenBlob() opens a file associated with the image. A file name of '-' sets
3126 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
3127 % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
3128 % compressed for type 'w'. If the filename prefix is '|', it is piped to or
3129 % from a system command.
3131 % The format of the OpenBlob method is:
3133 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
3134 % const BlobMode mode,ExceptionInfo *exception)
3136 % A description of each parameter follows:
3138 % o image_info: the image info.
3140 % o image: the image.
3142 % o mode: the mode for opening the file.
3146 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
3159 option=GetImageOption(image_info,"stream:buffer-size");
3160 if (option != (const char *) NULL)
3161 size=StringToUnsignedLong(option);
3162 status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
3163 _IONBF : _IOFBF,size);
3164 return(status == 0 ? MagickTrue : MagickFalse);
3167 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
3168 Image *image,const BlobMode mode,ExceptionInfo *exception)
3171 *magick_restrict blob_info;
3174 extension[MagickPathExtent],
3175 filename[MagickPathExtent];
3186 assert(image_info != (ImageInfo *) NULL);
3187 assert(image_info->signature == MagickCoreSignature);
3188 if (image_info->debug != MagickFalse)
3189 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3190 image_info->filename);
3191 assert(image != (Image *) NULL);
3192 assert(image->signature == MagickCoreSignature);
3193 blob_info=image->blob;
3194 if (image_info->blob != (void *) NULL)
3196 if (image_info->stream != (StreamHandler) NULL)
3197 blob_info->stream=(StreamHandler) image_info->stream;
3198 AttachBlob(blob_info,image_info->blob,image_info->length);
3201 if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3202 (*image->filename == '\0'))
3204 blob_info->type=CustomStream;
3205 blob_info->custom_stream=image_info->custom_stream;
3208 (void) DetachBlob(blob_info);
3209 blob_info->mode=mode;
3212 default: type="r"; break;
3213 case ReadBlobMode: type="r"; break;
3214 case ReadBinaryBlobMode: type="rb"; break;
3215 case WriteBlobMode: type="w"; break;
3216 case WriteBinaryBlobMode: type="w+b"; break;
3217 case AppendBlobMode: type="a"; break;
3218 case AppendBinaryBlobMode: type="a+b"; break;
3221 blob_info->synchronize=image_info->synchronize;
3222 if (image_info->stream != (StreamHandler) NULL)
3224 blob_info->stream=image_info->stream;
3227 blob_info->type=FifoStream;
3235 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3236 rights=ReadPolicyRights;
3238 rights=WritePolicyRights;
3239 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
3242 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
3243 "NotAuthorized","`%s'",filename);
3244 return(MagickFalse);
3246 if ((LocaleCompare(filename,"-") == 0) ||
3247 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3249 blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3250 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3251 if (strchr(type,'b') != (char *) NULL)
3252 setmode(fileno(blob_info->file_info.file),_O_BINARY);
3254 blob_info->type=StandardStream;
3255 blob_info->exempt=MagickTrue;
3256 return(SetStreamBuffering(image_info,image));
3258 if ((LocaleNCompare(filename,"fd:",3) == 0) &&
3259 (IsGeometry(filename+3) != MagickFalse))
3262 fileMode[MagickPathExtent];
3266 blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
3267 if (blob_info->file_info.file == (FILE *) NULL)
3269 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3270 return(MagickFalse);
3272 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3273 if (strchr(type,'b') != (char *) NULL)
3274 setmode(fileno(blob_info->file_info.file),_O_BINARY);
3276 blob_info->type=FileStream;
3277 blob_info->exempt=MagickTrue;
3278 return(SetStreamBuffering(image_info,image));
3280 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3281 if (*filename == '|')
3284 fileMode[MagickPathExtent],
3288 Pipe image to or from a system command.
3290 #if defined(SIGPIPE)
3292 (void) signal(SIGPIPE,SIG_IGN);
3296 sanitize_command=SanitizeString(filename+1);
3297 blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3298 sanitize_command=DestroyString(sanitize_command);
3299 if (blob_info->file_info.file == (FILE *) NULL)
3301 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3302 return(MagickFalse);
3304 blob_info->type=PipeStream;
3305 blob_info->exempt=MagickTrue;
3306 return(SetStreamBuffering(image_info,image));
3309 status=GetPathAttributes(filename,&blob_info->properties);
3310 #if defined(S_ISFIFO)
3311 if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3313 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3314 if (blob_info->file_info.file == (FILE *) NULL)
3316 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3317 return(MagickFalse);
3319 blob_info->type=FileStream;
3320 blob_info->exempt=MagickTrue;
3321 return(SetStreamBuffering(image_info,image));
3324 GetPathComponent(image->filename,ExtensionPath,extension);
3327 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3328 if ((image_info->adjoin == MagickFalse) ||
3329 (strchr(filename,'%') != (char *) NULL))
3332 Form filename for multi-part images.
3334 (void) InterpretImageFilename(image_info,image,image->filename,(int)
3335 image->scene,filename,exception);
3336 if ((LocaleCompare(filename,image->filename) == 0) &&
3337 ((GetPreviousImageInList(image) != (Image *) NULL) ||
3338 (GetNextImageInList(image) != (Image *) NULL)))
3341 path[MagickPathExtent];
3343 GetPathComponent(image->filename,RootPath,path);
3344 if (*extension == '\0')
3345 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
3346 path,(double) image->scene);
3348 (void) FormatLocaleString(filename,MagickPathExtent,
3349 "%s-%.20g.%s",path,(double) image->scene,extension);
3351 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3352 #if defined(macintosh)
3353 SetApplicationType(filename,image_info->magick,'8BIM');
3357 if (image_info->file != (FILE *) NULL)
3359 blob_info->file_info.file=image_info->file;
3360 blob_info->type=FileStream;
3361 blob_info->exempt=MagickTrue;
3366 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3367 if (blob_info->file_info.file != (FILE *) NULL)
3375 blob_info->type=FileStream;
3376 (void) SetStreamBuffering(image_info,image);
3377 (void) memset(magick,0,sizeof(magick));
3378 count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3379 (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3380 #if defined(MAGICKCORE_POSIX_SUPPORT)
3381 (void) fflush(blob_info->file_info.file);
3383 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
3384 " read %.20g magic header bytes",(double) count);
3385 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3386 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3387 ((int) magick[2] == 0x08))
3389 if (blob_info->file_info.file != (FILE *) NULL)
3390 (void) fclose(blob_info->file_info.file);
3391 blob_info->file_info.file=(FILE *) NULL;
3392 blob_info->file_info.gzfile=gzopen(filename,"rb");
3393 if (blob_info->file_info.gzfile != (gzFile) NULL)
3394 blob_info->type=ZipStream;
3397 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3398 if (strncmp((char *) magick,"BZh",3) == 0)
3400 if (blob_info->file_info.file != (FILE *) NULL)
3401 (void) fclose(blob_info->file_info.file);
3402 blob_info->file_info.file=(FILE *) NULL;
3403 blob_info->file_info.bzfile=BZ2_bzopen(filename,"r");
3404 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3405 blob_info->type=BZipStream;
3408 if (blob_info->type == FileStream)
3419 sans_exception=AcquireExceptionInfo();
3420 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3421 sans_exception=DestroyExceptionInfo(sans_exception);
3422 length=(size_t) blob_info->properties.st_size;
3423 if ((magick_info != (const MagickInfo *) NULL) &&
3424 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3425 (length > MagickMaxBufferExtent) &&
3426 (AcquireMagickResource(MapResource,length) != MagickFalse))
3431 blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3433 if (blob == (void *) NULL)
3434 RelinquishMagickResource(MapResource,length);
3438 Format supports blobs-- use memory-mapped I/O.
3440 if (image_info->file != (FILE *) NULL)
3441 blob_info->exempt=MagickFalse;
3444 (void) fclose(blob_info->file_info.file);
3445 blob_info->file_info.file=(FILE *) NULL;
3447 AttachBlob(blob_info,blob,length);
3448 blob_info->mapped=MagickTrue;
3455 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3456 if ((LocaleCompare(extension,"Z") == 0) ||
3457 (LocaleCompare(extension,"gz") == 0) ||
3458 (LocaleCompare(extension,"wmz") == 0) ||
3459 (LocaleCompare(extension,"svgz") == 0))
3461 blob_info->file_info.gzfile=gzopen(filename,"wb");
3462 if (blob_info->file_info.gzfile != (gzFile) NULL)
3463 blob_info->type=ZipStream;
3467 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3468 if (LocaleCompare(extension,"bz2") == 0)
3470 blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
3471 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3472 blob_info->type=BZipStream;
3477 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3478 if (blob_info->file_info.file != (FILE *) NULL)
3480 blob_info->type=FileStream;
3481 (void) SetStreamBuffering(image_info,image);
3484 blob_info->status=MagickFalse;
3485 if (blob_info->type != UndefinedStream)
3486 blob_info->size=GetBlobSize(image);
3489 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3490 return(MagickFalse);
3496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3506 % PingBlob() returns all the attributes of an image or image sequence except
3507 % for the pixels. It is much faster and consumes far less memory than
3508 % BlobToImage(). On failure, a NULL image is returned and exception
3509 % describes the reason for the failure.
3511 % The format of the PingBlob method is:
3513 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
3514 % const size_t length,ExceptionInfo *exception)
3516 % A description of each parameter follows:
3518 % o image_info: the image info.
3520 % o blob: the address of a character stream in one of the image formats
3521 % understood by ImageMagick.
3523 % o length: This size_t integer reflects the length in bytes of the blob.
3525 % o exception: return any errors or warnings in this structure.
3529 #if defined(__cplusplus) || defined(c_plusplus)
3533 static size_t PingStream(const Image *magick_unused(image),
3534 const void *magick_unused(pixels),const size_t columns)
3536 magick_unreferenced(image);
3537 magick_unreferenced(pixels);
3541 #if defined(__cplusplus) || defined(c_plusplus)
3545 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3546 const size_t length,ExceptionInfo *exception)
3561 assert(image_info != (ImageInfo *) NULL);
3562 assert(image_info->signature == MagickCoreSignature);
3563 if (image_info->debug != MagickFalse)
3564 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3565 image_info->filename);
3566 assert(exception != (ExceptionInfo *) NULL);
3567 if ((blob == (const void *) NULL) || (length == 0))
3569 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3570 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3571 return((Image *) NULL);
3573 ping_info=CloneImageInfo(image_info);
3574 ping_info->blob=(void *) blob;
3575 ping_info->length=length;
3576 ping_info->ping=MagickTrue;
3577 if (*ping_info->magick == '\0')
3578 (void) SetImageInfo(ping_info,0,exception);
3579 magick_info=GetMagickInfo(ping_info->magick,exception);
3580 if (magick_info == (const MagickInfo *) NULL)
3582 (void) ThrowMagickException(exception,GetMagickModule(),
3583 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3585 ping_info=DestroyImageInfo(ping_info);
3586 return((Image *) NULL);
3588 if (GetMagickBlobSupport(magick_info) != MagickFalse)
3591 filename[MagickPathExtent];
3594 Native blob support for this image format.
3596 (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3597 (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3598 ping_info->magick,filename);
3599 image=ReadStream(ping_info,&PingStream,exception);
3600 if (image != (Image *) NULL)
3601 (void) DetachBlob(image->blob);
3602 ping_info=DestroyImageInfo(ping_info);
3606 Write blob to a temporary file on disk.
3608 ping_info->blob=(void *) NULL;
3609 ping_info->length=0;
3610 *ping_info->filename='\0';
3611 status=BlobToFile(ping_info->filename,blob,length,exception);
3612 if (status == MagickFalse)
3614 (void) RelinquishUniqueFileResource(ping_info->filename);
3615 ping_info=DestroyImageInfo(ping_info);
3616 return((Image *) NULL);
3618 clone_info=CloneImageInfo(ping_info);
3619 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3620 ping_info->magick,ping_info->filename);
3621 image=ReadStream(clone_info,&PingStream,exception);
3622 if (image != (Image *) NULL)
3628 Restore original filenames and image format.
3630 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3632 (void) CopyMagickString(images->filename,image_info->filename,
3634 (void) CopyMagickString(images->magick_filename,image_info->filename,
3636 (void) CopyMagickString(images->magick,magick_info->name,
3638 images=GetNextImageInList(images);
3641 clone_info=DestroyImageInfo(clone_info);
3642 (void) RelinquishUniqueFileResource(ping_info->filename);
3643 ping_info=DestroyImageInfo(ping_info);
3648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3658 % ReadBlob() reads data from the blob or image file and returns it. It
3659 % returns the number of bytes read. If length is zero, ReadBlob() returns
3660 % zero and has no other results. If length is greater than SSIZE_MAX, the
3661 % result is unspecified.
3663 % The format of the ReadBlob method is:
3665 % ssize_t ReadBlob(Image *image,const size_t length,void *data)
3667 % A description of each parameter follows:
3669 % o image: the image.
3671 % o length: Specifies an integer representing the number of bytes to read
3674 % o data: Specifies an area to place the information requested from the
3678 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3681 *magick_restrict blob_info;
3686 register unsigned char
3692 assert(image != (Image *) NULL);
3693 assert(image->signature == MagickCoreSignature);
3694 assert(image->blob != (BlobInfo *) NULL);
3695 assert(image->blob->type != UndefinedStream);
3698 assert(data != (void *) NULL);
3699 blob_info=image->blob;
3701 q=(unsigned char *) data;
3702 switch (blob_info->type)
3704 case UndefinedStream:
3706 case StandardStream:
3714 count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3719 c=getc(blob_info->file_info.file);
3722 *q++=(unsigned char) c;
3727 c=getc(blob_info->file_info.file);
3730 *q++=(unsigned char) c;
3735 c=getc(blob_info->file_info.file);
3738 *q++=(unsigned char) c;
3743 c=getc(blob_info->file_info.file);
3746 *q++=(unsigned char) c;
3756 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3764 for (i=0; i < (ssize_t) length; i+=count)
3766 count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3767 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3780 c=gzgetc(blob_info->file_info.gzfile);
3783 *q++=(unsigned char) c;
3788 c=gzgetc(blob_info->file_info.gzfile);
3791 *q++=(unsigned char) c;
3796 c=gzgetc(blob_info->file_info.gzfile);
3799 *q++=(unsigned char) c;
3804 c=gzgetc(blob_info->file_info.gzfile);
3807 *q++=(unsigned char) c;
3818 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3822 for (i=0; i < (ssize_t) length; i+=count)
3824 count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
3825 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3841 register const unsigned char
3844 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3846 blob_info->eof=MagickTrue;
3849 p=blob_info->data+blob_info->offset;
3850 count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3851 blob_info->length-blob_info->offset);
3852 blob_info->offset+=count;
3853 if (count != (ssize_t) length)
3854 blob_info->eof=MagickTrue;
3855 (void) memcpy(q,p,(size_t) count);
3860 if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
3861 count=blob_info->custom_stream->reader(q,length,
3862 blob_info->custom_stream->data);
3870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3874 + R e a d B l o b B y t e %
3878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3880 % ReadBlobByte() reads a single byte from the image file and returns it.
3882 % The format of the ReadBlobByte method is:
3884 % int ReadBlobByte(Image *image)
3886 % A description of each parameter follows.
3888 % o image: the image.
3891 MagickExport int ReadBlobByte(Image *image)
3894 *magick_restrict blob_info;
3896 register const unsigned char
3902 assert(image != (Image *) NULL);
3903 assert(image->signature == MagickCoreSignature);
3904 assert(image->blob != (BlobInfo *) NULL);
3905 assert(image->blob->type != UndefinedStream);
3906 blob_info=image->blob;
3907 switch (blob_info->type)
3909 case StandardStream:
3916 p=(const unsigned char *) buffer;
3917 c=getc(blob_info->file_info.file);
3920 *buffer=(unsigned char) c;
3928 p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3942 + R e a d B l o b D o u b l e %
3946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3948 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3949 % specified by the endian member of the image structure.
3951 % The format of the ReadBlobDouble method is:
3953 % double ReadBlobDouble(Image *image)
3955 % A description of each parameter follows.
3957 % o image: the image.
3960 MagickExport double ReadBlobDouble(Image *image)
3971 quantum.double_value=0.0;
3972 quantum.unsigned_value=ReadBlobLongLong(image);
3973 return(quantum.double_value);
3977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3981 + R e a d B l o b F l o a t %
3985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3987 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3988 % specified by the endian member of the image structure.
3990 % The format of the ReadBlobFloat method is:
3992 % float ReadBlobFloat(Image *image)
3994 % A description of each parameter follows.
3996 % o image: the image.
3999 MagickExport float ReadBlobFloat(Image *image)
4010 quantum.float_value=0.0;
4011 quantum.unsigned_value=ReadBlobLong(image);
4012 return(quantum.float_value);
4016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4020 + R e a d B l o b L o n g %
4024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4026 % ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
4027 % byte-order specified by the endian member of the image structure.
4029 % The format of the ReadBlobLong method is:
4031 % unsigned int ReadBlobLong(Image *image)
4033 % A description of each parameter follows.
4035 % o image: the image.
4038 MagickExport unsigned int ReadBlobLong(Image *image)
4040 register const unsigned char
4052 assert(image != (Image *) NULL);
4053 assert(image->signature == MagickCoreSignature);
4055 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4058 if (image->endian == LSBEndian)
4060 value=(unsigned int) (*p++);
4061 value|=(unsigned int) (*p++) << 8;
4062 value|=(unsigned int) (*p++) << 16;
4063 value|=(unsigned int) (*p++) << 24;
4066 value=(unsigned int) (*p++) << 24;
4067 value|=(unsigned int) (*p++) << 16;
4068 value|=(unsigned int) (*p++) << 8;
4069 value|=(unsigned int) (*p++);
4074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4078 + R e a d B l o b L o n g L o n g %
4082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4084 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
4085 % byte-order specified by the endian member of the image structure.
4087 % The format of the ReadBlobLongLong method is:
4089 % MagickSizeType ReadBlobLongLong(Image *image)
4091 % A description of each parameter follows.
4093 % o image: the image.
4096 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
4101 register const unsigned char
4110 assert(image != (Image *) NULL);
4111 assert(image->signature == MagickCoreSignature);
4113 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4115 return(MagickULLConstant(0));
4116 if (image->endian == LSBEndian)
4118 value=(MagickSizeType) (*p++);
4119 value|=(MagickSizeType) (*p++) << 8;
4120 value|=(MagickSizeType) (*p++) << 16;
4121 value|=(MagickSizeType) (*p++) << 24;
4122 value|=(MagickSizeType) (*p++) << 32;
4123 value|=(MagickSizeType) (*p++) << 40;
4124 value|=(MagickSizeType) (*p++) << 48;
4125 value|=(MagickSizeType) (*p++) << 56;
4128 value=(MagickSizeType) (*p++) << 56;
4129 value|=(MagickSizeType) (*p++) << 48;
4130 value|=(MagickSizeType) (*p++) << 40;
4131 value|=(MagickSizeType) (*p++) << 32;
4132 value|=(MagickSizeType) (*p++) << 24;
4133 value|=(MagickSizeType) (*p++) << 16;
4134 value|=(MagickSizeType) (*p++) << 8;
4135 value|=(MagickSizeType) (*p++);
4140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4144 + R e a d B l o b S h o r t %
4148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4150 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
4151 % specified by the endian member of the image structure.
4153 % The format of the ReadBlobShort method is:
4155 % unsigned short ReadBlobShort(Image *image)
4157 % A description of each parameter follows.
4159 % o image: the image.
4162 MagickExport unsigned short ReadBlobShort(Image *image)
4164 register const unsigned char
4167 register unsigned short
4176 assert(image != (Image *) NULL);
4177 assert(image->signature == MagickCoreSignature);
4179 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4181 return((unsigned short) 0U);
4182 if (image->endian == LSBEndian)
4184 value=(unsigned short) (*p++);
4185 value|=(unsigned short) (*p++) << 8;
4188 value=(unsigned short) ((unsigned short) (*p++) << 8);
4189 value|=(unsigned short) (*p++);
4194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4198 + R e a d B l o b L S B L o n g %
4202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4204 % ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
4205 % least-significant byte first order.
4207 % The format of the ReadBlobLSBLong method is:
4209 % unsigned int ReadBlobLSBLong(Image *image)
4211 % A description of each parameter follows.
4213 % o image: the image.
4216 MagickExport unsigned int ReadBlobLSBLong(Image *image)
4218 register const unsigned char
4221 register unsigned int
4230 assert(image != (Image *) NULL);
4231 assert(image->signature == MagickCoreSignature);
4233 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4236 value=(unsigned int) (*p++);
4237 value|=(unsigned int) (*p++) << 8;
4238 value|=(unsigned int) (*p++) << 16;
4239 value|=(unsigned int) (*p++) << 24;
4244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4248 + R e a d B l o b L S B S i g n e d L o n g %
4252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4254 % ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
4255 % least-significant byte first order.
4257 % The format of the ReadBlobLSBSignedLong method is:
4259 % signed int ReadBlobLSBSignedLong(Image *image)
4261 % A description of each parameter follows.
4263 % o image: the image.
4266 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
4277 quantum.unsigned_value=ReadBlobLSBLong(image);
4278 return(quantum.signed_value);
4282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4286 + R e a d B l o b L S B S h o r t %
4290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4292 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4293 % least-significant byte first order.
4295 % The format of the ReadBlobLSBShort method is:
4297 % unsigned short ReadBlobLSBShort(Image *image)
4299 % A description of each parameter follows.
4301 % o image: the image.
4304 MagickExport unsigned short ReadBlobLSBShort(Image *image)
4306 register const unsigned char
4309 register unsigned short
4318 assert(image != (Image *) NULL);
4319 assert(image->signature == MagickCoreSignature);
4321 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4323 return((unsigned short) 0U);
4324 value=(unsigned short) (*p++);
4325 value|=(unsigned short) (*p++) << 8;
4330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4334 + R e a d B l o b L S B S i g n e d S h o r t %
4338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4340 % ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4341 % least-significant byte-order.
4343 % The format of the ReadBlobLSBSignedShort method is:
4345 % signed short ReadBlobLSBSignedShort(Image *image)
4347 % A description of each parameter follows.
4349 % o image: the image.
4352 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
4363 quantum.unsigned_value=ReadBlobLSBShort(image);
4364 return(quantum.signed_value);
4368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4372 + R e a d B l o b M S B L o n g %
4376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4378 % ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4379 % most-significant byte first order.
4381 % The format of the ReadBlobMSBLong method is:
4383 % unsigned int ReadBlobMSBLong(Image *image)
4385 % A description of each parameter follows.
4387 % o image: the image.
4390 MagickExport unsigned int ReadBlobMSBLong(Image *image)
4392 register const unsigned char
4395 register unsigned int
4404 assert(image != (Image *) NULL);
4405 assert(image->signature == MagickCoreSignature);
4407 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4410 value=(unsigned int) (*p++) << 24;
4411 value|=(unsigned int) (*p++) << 16;
4412 value|=(unsigned int) (*p++) << 8;
4413 value|=(unsigned int) (*p++);
4418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4422 + R e a d B l o b M S B L o n g L o n g %
4426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4428 % ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4429 % in most-significant byte first order.
4431 % The format of the ReadBlobMSBLongLong method is:
4433 % unsigned int ReadBlobMSBLongLong(Image *image)
4435 % A description of each parameter follows.
4437 % o image: the image.
4440 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
4442 register const unsigned char
4445 register MagickSizeType
4454 assert(image != (Image *) NULL);
4455 assert(image->signature == MagickCoreSignature);
4457 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4459 return(MagickULLConstant(0));
4460 value=(MagickSizeType) (*p++) << 56;
4461 value|=(MagickSizeType) (*p++) << 48;
4462 value|=(MagickSizeType) (*p++) << 40;
4463 value|=(MagickSizeType) (*p++) << 32;
4464 value|=(MagickSizeType) (*p++) << 24;
4465 value|=(MagickSizeType) (*p++) << 16;
4466 value|=(MagickSizeType) (*p++) << 8;
4467 value|=(MagickSizeType) (*p++);
4472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4476 + R e a d B l o b M S B S h o r t %
4480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4482 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4483 % most-significant byte first order.
4485 % The format of the ReadBlobMSBShort method is:
4487 % unsigned short ReadBlobMSBShort(Image *image)
4489 % A description of each parameter follows.
4491 % o image: the image.
4494 MagickExport unsigned short ReadBlobMSBShort(Image *image)
4496 register const unsigned char
4499 register unsigned short
4508 assert(image != (Image *) NULL);
4509 assert(image->signature == MagickCoreSignature);
4511 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4513 return((unsigned short) 0U);
4514 value=(unsigned short) ((*p++) << 8);
4515 value|=(unsigned short) (*p++);
4516 return((unsigned short) (value & 0xffff));
4520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4524 + R e a d B l o b M S B S i g n e d L o n g %
4528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4530 % ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4531 % most-significant byte-order.
4533 % The format of the ReadBlobMSBSignedLong method is:
4535 % signed int ReadBlobMSBSignedLong(Image *image)
4537 % A description of each parameter follows.
4539 % o image: the image.
4542 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4553 quantum.unsigned_value=ReadBlobMSBLong(image);
4554 return(quantum.signed_value);
4558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4562 + R e a d B l o b M S B S i g n e d S h o r t %
4566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4568 % ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4569 % most-significant byte-order.
4571 % The format of the ReadBlobMSBSignedShort method is:
4573 % signed short ReadBlobMSBSignedShort(Image *image)
4575 % A description of each parameter follows.
4577 % o image: the image.
4580 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4591 quantum.unsigned_value=ReadBlobMSBShort(image);
4592 return(quantum.signed_value);
4596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4600 + R e a d B l o b S i g n e d L o n g %
4604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4606 % ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4607 % byte-order specified by the endian member of the image structure.
4609 % The format of the ReadBlobSignedLong method is:
4611 % signed int ReadBlobSignedLong(Image *image)
4613 % A description of each parameter follows.
4615 % o image: the image.
4618 MagickExport signed int ReadBlobSignedLong(Image *image)
4629 quantum.unsigned_value=ReadBlobLong(image);
4630 return(quantum.signed_value);
4634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4638 + R e a d B l o b S i g n e d S h o r t %
4642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4644 % ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4645 % byte-order specified by the endian member of the image structure.
4647 % The format of the ReadBlobSignedShort method is:
4649 % signed short ReadBlobSignedShort(Image *image)
4651 % A description of each parameter follows.
4653 % o image: the image.
4656 MagickExport signed short ReadBlobSignedShort(Image *image)
4667 quantum.unsigned_value=ReadBlobShort(image);
4668 return(quantum.signed_value);
4672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4676 + R e a d B l o b S t r e a m %
4680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4682 % ReadBlobStream() reads data from the blob or image file and returns it. It
4683 % returns a pointer to the data buffer you supply or to the image memory
4684 % buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4685 % returns a count of zero and has no other results. If length is greater than
4686 % SSIZE_MAX, the result is unspecified.
4688 % The format of the ReadBlobStream method is:
4690 % const void *ReadBlobStream(Image *image,const size_t length,void *data,
4693 % A description of each parameter follows:
4695 % o image: the image.
4697 % o length: Specifies an integer representing the number of bytes to read
4700 % o count: returns the number of bytes read.
4702 % o data: Specifies an area to place the information requested from the
4706 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
4707 void *data,ssize_t *count)
4710 *magick_restrict blob_info;
4712 assert(image != (Image *) NULL);
4713 assert(image->signature == MagickCoreSignature);
4714 assert(image->blob != (BlobInfo *) NULL);
4715 assert(image->blob->type != UndefinedStream);
4716 assert(count != (ssize_t *) NULL);
4717 blob_info=image->blob;
4718 if (blob_info->type != BlobStream)
4720 assert(data != NULL);
4721 *count=ReadBlob(image,length,(unsigned char *) data);
4724 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4727 blob_info->eof=MagickTrue;
4730 data=blob_info->data+blob_info->offset;
4731 *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4732 blob_info->length-blob_info->offset);
4733 blob_info->offset+=(*count);
4734 if (*count != (ssize_t) length)
4735 blob_info->eof=MagickTrue;
4740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4744 + R e a d B l o b S t r i n g %
4748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4750 % ReadBlobString() reads characters from a blob or file until a newline
4751 % character is read or an end-of-file condition is encountered.
4753 % The format of the ReadBlobString method is:
4755 % char *ReadBlobString(Image *image,char *string)
4757 % A description of each parameter follows:
4759 % o image: the image.
4761 % o string: the address of a character buffer.
4764 MagickExport char *ReadBlobString(Image *image,char *string)
4772 assert(image != (Image *) NULL);
4773 assert(image->signature == MagickCoreSignature);
4774 for (i=0; i < (MagickPathExtent-1L); i++)
4776 c=ReadBlobByte(image);
4780 return((char *) NULL);
4786 if ((i > 0) && (string[i-1] == '\r'))
4796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4800 + R e f e r e n c e B l o b %
4804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4806 % ReferenceBlob() increments the reference count associated with the pixel
4807 % blob returning a pointer to the blob.
4809 % The format of the ReferenceBlob method is:
4811 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
4813 % A description of each parameter follows:
4815 % o blob_info: the blob_info.
4818 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4820 assert(blob != (BlobInfo *) NULL);
4821 assert(blob->signature == MagickCoreSignature);
4822 if (blob->debug != MagickFalse)
4823 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4824 LockSemaphoreInfo(blob->semaphore);
4825 blob->reference_count++;
4826 UnlockSemaphoreInfo(blob->semaphore);
4831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4841 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
4842 % and returns the resulting offset.
4844 % The format of the SeekBlob method is:
4846 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4849 % A description of each parameter follows:
4851 % o image: the image.
4853 % o offset: Specifies an integer representing the offset in bytes.
4855 % o whence: Specifies an integer representing how the offset is
4856 % treated relative to the beginning of the blob as follows:
4858 % SEEK_SET Set position equal to offset bytes.
4859 % SEEK_CUR Set position to current location plus offset.
4860 % SEEK_END Set position to EOF plus offset.
4863 MagickExport MagickOffsetType SeekBlob(Image *image,
4864 const MagickOffsetType offset,const int whence)
4867 *magick_restrict blob_info;
4869 assert(image != (Image *) NULL);
4870 assert(image->signature == MagickCoreSignature);
4871 if (image->debug != MagickFalse)
4872 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4873 assert(image->blob != (BlobInfo *) NULL);
4874 assert(image->blob->type != UndefinedStream);
4875 blob_info=image->blob;
4876 switch (blob_info->type)
4878 case UndefinedStream:
4880 case StandardStream:
4885 if ((offset < 0) && (whence == SEEK_SET))
4887 if (fseek(blob_info->file_info.file,offset,whence) < 0)
4889 blob_info->offset=TellBlob(image);
4894 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4895 if (gzseek(blob_info->file_info.gzfile,(off_t) offset,whence) < 0)
4898 blob_info->offset=TellBlob(image);
4914 blob_info->offset=offset;
4919 if ((blob_info->offset+offset) < 0)
4921 blob_info->offset+=offset;
4926 if (((MagickOffsetType) blob_info->length+offset) < 0)
4928 blob_info->offset=blob_info->length+offset;
4932 if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
4934 blob_info->eof=MagickFalse;
4937 if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
4943 if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
4945 blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
4946 blob_info->custom_stream->data);
4950 return(blob_info->offset);
4954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4958 + S e t B l o b E x e m p t %
4962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4964 % SetBlobExempt() sets the blob exempt status.
4966 % The format of the SetBlobExempt method is:
4968 % MagickBooleanType SetBlobExempt(const Image *image,
4969 % const MagickBooleanType exempt)
4971 % A description of each parameter follows:
4973 % o image: the image.
4975 % o exempt: Set to true if this blob is exempt from being closed.
4978 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4980 assert(image != (const Image *) NULL);
4981 assert(image->signature == MagickCoreSignature);
4982 if (image->debug != MagickFalse)
4983 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4984 image->blob->exempt=exempt;
4988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4992 + S e t B l o b E x t e n t %
4996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4998 % SetBlobExtent() ensures enough space is allocated for the blob. If the
4999 % method is successful, subsequent writes to bytes in the specified range are
5000 % guaranteed not to fail.
5002 % The format of the SetBlobExtent method is:
5004 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
5006 % A description of each parameter follows:
5008 % o image: the image.
5010 % o extent: the blob maximum extent.
5013 MagickExport MagickBooleanType SetBlobExtent(Image *image,
5014 const MagickSizeType extent)
5017 *magick_restrict blob_info;
5019 assert(image != (Image *) NULL);
5020 assert(image->signature == MagickCoreSignature);
5021 if (image->debug != MagickFalse)
5022 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5023 assert(image->blob != (BlobInfo *) NULL);
5024 assert(image->blob->type != UndefinedStream);
5025 blob_info=image->blob;
5026 switch (blob_info->type)
5028 case UndefinedStream:
5030 case StandardStream:
5031 return(MagickFalse);
5040 if (extent != (MagickSizeType) ((off_t) extent))
5041 return(MagickFalse);
5042 offset=SeekBlob(image,0,SEEK_END);
5044 return(MagickFalse);
5045 if ((MagickSizeType) offset >= extent)
5047 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5050 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5051 blob_info->file_info.file);
5052 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5053 if (blob_info->synchronize != MagickFalse)
5058 file=fileno(blob_info->file_info.file);
5059 if ((file == -1) || (offset < 0))
5060 return(MagickFalse);
5061 (void) posix_fallocate(file,offset,extent-offset);
5064 offset=SeekBlob(image,offset,SEEK_SET);
5066 return(MagickFalse);
5071 return(MagickFalse);
5073 return(MagickFalse);
5075 return(MagickFalse);
5078 if (extent != (MagickSizeType) ((size_t) extent))
5079 return(MagickFalse);
5080 if (blob_info->mapped != MagickFalse)
5088 (void) UnmapBlob(blob_info->data,blob_info->length);
5089 RelinquishMagickResource(MapResource,blob_info->length);
5090 if (extent != (MagickSizeType) ((off_t) extent))
5091 return(MagickFalse);
5092 offset=SeekBlob(image,0,SEEK_END);
5094 return(MagickFalse);
5095 if ((MagickSizeType) offset >= extent)
5097 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5098 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5099 blob_info->file_info.file);
5100 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5101 if (blob_info->synchronize != MagickFalse)
5106 file=fileno(blob_info->file_info.file);
5107 if ((file == -1) || (offset < 0))
5108 return(MagickFalse);
5109 (void) posix_fallocate(file,offset,extent-offset);
5112 offset=SeekBlob(image,offset,SEEK_SET);
5114 return(MagickFalse);
5115 (void) AcquireMagickResource(MapResource,extent);
5116 blob_info->data=(unsigned char*) MapBlob(fileno(
5117 blob_info->file_info.file),WriteMode,0,(size_t) extent);
5118 blob_info->extent=(size_t) extent;
5119 blob_info->length=(size_t) extent;
5120 (void) SyncBlob(image);
5123 blob_info->extent=(size_t) extent;
5124 blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
5125 blob_info->extent+1,sizeof(*blob_info->data));
5126 (void) SyncBlob(image);
5127 if (blob_info->data == (unsigned char *) NULL)
5129 (void) DetachBlob(blob_info);
5130 return(MagickFalse);
5141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5145 + S e t C u s t o m S t r e a m D a t a %
5149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5151 % SetCustomStreamData() sets the stream info data member.
5153 % The format of the SetCustomStreamData method is:
5155 % void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
5157 % A description of each parameter follows:
5159 % o custom_stream: the custom stream info.
5161 % o data: an object containing information about the custom stream.
5164 MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
5167 assert(custom_stream != (CustomStreamInfo *) NULL);
5168 assert(custom_stream->signature == MagickCoreSignature);
5169 custom_stream->data=data;
5173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5177 + S e t C u s t o m S t r e a m R e a d e r %
5181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5183 % SetCustomStreamReader() sets the stream info reader member.
5185 % The format of the SetCustomStreamReader method is:
5187 % void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5188 % CustomStreamHandler reader)
5190 % A description of each parameter follows:
5192 % o custom_stream: the custom stream info.
5194 % o reader: a function to read from the stream.
5197 MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5198 CustomStreamHandler reader)
5200 assert(custom_stream != (CustomStreamInfo *) NULL);
5201 assert(custom_stream->signature == MagickCoreSignature);
5202 custom_stream->reader=reader;
5206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5210 + S e t C u s t o m S t r e a m S e e k e r %
5214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5216 % SetCustomStreamSeeker() sets the stream info seeker member.
5218 % The format of the SetCustomStreamReader method is:
5220 % void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5221 % CustomStreamSeeker seeker)
5223 % A description of each parameter follows:
5225 % o custom_stream: the custom stream info.
5227 % o seeker: a function to seek in the custom stream.
5230 MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5231 CustomStreamSeeker seeker)
5233 assert(custom_stream != (CustomStreamInfo *) NULL);
5234 assert(custom_stream->signature == MagickCoreSignature);
5235 custom_stream->seeker=seeker;
5239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5243 + S e t C u s t o m S t r e a m T e l l e r %
5247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5249 % SetCustomStreamTeller() sets the stream info teller member.
5251 % The format of the SetCustomStreamTeller method is:
5253 % void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5254 % CustomStreamTeller *teller)
5256 % A description of each parameter follows:
5258 % o custom_stream: the custom stream info.
5260 % o teller: a function to set the position in the stream.
5263 MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5264 CustomStreamTeller teller)
5266 assert(custom_stream != (CustomStreamInfo *) NULL);
5267 assert(custom_stream->signature == MagickCoreSignature);
5268 custom_stream->teller=teller;
5272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5276 + S e t C u s t o m S t r e a m W r i t e r %
5280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5282 % SetCustomStreamWriter() sets the stream info writer member.
5284 % The format of the SetCustomStreamWriter method is:
5286 % void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5287 % CustomStreamHandler *writer)
5289 % A description of each parameter follows:
5291 % o custom_stream: the custom stream info.
5293 % o writer: a function to write to the custom stream.
5296 MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5297 CustomStreamHandler writer)
5299 assert(custom_stream != (CustomStreamInfo *) NULL);
5300 assert(custom_stream->signature == MagickCoreSignature);
5301 custom_stream->writer=writer;
5305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5315 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
5316 % attributes if it is an blob.
5318 % The format of the SyncBlob method is:
5320 % int SyncBlob(Image *image)
5322 % A description of each parameter follows:
5324 % o image: the image.
5327 static int SyncBlob(Image *image)
5330 *magick_restrict blob_info;
5335 assert(image != (Image *) NULL);
5336 assert(image->signature == MagickCoreSignature);
5337 if (image->debug != MagickFalse)
5338 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5339 assert(image->blob != (BlobInfo *) NULL);
5340 assert(image->blob->type != UndefinedStream);
5341 blob_info=image->blob;
5343 switch (blob_info->type)
5345 case UndefinedStream:
5346 case StandardStream:
5351 status=fflush(blob_info->file_info.file);
5356 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5357 status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5363 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5364 status=BZ2_bzflush(blob_info->file_info.bzfile);
5379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5389 % TellBlob() obtains the current value of the blob or file position.
5391 % The format of the TellBlob method is:
5393 % MagickOffsetType TellBlob(const Image *image)
5395 % A description of each parameter follows:
5397 % o image: the image.
5400 MagickExport MagickOffsetType TellBlob(const Image *image)
5403 *magick_restrict blob_info;
5408 assert(image != (Image *) NULL);
5409 assert(image->signature == MagickCoreSignature);
5410 if (image->debug != MagickFalse)
5411 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5412 assert(image->blob != (BlobInfo *) NULL);
5413 assert(image->blob->type != UndefinedStream);
5414 blob_info=image->blob;
5416 switch (blob_info->type)
5418 case UndefinedStream:
5419 case StandardStream:
5423 offset=ftell(blob_info->file_info.file);
5430 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5431 offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5441 offset=blob_info->offset;
5446 if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5447 offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5459 + U n m a p B l o b %
5463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5465 % UnmapBlob() deallocates the binary large object previously allocated with
5466 % the MapBlob method.
5468 % The format of the UnmapBlob method is:
5470 % MagickBooleanType UnmapBlob(void *map,const size_t length)
5472 % A description of each parameter follows:
5474 % o map: the address of the binary large object.
5476 % o length: the length of the binary large object.
5479 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5481 #if defined(MAGICKCORE_HAVE_MMAP)
5485 status=munmap(map,length);
5486 return(status == -1 ? MagickFalse : MagickTrue);
5490 return(MagickFalse);
5495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5499 + W r i t e B l o b %
5503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5505 % WriteBlob() writes data to a blob or image file. It returns the number of
5508 % The format of the WriteBlob method is:
5510 % ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5512 % A description of each parameter follows:
5514 % o image: the image.
5516 % o length: Specifies an integer representing the number of bytes to
5517 % write to the file.
5519 % o data: The address of the data to write to the blob or file.
5522 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5526 *magick_restrict blob_info;
5531 register const unsigned char
5534 register unsigned char
5540 assert(image != (Image *) NULL);
5541 assert(image->signature == MagickCoreSignature);
5542 assert(image->blob != (BlobInfo *) NULL);
5543 assert(image->blob->type != UndefinedStream);
5546 assert(data != (const void *) NULL);
5547 blob_info=image->blob;
5549 p=(const unsigned char *) data;
5550 q=(unsigned char *) data;
5551 switch (blob_info->type)
5553 case UndefinedStream:
5555 case StandardStream:
5563 count=(ssize_t) fwrite((const char *) data,1,length,
5564 blob_info->file_info.file);
5569 c=putc((int) *p++,blob_info->file_info.file);
5576 c=putc((int) *p++,blob_info->file_info.file);
5583 c=putc((int) *p++,blob_info->file_info.file);
5590 c=putc((int) *p++,blob_info->file_info.file);
5602 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5610 for (i=0; i < (ssize_t) length; i+=count)
5612 count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
5613 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
5626 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5633 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5640 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5647 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5660 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5664 for (i=0; i < (ssize_t) length; i+=count)
5666 count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5667 (int) MagickMin(length-i,MagickMaxBufferExtent));
5681 count=(ssize_t) blob_info->stream(image,data,length);
5686 if ((blob_info->offset+(MagickOffsetType) length) >=
5687 (MagickOffsetType) blob_info->extent)
5689 if (blob_info->mapped != MagickFalse)
5691 blob_info->extent+=length+blob_info->quantum;
5692 blob_info->quantum<<=1;
5693 blob_info->data=(unsigned char *) ResizeQuantumMemory(
5694 blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5695 (void) SyncBlob(image);
5696 if (blob_info->data == (unsigned char *) NULL)
5698 (void) DetachBlob(blob_info);
5702 q=blob_info->data+blob_info->offset;
5703 (void) memcpy(q,p,length);
5704 blob_info->offset+=length;
5705 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5706 blob_info->length=(size_t) blob_info->offset;
5707 count=(ssize_t) length;
5712 if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
5713 count=blob_info->custom_stream->writer((unsigned char *) data,
5714 length,blob_info->custom_stream->data);
5722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5726 + W r i t e B l o b B y t e %
5730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5732 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
5733 % written (either 0 or 1);
5735 % The format of the WriteBlobByte method is:
5737 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
5739 % A description of each parameter follows.
5741 % o image: the image.
5743 % o value: Specifies the value to write.
5746 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5749 *magick_restrict blob_info;
5754 assert(image != (Image *) NULL);
5755 assert(image->signature == MagickCoreSignature);
5756 assert(image->blob != (BlobInfo *) NULL);
5757 assert(image->blob->type != UndefinedStream);
5758 blob_info=image->blob;
5760 switch (blob_info->type)
5762 case StandardStream:
5769 c=putc((int) value,blob_info->file_info.file);
5777 count=WriteBlobStream(image,1,&value);
5785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5789 + W r i t e B l o b F l o a t %
5793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5795 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5796 % specified by the endian member of the image structure.
5798 % The format of the WriteBlobFloat method is:
5800 % ssize_t WriteBlobFloat(Image *image,const float value)
5802 % A description of each parameter follows.
5804 % o image: the image.
5806 % o value: Specifies the value to write.
5809 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5820 quantum.unsigned_value=0U;
5821 quantum.float_value=value;
5822 return(WriteBlobLong(image,quantum.unsigned_value));
5826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5830 + W r i t e B l o b L o n g %
5834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5836 % WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5837 % byte-order specified by the endian member of the image structure.
5839 % The format of the WriteBlobLong method is:
5841 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
5843 % A description of each parameter follows.
5845 % o image: the image.
5847 % o value: Specifies the value to write.
5850 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5855 assert(image != (Image *) NULL);
5856 assert(image->signature == MagickCoreSignature);
5857 if (image->endian == LSBEndian)
5859 buffer[0]=(unsigned char) value;
5860 buffer[1]=(unsigned char) (value >> 8);
5861 buffer[2]=(unsigned char) (value >> 16);
5862 buffer[3]=(unsigned char) (value >> 24);
5863 return(WriteBlobStream(image,4,buffer));
5865 buffer[0]=(unsigned char) (value >> 24);
5866 buffer[1]=(unsigned char) (value >> 16);
5867 buffer[2]=(unsigned char) (value >> 8);
5868 buffer[3]=(unsigned char) value;
5869 return(WriteBlobStream(image,4,buffer));
5873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5877 + W r i t e B l o b L o n g L o n g %
5881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5883 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
5884 % byte-order specified by the endian member of the image structure.
5886 % The format of the WriteBlobLongLong method is:
5888 % ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5890 % A description of each parameter follows.
5892 % o value: Specifies the value to write.
5894 % o image: the image.
5897 MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5902 assert(image != (Image *) NULL);
5903 assert(image->signature == MagickCoreSignature);
5904 if (image->endian == LSBEndian)
5906 buffer[0]=(unsigned char) value;
5907 buffer[1]=(unsigned char) (value >> 8);
5908 buffer[2]=(unsigned char) (value >> 16);
5909 buffer[3]=(unsigned char) (value >> 24);
5910 buffer[4]=(unsigned char) (value >> 32);
5911 buffer[5]=(unsigned char) (value >> 40);
5912 buffer[6]=(unsigned char) (value >> 48);
5913 buffer[7]=(unsigned char) (value >> 56);
5914 return(WriteBlobStream(image,8,buffer));
5916 buffer[0]=(unsigned char) (value >> 56);
5917 buffer[1]=(unsigned char) (value >> 48);
5918 buffer[2]=(unsigned char) (value >> 40);
5919 buffer[3]=(unsigned char) (value >> 32);
5920 buffer[4]=(unsigned char) (value >> 24);
5921 buffer[5]=(unsigned char) (value >> 16);
5922 buffer[6]=(unsigned char) (value >> 8);
5923 buffer[7]=(unsigned char) value;
5924 return(WriteBlobStream(image,8,buffer));
5928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5932 + W r i t e B l o b S h o r t %
5936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5938 % WriteBlobShort() writes a short value as a 16-bit quantity in the
5939 % byte-order specified by the endian member of the image structure.
5941 % The format of the WriteBlobShort method is:
5943 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
5945 % A description of each parameter follows.
5947 % o image: the image.
5949 % o value: Specifies the value to write.
5952 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5957 assert(image != (Image *) NULL);
5958 assert(image->signature == MagickCoreSignature);
5959 if (image->endian == LSBEndian)
5961 buffer[0]=(unsigned char) value;
5962 buffer[1]=(unsigned char) (value >> 8);
5963 return(WriteBlobStream(image,2,buffer));
5965 buffer[0]=(unsigned char) (value >> 8);
5966 buffer[1]=(unsigned char) value;
5967 return(WriteBlobStream(image,2,buffer));
5971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5975 + W r i t e B l o b S i g n e d L o n g %
5979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5981 % WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
5982 % byte-order specified by the endian member of the image structure.
5984 % The format of the WriteBlobSignedLong method is:
5986 % ssize_t WriteBlobSignedLong(Image *image,const signed int value)
5988 % A description of each parameter follows.
5990 % o image: the image.
5992 % o value: Specifies the value to write.
5995 MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6009 assert(image != (Image *) NULL);
6010 assert(image->signature == MagickCoreSignature);
6011 quantum.signed_value=value;
6012 if (image->endian == LSBEndian)
6014 buffer[0]=(unsigned char) quantum.unsigned_value;
6015 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6016 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6017 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6018 return(WriteBlobStream(image,4,buffer));
6020 buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
6021 buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
6022 buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
6023 buffer[3]=(unsigned char) quantum.unsigned_value;
6024 return(WriteBlobStream(image,4,buffer));
6028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6032 + W r i t e B l o b L S B L o n g %
6036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6038 % WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
6039 % least-significant byte first order.
6041 % The format of the WriteBlobLSBLong method is:
6043 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6045 % A description of each parameter follows.
6047 % o image: the image.
6049 % o value: Specifies the value to write.
6052 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6057 assert(image != (Image *) NULL);
6058 assert(image->signature == MagickCoreSignature);
6059 buffer[0]=(unsigned char) value;
6060 buffer[1]=(unsigned char) (value >> 8);
6061 buffer[2]=(unsigned char) (value >> 16);
6062 buffer[3]=(unsigned char) (value >> 24);
6063 return(WriteBlobStream(image,4,buffer));
6067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6071 + W r i t e B l o b L S B S h o r t %
6075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6077 % WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
6078 % least-significant byte first order.
6080 % The format of the WriteBlobLSBShort method is:
6082 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6084 % A description of each parameter follows.
6086 % o image: the image.
6088 % o value: Specifies the value to write.
6091 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6096 assert(image != (Image *) NULL);
6097 assert(image->signature == MagickCoreSignature);
6098 buffer[0]=(unsigned char) value;
6099 buffer[1]=(unsigned char) (value >> 8);
6100 return(WriteBlobStream(image,2,buffer));
6104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6108 + W r i t e B l o b L S B S i g n e d L o n g %
6112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6114 % WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
6115 % least-significant byte first order.
6117 % The format of the WriteBlobLSBSignedLong method is:
6119 % ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6121 % A description of each parameter follows.
6123 % o image: the image.
6125 % o value: Specifies the value to write.
6128 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6142 assert(image != (Image *) NULL);
6143 assert(image->signature == MagickCoreSignature);
6144 quantum.signed_value=value;
6145 buffer[0]=(unsigned char) quantum.unsigned_value;
6146 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6147 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6148 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6149 return(WriteBlobStream(image,4,buffer));
6153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6157 + W r i t e B l o b L S B S i g n e d S h o r t %
6161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6163 % WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
6164 % in least-significant byte first order.
6166 % The format of the WriteBlobLSBSignedShort method is:
6168 % ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
6170 % A description of each parameter follows.
6172 % o image: the image.
6174 % o value: Specifies the value to write.
6177 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
6178 const signed short value)
6192 assert(image != (Image *) NULL);
6193 assert(image->signature == MagickCoreSignature);
6194 quantum.signed_value=value;
6195 buffer[0]=(unsigned char) quantum.unsigned_value;
6196 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6197 return(WriteBlobStream(image,2,buffer));
6201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6205 + W r i t e B l o b M S B L o n g %
6209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6211 % WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
6212 % most-significant byte first order.
6214 % The format of the WriteBlobMSBLong method is:
6216 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6218 % A description of each parameter follows.
6220 % o value: Specifies the value to write.
6222 % o image: the image.
6225 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6230 assert(image != (Image *) NULL);
6231 assert(image->signature == MagickCoreSignature);
6232 buffer[0]=(unsigned char) (value >> 24);
6233 buffer[1]=(unsigned char) (value >> 16);
6234 buffer[2]=(unsigned char) (value >> 8);
6235 buffer[3]=(unsigned char) value;
6236 return(WriteBlobStream(image,4,buffer));
6240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6244 + W r i t e B l o b M S B S i g n e d S h o r t %
6248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6250 % WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
6251 % in most-significant byte first order.
6253 % The format of the WriteBlobMSBSignedShort method is:
6255 % ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
6257 % A description of each parameter follows.
6259 % o image: the image.
6261 % o value: Specifies the value to write.
6264 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
6265 const signed short value)
6279 assert(image != (Image *) NULL);
6280 assert(image->signature == MagickCoreSignature);
6281 quantum.signed_value=value;
6282 buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
6283 buffer[1]=(unsigned char) quantum.unsigned_value;
6284 return(WriteBlobStream(image,2,buffer));
6288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6292 + W r i t e B l o b M S B S h o r t %
6296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6298 % WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6299 % most-significant byte first order.
6301 % The format of the WriteBlobMSBShort method is:
6303 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6305 % A description of each parameter follows.
6307 % o value: Specifies the value to write.
6309 % o file: Specifies the file to write the data to.
6312 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6317 assert(image != (Image *) NULL);
6318 assert(image->signature == MagickCoreSignature);
6319 buffer[0]=(unsigned char) (value >> 8);
6320 buffer[1]=(unsigned char) value;
6321 return(WriteBlobStream(image,2,buffer));
6325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6329 + W r i t e B l o b S t r i n g %
6333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6335 % WriteBlobString() write a string to a blob. It returns the number of
6336 % characters written.
6338 % The format of the WriteBlobString method is:
6340 % ssize_t WriteBlobString(Image *image,const char *string)
6342 % A description of each parameter follows.
6344 % o image: the image.
6346 % o string: Specifies the string to write.
6349 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6351 assert(image != (Image *) NULL);
6352 assert(image->signature == MagickCoreSignature);
6353 assert(string != (const char *) NULL);
6354 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));