2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 % BBBB LLLLL OOO BBBB %
13 % MagickCore Binary Large OBjectS Methods %
20 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/nt-base-private.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/blob-private.h"
47 #include "MagickCore/cache.h"
48 #include "MagickCore/client.h"
49 #include "MagickCore/constitute.h"
50 #include "MagickCore/delegate.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/image-private.h"
54 #include "MagickCore/list.h"
55 #include "MagickCore/locale_.h"
56 #include "MagickCore/log.h"
57 #include "MagickCore/magick.h"
58 #include "MagickCore/memory_.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/resource_.h"
61 #include "MagickCore/semaphore.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/string-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
67 #if defined(MAGICKCORE_ZLIB_DELEGATE)
70 #if defined(MAGICKCORE_BZLIB_DELEGATE)
77 #define MagickMaxBlobExtent 65541
78 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
79 # define MAP_ANONYMOUS MAP_ANON
81 #if !defined(MAP_FAILED)
82 #define MAP_FAILED ((void *) -1)
86 #define _O_BINARY O_BINARY
92 typedef union FileInfo
97 #if defined(MAGICKCORE_ZLIB_DELEGATE)
102 #if defined(MAGICKCORE_BZLIB_DELEGATE)
160 Forward declarations.
166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 + A t t a c h B l o b %
174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
176 % AttachBlob() attaches a blob to the BlobInfo structure.
178 % The format of the AttachBlob method is:
180 % void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
182 % A description of each parameter follows:
184 % o blob_info: Specifies a pointer to a BlobInfo structure.
186 % o blob: the address of a character stream in one of the image formats
187 % understood by ImageMagick.
189 % o length: This size_t integer reflects the length in bytes of the blob.
192 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
195 assert(blob_info != (BlobInfo *) NULL);
196 if (blob_info->debug != MagickFalse)
197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
198 blob_info->length=length;
199 blob_info->extent=length;
200 blob_info->quantum=(size_t) MagickMaxBlobExtent;
202 blob_info->type=BlobStream;
203 blob_info->file_info.file=(FILE *) NULL;
204 blob_info->data=(unsigned char *) blob;
205 blob_info->mapped=MagickFalse;
209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213 + B l o b T o F i l e %
217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 % BlobToFile() writes a blob to a file. It returns MagickFalse if an error
220 % occurs otherwise MagickTrue.
222 % The format of the BlobToFile method is:
224 % MagickBooleanType BlobToFile(char *filename,const void *blob,
225 % const size_t length,ExceptionInfo *exception)
227 % A description of each parameter follows:
229 % o filename: Write the blob to this file.
231 % o blob: the address of a blob.
233 % o length: This length in bytes of the blob.
235 % o exception: return any errors or warnings in this structure.
239 static inline MagickSizeType MagickMin(const MagickSizeType x,
240 const MagickSizeType y)
247 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
248 const size_t length,ExceptionInfo *exception)
259 assert(filename != (const char *) NULL);
260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
261 assert(blob != (const void *) NULL);
262 if (*filename == '\0')
263 file=AcquireUniqueFileResource(filename);
265 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
268 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
271 for (i=0; i < length; i+=count)
273 count=write(file,(const char *) blob+i,(size_t) MagickMin(length-i,
274 (MagickSizeType) SSIZE_MAX));
283 if ((file == -1) || (i < length))
285 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 % B l o b T o I m a g e %
300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 % BlobToImage() implements direct to memory image formats. It returns the
305 % The format of the BlobToImage method is:
307 % Image *BlobToImage(const ImageInfo *image_info,const void *blob,
308 % const size_t length,ExceptionInfo *exception)
310 % A description of each parameter follows:
312 % o image_info: the image info.
314 % o blob: the address of a character stream in one of the image formats
315 % understood by ImageMagick.
317 % o length: This size_t integer reflects the length in bytes of the blob.
319 % o exception: return any errors or warnings in this structure.
322 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
323 const size_t length,ExceptionInfo *exception)
338 assert(image_info != (ImageInfo *) NULL);
339 assert(image_info->signature == MagickSignature);
340 if (image_info->debug != MagickFalse)
341 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
342 image_info->filename);
343 assert(exception != (ExceptionInfo *) NULL);
344 if ((blob == (const void *) NULL) || (length == 0))
346 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
347 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
348 return((Image *) NULL);
350 blob_info=CloneImageInfo(image_info);
351 blob_info->blob=(void *) blob;
352 blob_info->length=length;
353 if (*blob_info->magick == '\0')
354 (void) SetImageInfo(blob_info,0,exception);
355 magick_info=GetMagickInfo(blob_info->magick,exception);
356 if (magick_info == (const MagickInfo *) NULL)
358 blob_info=DestroyImageInfo(blob_info);
359 (void) ThrowMagickException(exception,GetMagickModule(),
360 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
361 image_info->filename);
362 return((Image *) NULL);
364 if (GetMagickBlobSupport(magick_info) != MagickFalse)
367 Native blob support for this image format.
369 (void) CopyMagickString(blob_info->filename,image_info->filename,
371 (void) CopyMagickString(blob_info->magick,image_info->magick,
373 image=ReadImage(blob_info,exception);
374 if (image != (Image *) NULL)
375 (void) DetachBlob(image->blob);
376 blob_info=DestroyImageInfo(blob_info);
380 Write blob to a temporary file on disk.
382 blob_info->blob=(void *) NULL;
384 *blob_info->filename='\0';
385 status=BlobToFile(blob_info->filename,blob,length,exception);
386 if (status == MagickFalse)
388 (void) RelinquishUniqueFileResource(blob_info->filename);
389 blob_info=DestroyImageInfo(blob_info);
390 return((Image *) NULL);
392 clone_info=CloneImageInfo(blob_info);
393 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
394 blob_info->magick,blob_info->filename);
395 image=ReadImage(clone_info,exception);
396 if (image != (Image *) NULL)
402 Restore original filenames.
404 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
406 (void) CopyMagickMemory(images->filename,image_info->filename,
407 sizeof(images->filename));
408 (void) CopyMagickMemory(images->magick_filename,image_info->filename,
409 sizeof(images->magick_filename));
410 images=GetNextImageInList(images);
413 clone_info=DestroyImageInfo(clone_info);
414 (void) RelinquishUniqueFileResource(blob_info->filename);
415 blob_info=DestroyImageInfo(blob_info);
420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424 + C l o n e B l o b I n f o %
428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 % CloneBlobInfo() makes a duplicate of the given blob info structure, or if
431 % blob info is NULL, a new one.
433 % The format of the CloneBlobInfo method is:
435 % BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
437 % A description of each parameter follows:
439 % o blob_info: the blob info.
442 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
447 clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
448 if (clone_info == (BlobInfo *) NULL)
449 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
450 GetBlobInfo(clone_info);
451 if (blob_info == (BlobInfo *) NULL)
453 clone_info->length=blob_info->length;
454 clone_info->extent=blob_info->extent;
455 clone_info->synchronize=blob_info->synchronize;
456 clone_info->quantum=blob_info->quantum;
457 clone_info->mapped=blob_info->mapped;
458 clone_info->eof=blob_info->eof;
459 clone_info->offset=blob_info->offset;
460 clone_info->size=blob_info->size;
461 clone_info->exempt=blob_info->exempt;
462 clone_info->status=blob_info->status;
463 clone_info->temporary=blob_info->temporary;
464 clone_info->type=blob_info->type;
465 clone_info->file_info.file=blob_info->file_info.file;
466 clone_info->properties=blob_info->properties;
467 clone_info->stream=blob_info->stream;
468 clone_info->data=blob_info->data;
469 clone_info->debug=IsEventLogging();
470 clone_info->reference_count=1;
475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479 + C l o s e B l o b %
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 % CloseBlob() closes a stream associated with the image.
487 % The format of the CloseBlob method is:
489 % MagickBooleanType CloseBlob(Image *image)
491 % A description of each parameter follows:
493 % o image: the image.
496 MagickExport MagickBooleanType CloseBlob(Image *image)
504 assert(image != (Image *) NULL);
505 assert(image->signature == MagickSignature);
506 if (image->debug != MagickFalse)
507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
508 assert(image->blob != (BlobInfo *) NULL);
509 if (image->blob->type == UndefinedStream)
511 status=SyncBlob(image);
512 switch (image->blob->type)
514 case UndefinedStream:
520 if (image->blob->synchronize != MagickFalse)
521 status=fsync(fileno(image->blob->file_info.file));
522 status=ferror(image->blob->file_info.file);
527 #if defined(MAGICKCORE_ZLIB_DELEGATE)
528 (void) gzerror(image->blob->file_info.gzfile,&status);
534 #if defined(MAGICKCORE_BZLIB_DELEGATE)
535 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
543 if ((image->blob->file_info.file != (FILE *) NULL) &&
544 (image->blob->synchronize != MagickFalse))
546 (void) fsync(fileno(image->blob->file_info.file));
547 status=ferror(image->blob->file_info.file);
552 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
553 image->blob->size=GetBlobSize(image);
554 image->extent=image->blob->size;
555 image->blob->eof=MagickFalse;
556 if (image->blob->exempt != MagickFalse)
558 image->blob->type=UndefinedStream;
559 return(image->blob->status);
561 switch (image->blob->type)
563 case UndefinedStream:
568 status=fclose(image->blob->file_info.file);
573 #if defined(MAGICKCORE_HAVE_PCLOSE)
574 status=pclose(image->blob->file_info.file);
580 #if defined(MAGICKCORE_ZLIB_DELEGATE)
581 status=gzclose(image->blob->file_info.gzfile);
587 #if defined(MAGICKCORE_BZLIB_DELEGATE)
588 BZ2_bzclose(image->blob->file_info.bzfile);
596 if (image->blob->file_info.file != (FILE *) NULL)
597 status=fclose(image->blob->file_info.file);
601 (void) DetachBlob(image->blob);
602 image->blob->status=status < 0 ? MagickTrue : MagickFalse;
603 return(image->blob->status);
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 + D e s t r o y B l o b %
615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617 % DestroyBlob() deallocates memory associated with a blob.
619 % The format of the DestroyBlob method is:
621 % void DestroyBlob(Image *image)
623 % A description of each parameter follows:
625 % o image: the image.
628 MagickExport void DestroyBlob(Image *image)
633 assert(image != (Image *) NULL);
634 assert(image->signature == MagickSignature);
635 if (image->debug != MagickFalse)
636 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
637 assert(image->blob != (BlobInfo *) NULL);
638 assert(image->blob->signature == MagickSignature);
640 LockSemaphoreInfo(image->blob->semaphore);
641 image->blob->reference_count--;
642 assert(image->blob->reference_count >= 0);
643 if (image->blob->reference_count == 0)
645 UnlockSemaphoreInfo(image->blob->semaphore);
646 if (destroy == MagickFalse)
648 (void) CloseBlob(image);
649 if (image->blob->mapped != MagickFalse)
651 (void) UnmapBlob(image->blob->data,image->blob->length);
652 RelinquishMagickResource(MapResource,image->blob->length);
654 if (image->blob->semaphore != (SemaphoreInfo *) NULL)
655 DestroySemaphoreInfo(&image->blob->semaphore);
656 image->blob->signature=(~MagickSignature);
657 image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665 + D e t a c h B l o b %
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671 % DetachBlob() detaches a blob from the BlobInfo structure.
673 % The format of the DetachBlob method is:
675 % unsigned char *DetachBlob(BlobInfo *blob_info)
677 % A description of each parameter follows:
679 % o blob_info: Specifies a pointer to a BlobInfo structure.
682 MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
687 assert(blob_info != (BlobInfo *) NULL);
688 if (blob_info->debug != MagickFalse)
689 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
690 if (blob_info->mapped != MagickFalse)
692 (void) UnmapBlob(blob_info->data,blob_info->length);
693 RelinquishMagickResource(MapResource,blob_info->length);
695 blob_info->mapped=MagickFalse;
698 blob_info->eof=MagickFalse;
699 blob_info->exempt=MagickFalse;
700 blob_info->type=UndefinedStream;
701 blob_info->file_info.file=(FILE *) NULL;
702 data=blob_info->data;
703 blob_info->data=(unsigned char *) NULL;
704 blob_info->stream=(StreamHandler) NULL;
709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713 + D i s c a r d B l o b B y t e s %
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719 % DiscardBlobBytes() discards bytes in a blob.
721 % The format of the DiscardBlobBytes method is:
723 % MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
725 % A description of each parameter follows.
727 % o image: the image.
729 % o length: the number of bytes to skip.
733 static inline const unsigned char *ReadBlobStream(Image *image,
734 const size_t length,unsigned char *data,ssize_t *count)
736 assert(count != (ssize_t *) NULL);
737 assert(image->blob != (BlobInfo *) NULL);
738 if (image->blob->type != BlobStream)
740 *count=ReadBlob(image,length,data);
743 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
746 image->blob->eof=MagickTrue;
749 data=image->blob->data+image->blob->offset;
750 *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
751 image->blob->offset));
752 image->blob->offset+=(*count);
753 if (*count != (ssize_t) length)
754 image->blob->eof=MagickTrue;
758 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
759 const MagickSizeType length)
761 register MagickOffsetType
773 assert(image != (Image *) NULL);
774 assert(image->signature == MagickSignature);
776 for (i=0; i < (MagickOffsetType) length; i+=count)
778 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
779 (void) ReadBlobStream(image,quantum,buffer,&count);
787 return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 + D u p l i c a t e s B l o b %
799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
801 % DuplicateBlob() duplicates a blob descriptor.
803 % The format of the DuplicateBlob method is:
805 % void DuplicateBlob(Image *image,const Image *duplicate)
807 % A description of each parameter follows:
809 % o image: the image.
811 % o duplicate: the duplicate image.
814 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
816 assert(image != (Image *) NULL);
817 assert(image->signature == MagickSignature);
818 if (image->debug != MagickFalse)
819 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
820 assert(duplicate != (Image *) NULL);
821 assert(duplicate->signature == MagickSignature);
823 image->blob=ReferenceBlob(duplicate->blob);
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 % EOFBlob() returns a non-zero value when EOF has been detected reading from
840 % The format of the EOFBlob method is:
842 % int EOFBlob(const Image *image)
844 % A description of each parameter follows:
846 % o image: the image.
849 MagickExport int EOFBlob(const Image *image)
851 assert(image != (Image *) NULL);
852 assert(image->signature == MagickSignature);
853 if (image->debug != MagickFalse)
854 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
855 assert(image->blob != (BlobInfo *) NULL);
856 assert(image->blob->type != UndefinedStream);
857 switch (image->blob->type)
859 case UndefinedStream:
865 image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
871 image->blob->eof=MagickFalse;
876 #if defined(MAGICKCORE_BZLIB_DELEGATE)
881 (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
882 image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
888 image->blob->eof=MagickFalse;
894 return((int) image->blob->eof);
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 + F i l e T o B l o b %
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 % FileToBlob() returns the contents of a file as a buffer terminated with
909 % the '\0' character. The length of the buffer (not including the extra
910 % terminating '\0' character) is returned via the 'length' parameter. Free
911 % the buffer with RelinquishMagickMemory().
913 % The format of the FileToBlob method is:
915 % unsigned char *FileToBlob(const char *filename,const size_t extent,
916 % size_t *length,ExceptionInfo *exception)
918 % A description of each parameter follows:
920 % o blob: FileToBlob() returns the contents of a file as a blob. If
921 % an error occurs NULL is returned.
923 % o filename: the filename.
925 % o extent: The maximum length of the blob.
927 % o length: On return, this reflects the actual length of the blob.
929 % o exception: return any errors or warnings in this structure.
932 MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
933 size_t *length,ExceptionInfo *exception)
953 assert(filename != (const char *) NULL);
954 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
955 assert(exception != (ExceptionInfo *) NULL);
958 if (LocaleCompare(filename,"-") != 0)
959 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
962 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
963 return((unsigned char *) NULL);
965 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
967 if ((file == fileno(stdin)) || (offset < 0) ||
968 (offset != (MagickOffsetType) ((ssize_t) offset)))
977 Stream is not seekable.
979 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
980 quantum=(size_t) MagickMaxBufferExtent;
981 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
982 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
983 MagickMaxBufferExtent);
984 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
985 for (i=0; blob != (unsigned char *) NULL; i+=count)
987 count=read(file,blob+i,quantum);
994 if (~((size_t) i) < (quantum+1))
996 blob=(unsigned char *) RelinquishMagickMemory(blob);
999 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1001 if ((size_t) (i+count) >= extent)
1004 if (LocaleCompare(filename,"-") != 0)
1006 if (blob == (unsigned char *) NULL)
1008 (void) ThrowMagickException(exception,GetMagickModule(),
1009 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1010 return((unsigned char *) NULL);
1014 blob=(unsigned char *) RelinquishMagickMemory(blob);
1015 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1016 return((unsigned char *) NULL);
1018 *length=(size_t) MagickMin(i+count,extent);
1022 *length=(size_t) MagickMin((MagickSizeType) offset,extent);
1023 blob=(unsigned char *) NULL;
1024 if (~(*length) >= (MaxTextExtent-1))
1025 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1027 if (blob == (unsigned char *) NULL)
1030 (void) ThrowMagickException(exception,GetMagickModule(),
1031 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1032 return((unsigned char *) NULL);
1034 map=MapBlob(file,ReadMode,0,*length);
1035 if (map != (unsigned char *) NULL)
1037 (void) memcpy(blob,map,*length);
1038 (void) UnmapBlob(map,*length);
1042 (void) lseek(file,0,SEEK_SET);
1043 for (i=0; i < *length; i+=count)
1045 count=read(file,blob+i,(size_t) MagickMin(*length-i,(MagickSizeType)
1057 blob=(unsigned char *) RelinquishMagickMemory(blob);
1058 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1059 return((unsigned char *) NULL);
1063 if (LocaleCompare(filename,"-") != 0)
1067 blob=(unsigned char *) RelinquishMagickMemory(blob);
1068 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078 % F i l e T o I m a g e %
1082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1084 % FileToImage() write the contents of a file to an image.
1086 % The format of the FileToImage method is:
1088 % MagickBooleanType FileToImage(Image *,const char *filename)
1090 % A description of each parameter follows:
1092 % o image: the image.
1094 % o filename: the filename.
1098 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1099 const unsigned char *data)
1104 register unsigned char
1107 assert(image->blob != (BlobInfo *) NULL);
1108 if (image->blob->type != BlobStream)
1109 return(WriteBlob(image,length,data));
1110 assert(image->blob->type != UndefinedStream);
1111 assert(data != (void *) NULL);
1112 extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1113 if (extent >= image->blob->extent)
1115 image->blob->quantum<<=1;
1116 extent=image->blob->extent+image->blob->quantum+length;
1117 if (SetBlobExtent(image,extent) == MagickFalse)
1120 q=image->blob->data+image->blob->offset;
1121 (void) memcpy(q,data,length);
1122 image->blob->offset+=length;
1123 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1124 image->blob->length=(size_t) image->blob->offset;
1125 return((ssize_t) length);
1128 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1129 ExceptionInfo *exception)
1147 assert(image != (const Image *) NULL);
1148 assert(image->signature == MagickSignature);
1149 assert(filename != (const char *) NULL);
1150 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1152 if (LocaleCompare(filename,"-") != 0)
1153 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1156 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1157 return(MagickFalse);
1159 quantum=(size_t) MagickMaxBufferExtent;
1160 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1161 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1162 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1163 if (blob == (unsigned char *) NULL)
1165 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1167 return(MagickFalse);
1171 count=read(file,blob,quantum);
1178 length=(size_t) count;
1179 count=WriteBlobStream(image,length,blob);
1180 if (count != (ssize_t) length)
1182 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1188 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1189 blob=(unsigned char *) RelinquishMagickMemory(blob);
1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1198 + G e t B l o b E r r o r %
1202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1204 % GetBlobError() returns MagickTrue if the blob associated with the specified
1205 % image encountered an error.
1207 % The format of the GetBlobError method is:
1209 % MagickBooleanType GetBlobError(const Image *image)
1211 % A description of each parameter follows:
1213 % o image: the image.
1216 MagickPrivate MagickBooleanType GetBlobError(const Image *image)
1218 assert(image != (const Image *) NULL);
1219 assert(image->signature == MagickSignature);
1220 if (image->debug != MagickFalse)
1221 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1222 return(image->blob->status);
1226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1230 + G e t B l o b F i l e H a n d l e %
1234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1236 % GetBlobFileHandle() returns the file handle associated with the image blob.
1238 % The format of the GetBlobFile method is:
1240 % FILE *GetBlobFileHandle(const Image *image)
1242 % A description of each parameter follows:
1244 % o image: the image.
1247 MagickExport FILE *GetBlobFileHandle(const Image *image)
1249 assert(image != (const Image *) NULL);
1250 assert(image->signature == MagickSignature);
1251 return(image->blob->file_info.file);
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259 + G e t B l o b I n f o %
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265 % GetBlobInfo() initializes the BlobInfo structure.
1267 % The format of the GetBlobInfo method is:
1269 % void GetBlobInfo(BlobInfo *blob_info)
1271 % A description of each parameter follows:
1273 % o blob_info: Specifies a pointer to a BlobInfo structure.
1276 MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
1278 assert(blob_info != (BlobInfo *) NULL);
1279 (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1280 blob_info->type=UndefinedStream;
1281 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1282 blob_info->properties.st_mtime=time((time_t *) NULL);
1283 blob_info->properties.st_ctime=time((time_t *) NULL);
1284 blob_info->debug=IsEventLogging();
1285 blob_info->reference_count=1;
1286 blob_info->semaphore=AllocateSemaphoreInfo();
1287 blob_info->signature=MagickSignature;
1291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1295 % G e t B l o b P r o p e r t i e s %
1299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1301 % GetBlobProperties() returns information about an image blob.
1303 % The format of the GetBlobProperties method is:
1305 % const struct stat *GetBlobProperties(const Image *image)
1307 % A description of each parameter follows:
1309 % o image: the image.
1312 MagickPrivate const struct stat *GetBlobProperties(const Image *image)
1314 assert(image != (Image *) NULL);
1315 assert(image->signature == MagickSignature);
1316 if (image->debug != MagickFalse)
1317 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1318 return(&image->blob->properties);
1322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326 + G e t B l o b S i z e %
1330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1332 % GetBlobSize() returns the current length of the image file or blob; zero is
1333 % returned if the size cannot be determined.
1335 % The format of the GetBlobSize method is:
1337 % MagickSizeType GetBlobSize(const Image *image)
1339 % A description of each parameter follows:
1341 % o image: the image.
1344 MagickExport MagickSizeType GetBlobSize(const Image *image)
1349 assert(image != (Image *) NULL);
1350 assert(image->signature == MagickSignature);
1351 if (image->debug != MagickFalse)
1352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1353 assert(image->blob != (BlobInfo *) NULL);
1355 switch (image->blob->type)
1357 case UndefinedStream:
1359 extent=image->blob->size;
1362 case StandardStream:
1364 extent=image->blob->size;
1369 if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
1370 extent=(MagickSizeType) image->blob->properties.st_size;
1375 extent=image->blob->size;
1384 status=GetPathAttributes(image->filename,&image->blob->properties);
1385 if (status != MagickFalse)
1386 extent=(MagickSizeType) image->blob->properties.st_size;
1393 extent=(MagickSizeType) image->blob->length;
1401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405 + G e t B l o b S t r e a m D a t a %
1409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1411 % GetBlobStreamData() returns the stream data for the image.
1413 % The format of the GetBlobStreamData method is:
1415 % unsigned char *GetBlobStreamData(const Image *image)
1417 % A description of each parameter follows:
1419 % o image: the image.
1422 MagickExport unsigned char *GetBlobStreamData(const Image *image)
1424 assert(image != (const Image *) NULL);
1425 assert(image->signature == MagickSignature);
1426 return(image->blob->data);
1430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1434 + G e t B l o b S t r e a m H a n d l e r %
1438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440 % GetBlobStreamHandler() returns the stream handler for the image.
1442 % The format of the GetBlobStreamHandler method is:
1444 % StreamHandler GetBlobStreamHandler(const Image *image)
1446 % A description of each parameter follows:
1448 % o image: the image.
1451 MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
1453 assert(image != (const Image *) NULL);
1454 assert(image->signature == MagickSignature);
1455 if (image->debug != MagickFalse)
1456 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1457 return(image->blob->stream);
1461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465 % I m a g e T o B l o b %
1469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1471 % ImageToBlob() implements direct to memory image formats. It returns the
1472 % image as a formatted blob and its length. The magick member of the Image
1473 % structure determines the format of the returned blob (GIF, JPEG, PNG,
1474 % etc.). This method is the equivalent of WriteImage(), but writes the
1475 % formatted "file" to a memory buffer rather than to an actual file.
1477 % The format of the ImageToBlob method is:
1479 % unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1480 % size_t *length,ExceptionInfo *exception)
1482 % A description of each parameter follows:
1484 % o image_info: the image info.
1486 % o image: the image.
1488 % o length: return the actual length of the blob.
1490 % o exception: return any errors or warnings in this structure.
1493 MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1494 Image *image,size_t *length,ExceptionInfo *exception)
1508 assert(image_info != (const ImageInfo *) NULL);
1509 assert(image_info->signature == MagickSignature);
1510 if (image_info->debug != MagickFalse)
1511 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1512 image_info->filename);
1513 assert(image != (Image *) NULL);
1514 assert(image->signature == MagickSignature);
1515 assert(exception != (ExceptionInfo *) NULL);
1517 blob=(unsigned char *) NULL;
1518 blob_info=CloneImageInfo(image_info);
1519 blob_info->adjoin=MagickFalse;
1520 (void) SetImageInfo(blob_info,1,exception);
1521 if (*blob_info->magick != '\0')
1522 (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1523 magick_info=GetMagickInfo(image->magick,exception);
1524 if (magick_info == (const MagickInfo *) NULL)
1526 (void) ThrowMagickException(exception,GetMagickModule(),
1527 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1531 (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1532 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1535 Native blob support for this image format.
1537 blob_info->length=0;
1538 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1539 sizeof(unsigned char));
1540 if (blob_info->blob == (void *) NULL)
1541 (void) ThrowMagickException(exception,GetMagickModule(),
1542 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1545 (void) CloseBlob(image);
1546 image->blob->exempt=MagickTrue;
1547 *image->filename='\0';
1548 status=WriteImage(blob_info,image,exception);
1549 *length=image->blob->length;
1550 blob=DetachBlob(image->blob);
1551 if (status == MagickFalse)
1552 blob=(unsigned char *) RelinquishMagickMemory(blob);
1554 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1561 unique[MaxTextExtent];
1567 Write file to disk in blob image format.
1569 file=AcquireUniqueFileResource(unique);
1572 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1573 image_info->filename);
1577 blob_info->file=fdopen(file,"wb");
1578 if (blob_info->file != (FILE *) NULL)
1580 (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
1581 image->magick,unique);
1582 status=WriteImage(blob_info,image,exception);
1583 (void) fclose(blob_info->file);
1584 if (status != MagickFalse)
1585 blob=FileToBlob(image->filename,~0UL,length,exception);
1587 (void) RelinquishUniqueFileResource(unique);
1590 blob_info=DestroyImageInfo(blob_info);
1595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1599 % I m a g e T o F i l e %
1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605 % ImageToFile() writes an image to a file. It returns MagickFalse if an error
1606 % occurs otherwise MagickTrue.
1608 % The format of the ImageToFile method is:
1610 % MagickBooleanType ImageToFile(Image *image,char *filename,
1611 % ExceptionInfo *exception)
1613 % A description of each parameter follows:
1615 % o image: the image.
1617 % o filename: Write the image to this file.
1619 % o exception: return any errors or warnings in this structure.
1622 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1623 ExceptionInfo *exception)
1628 register const unsigned char
1647 assert(image != (Image *) NULL);
1648 assert(image->signature == MagickSignature);
1649 assert(image->blob != (BlobInfo *) NULL);
1650 assert(image->blob->type != UndefinedStream);
1651 if (image->debug != MagickFalse)
1652 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1653 assert(filename != (const char *) NULL);
1654 if (*filename == '\0')
1655 file=AcquireUniqueFileResource(filename);
1657 if (LocaleCompare(filename,"-") == 0)
1658 file=fileno(stdout);
1660 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1663 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1664 return(MagickFalse);
1666 quantum=(size_t) MagickMaxBufferExtent;
1667 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1668 quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
1669 MagickMaxBufferExtent);
1670 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1671 if (buffer == (unsigned char *) NULL)
1674 (void) ThrowMagickException(exception,GetMagickModule(),
1675 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1676 return(MagickFalse);
1679 p=ReadBlobStream(image,quantum,buffer,&count);
1680 for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1682 length=(size_t) count;
1683 for (i=0; i < length; i+=count)
1685 count=write(file,p+i,(size_t) (length-i));
1696 if (LocaleCompare(filename,"-") != 0)
1698 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1699 if ((file == -1) || (i < length))
1701 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1702 return(MagickFalse);
1708 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1712 % I m a g e s T o B l o b %
1716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718 % ImagesToBlob() implements direct to memory image formats. It returns the
1719 % image sequence as a blob and its length. The magick member of the ImageInfo
1720 % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1722 % Note, some image formats do not permit multiple images to the same image
1723 % stream (e.g. JPEG). in this instance, just the first image of the
1724 % sequence is returned as a blob.
1726 % The format of the ImagesToBlob method is:
1728 % unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1729 % size_t *length,ExceptionInfo *exception)
1731 % A description of each parameter follows:
1733 % o image_info: the image info.
1735 % o images: the image list.
1737 % o length: return the actual length of the blob.
1739 % o exception: return any errors or warnings in this structure.
1742 MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1743 Image *images,size_t *length,ExceptionInfo *exception)
1757 assert(image_info != (const ImageInfo *) NULL);
1758 assert(image_info->signature == MagickSignature);
1759 if (image_info->debug != MagickFalse)
1760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1761 image_info->filename);
1762 assert(images != (Image *) NULL);
1763 assert(images->signature == MagickSignature);
1764 assert(exception != (ExceptionInfo *) NULL);
1766 blob=(unsigned char *) NULL;
1767 blob_info=CloneImageInfo(image_info);
1768 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1770 if (*blob_info->magick != '\0')
1771 (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1772 if (blob_info->adjoin == MagickFalse)
1774 blob_info=DestroyImageInfo(blob_info);
1775 return(ImageToBlob(image_info,images,length,exception));
1777 magick_info=GetMagickInfo(images->magick,exception);
1778 if (magick_info == (const MagickInfo *) NULL)
1780 (void) ThrowMagickException(exception,GetMagickModule(),
1781 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1785 (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1786 if (GetMagickBlobSupport(magick_info) != MagickFalse)
1789 Native blob support for this images format.
1791 blob_info->length=0;
1792 blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1793 sizeof(unsigned char));
1794 if (blob_info->blob == (void *) NULL)
1795 (void) ThrowMagickException(exception,GetMagickModule(),
1796 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1799 (void) CloseBlob(images);
1800 images->blob->exempt=MagickTrue;
1801 *images->filename='\0';
1802 status=WriteImages(blob_info,images,images->filename,exception);
1803 *length=images->blob->length;
1804 blob=DetachBlob(images->blob);
1805 if (status == MagickFalse)
1806 blob=(unsigned char *) RelinquishMagickMemory(blob);
1808 blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1815 filename[MaxTextExtent],
1816 unique[MaxTextExtent];
1822 Write file to disk in blob images format.
1824 file=AcquireUniqueFileResource(unique);
1827 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1828 image_info->filename);
1832 blob_info->file=fdopen(file,"wb");
1833 if (blob_info->file != (FILE *) NULL)
1835 (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
1836 images->magick,unique);
1837 status=WriteImages(blob_info,images,filename,exception);
1838 (void) fclose(blob_info->file);
1839 if (status != MagickFalse)
1840 blob=FileToBlob(images->filename,~0UL,length,exception);
1842 (void) RelinquishUniqueFileResource(unique);
1845 blob_info=DestroyImageInfo(blob_info);
1849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1853 % I n j e c t I m a g e B l o b %
1857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1859 % InjectImageBlob() injects the image with a copy of itself in the specified
1860 % format (e.g. inject JPEG into a PDF image).
1862 % The format of the InjectImageBlob method is:
1864 % MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1865 % Image *image,Image *inject_image,const char *format,
1866 % ExceptionInfo *exception)
1868 % A description of each parameter follows:
1870 % o image_info: the image info..
1872 % o image: the image.
1874 % o inject_image: inject into the image stream.
1876 % o format: the image format.
1878 % o exception: return any errors or warnings in this structure.
1881 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1882 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1885 filename[MaxTextExtent];
1918 Write inject image to a temporary file.
1920 assert(image_info != (ImageInfo *) NULL);
1921 assert(image_info->signature == MagickSignature);
1922 assert(image != (Image *) NULL);
1923 assert(image->signature == MagickSignature);
1924 if (image->debug != MagickFalse)
1925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1926 assert(inject_image != (Image *) NULL);
1927 assert(inject_image->signature == MagickSignature);
1928 assert(exception != (ExceptionInfo *) NULL);
1929 unique_file=(FILE *) NULL;
1930 file=AcquireUniqueFileResource(filename);
1932 unique_file=fdopen(file,"wb");
1933 if ((file == -1) || (unique_file == (FILE *) NULL))
1935 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1936 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1938 return(MagickFalse);
1940 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1941 if (byte_image == (Image *) NULL)
1943 (void) fclose(unique_file);
1944 (void) RelinquishUniqueFileResource(filename);
1945 return(MagickFalse);
1947 (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
1949 DestroyBlob(byte_image);
1950 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1951 write_info=CloneImageInfo(image_info);
1952 SetImageInfoFile(write_info,unique_file);
1953 status=WriteImage(write_info,byte_image,exception);
1954 write_info=DestroyImageInfo(write_info);
1955 byte_image=DestroyImage(byte_image);
1956 (void) fclose(unique_file);
1957 if (status == MagickFalse)
1959 (void) RelinquishUniqueFileResource(filename);
1960 return(MagickFalse);
1963 Inject into image stream.
1965 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1968 (void) RelinquishUniqueFileResource(filename);
1969 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1970 image_info->filename);
1971 return(MagickFalse);
1973 quantum=(size_t) MagickMaxBufferExtent;
1974 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1975 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1976 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1977 if (buffer == (unsigned char *) NULL)
1979 (void) RelinquishUniqueFileResource(filename);
1980 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1983 for (i=0; ; i+=count)
1985 count=read(file,buffer,quantum);
1992 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1997 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
1998 (void) RelinquishUniqueFileResource(filename);
1999 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2008 + I s B l o b E x e m p t %
2012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2014 % IsBlobExempt() returns true if the blob is exempt.
2016 % The format of the IsBlobExempt method is:
2018 % MagickBooleanType IsBlobExempt(const Image *image)
2020 % A description of each parameter follows:
2022 % o image: the image.
2025 MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
2027 assert(image != (const Image *) NULL);
2028 assert(image->signature == MagickSignature);
2029 if (image->debug != MagickFalse)
2030 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2031 return(image->blob->exempt);
2035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2039 + I s B l o b S e e k a b l e %
2043 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2045 % IsBlobSeekable() returns true if the blob is seekable.
2047 % The format of the IsBlobSeekable method is:
2049 % MagickBooleanType IsBlobSeekable(const Image *image)
2051 % A description of each parameter follows:
2053 % o image: the image.
2056 MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
2061 assert(image != (const Image *) NULL);
2062 assert(image->signature == MagickSignature);
2063 if (image->debug != MagickFalse)
2064 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2065 switch (image->blob->type)
2071 seekable=MagickTrue;
2076 seekable=MagickFalse;
2084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2088 + I s B l o b T e m p o r a r y %
2092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2094 % IsBlobTemporary() returns true if the blob is temporary.
2096 % The format of the IsBlobTemporary method is:
2098 % MagickBooleanType IsBlobTemporary(const Image *image)
2100 % A description of each parameter follows:
2102 % o image: the image.
2105 MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
2107 assert(image != (const Image *) NULL);
2108 assert(image->signature == MagickSignature);
2109 if (image->debug != MagickFalse)
2110 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2111 return(image->blob->temporary);
2115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2125 % MapBlob() creates a mapping from a file to a binary large object.
2127 % The format of the MapBlob method is:
2129 % unsigned char *MapBlob(int file,const MapMode mode,
2130 % const MagickOffsetType offset,const size_t length)
2132 % A description of each parameter follows:
2134 % o file: map this file descriptor.
2136 % o mode: ReadMode, WriteMode, or IOMode.
2138 % o offset: starting at this offset within the file.
2140 % o length: the length of the mapping is returned in this pointer.
2143 MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2144 const MagickOffsetType offset,const size_t length)
2146 #if defined(MAGICKCORE_HAVE_MMAP)
2159 #if defined(MAP_ANONYMOUS)
2160 flags|=MAP_ANONYMOUS;
2162 return((unsigned char *) NULL);
2169 protection=PROT_READ;
2175 protection=PROT_WRITE;
2181 protection=PROT_READ | PROT_WRITE;
2186 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2187 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2190 map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
2191 MAP_HUGETLB,file,(off_t) offset);
2192 if (map == (unsigned char *) MAP_FAILED)
2193 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2196 if (map == (unsigned char *) MAP_FAILED)
2197 return((unsigned char *) NULL);
2204 return((unsigned char *) NULL);
2209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2213 + M S B O r d e r L o n g %
2217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2219 % MSBOrderLong() converts a least-significant byte first buffer of integers to
2220 % most-significant byte first.
2222 % The format of the MSBOrderLong method is:
2224 % void MSBOrderLong(unsigned char *buffer,const size_t length)
2226 % A description of each parameter follows.
2228 % o buffer: Specifies a pointer to a buffer of integers.
2230 % o length: Specifies the length of the buffer.
2233 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2238 register unsigned char
2242 assert(buffer != (unsigned char *) NULL);
2249 *buffer++=(unsigned char) c;
2253 *buffer++=(unsigned char) c;
2259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2263 + M S B O r d e r S h o r t %
2267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2269 % MSBOrderShort() converts a least-significant byte first buffer of integers
2270 % to most-significant byte first.
2272 % The format of the MSBOrderShort method is:
2274 % void MSBOrderShort(unsigned char *p,const size_t length)
2276 % A description of each parameter follows.
2278 % o p: Specifies a pointer to a buffer of integers.
2280 % o length: Specifies the length of the buffer.
2283 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2288 register unsigned char
2291 assert(p != (unsigned char *) NULL);
2298 *p++=(unsigned char) c;
2303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2313 % OpenBlob() opens a file associated with the image. A file name of '-' sets
2314 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
2315 % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2316 % compressed for type 'w'. If the filename prefix is '|', it is piped to or
2317 % from a system command.
2319 % The format of the OpenBlob method is:
2321 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2322 % const BlobMode mode,ExceptionInfo *exception)
2324 % A description of each parameter follows:
2326 % o image_info: the image info.
2328 % o image: the image.
2330 % o mode: the mode for opening the file.
2333 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2334 Image *image,const BlobMode mode,ExceptionInfo *exception)
2337 extension[MaxTextExtent],
2338 filename[MaxTextExtent];
2349 assert(image_info != (ImageInfo *) NULL);
2350 assert(image_info->signature == MagickSignature);
2351 if (image_info->debug != MagickFalse)
2352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2353 image_info->filename);
2354 assert(image != (Image *) NULL);
2355 assert(image->signature == MagickSignature);
2356 if (image_info->blob != (void *) NULL)
2358 if (image_info->stream != (StreamHandler) NULL)
2359 image->blob->stream=(StreamHandler) image_info->stream;
2360 AttachBlob(image->blob,image_info->blob,image_info->length);
2363 (void) DetachBlob(image->blob);
2366 default: type="r"; break;
2367 case ReadBlobMode: type="r"; break;
2368 case ReadBinaryBlobMode: type="rb"; break;
2369 case WriteBlobMode: type="w"; break;
2370 case WriteBinaryBlobMode: type="w+b"; break;
2371 case AppendBlobMode: type="a"; break;
2372 case AppendBinaryBlobMode: type="a+b"; break;
2375 image->blob->synchronize=image_info->synchronize;
2376 if (image_info->stream != (StreamHandler) NULL)
2378 image->blob->stream=(StreamHandler) image_info->stream;
2381 image->blob->type=FifoStream;
2389 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2390 rights=ReadPolicyRights;
2392 rights=WritePolicyRights;
2393 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2396 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2397 "NotAuthorized","`%s'",filename);
2398 return(MagickFalse);
2400 if ((LocaleCompare(filename,"-") == 0) ||
2401 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2403 image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2404 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2405 if (strchr(type,'b') != (char *) NULL)
2406 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2408 image->blob->type=StandardStream;
2409 image->blob->exempt=MagickTrue;
2412 if (LocaleNCompare(filename,"fd:",3) == 0)
2415 mode[MaxTextExtent];
2419 image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2420 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2421 if (strchr(type,'b') != (char *) NULL)
2422 setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2424 image->blob->type=StandardStream;
2425 image->blob->exempt=MagickTrue;
2428 #if defined(MAGICKCORE_HAVE_POPEN)
2429 if (*filename == '|')
2432 mode[MaxTextExtent];
2435 Pipe image to or from a system command.
2437 #if defined(SIGPIPE)
2439 (void) signal(SIGPIPE,SIG_IGN);
2443 image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2444 if (image->blob->file_info.file == (FILE *) NULL)
2446 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2447 return(MagickFalse);
2449 image->blob->type=PipeStream;
2450 image->blob->exempt=MagickTrue;
2454 status=GetPathAttributes(filename,&image->blob->properties);
2455 #if defined(S_ISFIFO)
2456 if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
2458 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2459 if (image->blob->file_info.file == (FILE *) NULL)
2461 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2462 return(MagickFalse);
2464 image->blob->type=FileStream;
2465 image->blob->exempt=MagickTrue;
2469 GetPathComponent(image->filename,ExtensionPath,extension);
2472 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2473 if ((image_info->adjoin == MagickFalse) ||
2474 (strchr(filename,'%') != (char *) NULL))
2477 Form filename for multi-part images.
2479 (void) InterpretImageFilename(image_info,image,image->filename,(int)
2480 image->scene,filename,exception);
2481 if ((LocaleCompare(filename,image->filename) == 0) &&
2482 ((GetPreviousImageInList(image) != (Image *) NULL) ||
2483 (GetNextImageInList(image) != (Image *) NULL)))
2486 path[MaxTextExtent];
2488 GetPathComponent(image->filename,RootPath,path);
2489 if (*extension == '\0')
2490 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
2491 path,(double) image->scene);
2493 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
2494 path,(double) image->scene,extension);
2496 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
2497 #if defined(macintosh)
2498 SetApplicationType(filename,image_info->magick,'8BIM');
2502 if (image_info->file != (FILE *) NULL)
2504 image->blob->file_info.file=image_info->file;
2505 image->blob->type=FileStream;
2506 image->blob->exempt=MagickTrue;
2511 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2512 if (image->blob->file_info.file != (FILE *) NULL)
2520 image->blob->type=FileStream;
2521 #if defined(MAGICKCORE_HAVE_SETVBUF)
2522 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2525 (void) ResetMagickMemory(magick,0,sizeof(magick));
2526 count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2527 (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
2528 (void) fflush(image->blob->file_info.file);
2529 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2530 " read %.20g magic header bytes",(double) count);
2531 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2532 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2533 ((int) magick[2] == 0x08))
2535 (void) fclose(image->blob->file_info.file);
2536 image->blob->file_info.gzfile=gzopen(filename,type);
2537 if (image->blob->file_info.gzfile != (gzFile) NULL)
2538 image->blob->type=ZipStream;
2541 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2542 if (strncmp((char *) magick,"BZh",3) == 0)
2544 (void) fclose(image->blob->file_info.file);
2545 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2546 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2547 image->blob->type=BZipStream;
2550 if (image->blob->type == FileStream)
2561 sans_exception=AcquireExceptionInfo();
2562 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2563 sans_exception=DestroyExceptionInfo(sans_exception);
2564 length=(size_t) image->blob->properties.st_size;
2565 if ((magick_info != (const MagickInfo *) NULL) &&
2566 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2567 (length <= MagickMaxBufferExtent) &&
2568 (AcquireMagickResource(MapResource,length) != MagickFalse))
2573 blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2575 if (blob == (void *) NULL)
2576 RelinquishMagickResource(MapResource,length);
2580 Format supports blobs-- use memory-mapped I/O.
2582 if (image_info->file != (FILE *) NULL)
2583 image->blob->exempt=MagickFalse;
2586 (void) fclose(image->blob->file_info.file);
2587 image->blob->file_info.file=(FILE *) NULL;
2589 AttachBlob(image->blob,blob,length);
2590 image->blob->mapped=MagickTrue;
2597 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2598 if ((LocaleCompare(extension,"Z") == 0) ||
2599 (LocaleCompare(extension,"gz") == 0) ||
2600 (LocaleCompare(extension,"wmz") == 0) ||
2601 (LocaleCompare(extension,"svgz") == 0))
2603 if (mode == WriteBinaryBlobMode)
2605 image->blob->file_info.gzfile=gzopen(filename,type);
2606 if (image->blob->file_info.gzfile != (gzFile) NULL)
2607 image->blob->type=ZipStream;
2611 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2612 if (LocaleCompare(extension,"bz2") == 0)
2614 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2615 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2616 image->blob->type=BZipStream;
2621 image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2622 if (image->blob->file_info.file != (FILE *) NULL)
2624 image->blob->type=FileStream;
2625 #if defined(MAGICKCORE_HAVE_SETVBUF)
2626 (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int)
2631 image->blob->status=MagickFalse;
2632 if (image->blob->type != UndefinedStream)
2633 image->blob->size=GetBlobSize(image);
2636 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2637 return(MagickFalse);
2643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2653 % PingBlob() returns all the attributes of an image or image sequence except
2654 % for the pixels. It is much faster and consumes far less memory than
2655 % BlobToImage(). On failure, a NULL image is returned and exception
2656 % describes the reason for the failure.
2658 % The format of the PingBlob method is:
2660 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
2661 % const size_t length,ExceptionInfo *exception)
2663 % A description of each parameter follows:
2665 % o image_info: the image info.
2667 % o blob: the address of a character stream in one of the image formats
2668 % understood by ImageMagick.
2670 % o length: This size_t integer reflects the length in bytes of the blob.
2672 % o exception: return any errors or warnings in this structure.
2676 #if defined(__cplusplus) || defined(c_plusplus)
2680 static size_t PingStream(const Image *magick_unused(image),
2681 const void *magick_unused(pixels),const size_t columns)
2686 #if defined(__cplusplus) || defined(c_plusplus)
2690 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2691 const size_t length,ExceptionInfo *exception)
2699 assert(image_info != (ImageInfo *) NULL);
2700 assert(image_info->signature == MagickSignature);
2701 if (image_info->debug != MagickFalse)
2702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2703 image_info->filename);
2704 assert(exception != (ExceptionInfo *) NULL);
2705 if ((blob == (const void *) NULL) || (length == 0))
2707 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2708 "UnrecognizedImageFormat","`%s'",image_info->magick);
2709 return((Image *) NULL);
2711 ping_info=CloneImageInfo(image_info);
2712 ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2713 if (ping_info->blob == (const void *) NULL)
2715 (void) ThrowMagickException(exception,GetMagickModule(),
2716 ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2717 return((Image *) NULL);
2719 (void) memcpy(ping_info->blob,blob,length);
2720 ping_info->length=length;
2721 ping_info->ping=MagickTrue;
2722 image=ReadStream(ping_info,&PingStream,exception);
2723 ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2724 ping_info=DestroyImageInfo(ping_info);
2729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2739 % ReadBlob() reads data from the blob or image file and returns it. It
2740 % returns the number of bytes read. If length is zero, ReadBlob() returns
2741 % zero and has no other results. If length is greater than SSIZE_MAX, the
2742 % result is unspecified.
2744 % The format of the ReadBlob method is:
2746 % ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2748 % A description of each parameter follows:
2750 % o image: the image.
2752 % o length: Specifies an integer representing the number of bytes to read
2755 % o data: Specifies an area to place the information requested from the
2759 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2760 unsigned char *data)
2765 register unsigned char
2771 assert(image != (Image *) NULL);
2772 assert(image->signature == MagickSignature);
2773 assert(image->blob != (BlobInfo *) NULL);
2774 assert(image->blob->type != UndefinedStream);
2777 assert(data != (void *) NULL);
2780 switch (image->blob->type)
2782 case UndefinedStream:
2784 case StandardStream:
2789 for (i=0; i < (ssize_t) length; i+=count)
2791 count=read(fileno(image->blob->file_info.file),q+i,(size_t)
2792 MagickMin(length-i,(MagickSizeType) SSIZE_MAX));
2810 count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
2815 c=getc(image->blob->file_info.file);
2818 *q++=(unsigned char) c;
2823 c=getc(image->blob->file_info.file);
2826 *q++=(unsigned char) c;
2836 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2841 count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
2842 (unsigned int) length);
2847 c=gzgetc(image->blob->file_info.gzfile);
2850 *q++=(unsigned char) c;
2855 c=gzgetc(image->blob->file_info.gzfile);
2858 *q++=(unsigned char) c;
2869 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2870 count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
2878 register const unsigned char
2881 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2883 image->blob->eof=MagickTrue;
2886 p=image->blob->data+image->blob->offset;
2887 count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2888 image->blob->offset));
2889 image->blob->offset+=count;
2890 if (count != (ssize_t) length)
2891 image->blob->eof=MagickTrue;
2892 (void) memcpy(q,p,(size_t) count);
2900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2904 + R e a d B l o b B y t e %
2908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2910 % ReadBlobByte() reads a single byte from the image file and returns it.
2912 % The format of the ReadBlobByte method is:
2914 % int ReadBlobByte(Image *image)
2916 % A description of each parameter follows.
2918 % o image: the image.
2921 MagickExport int ReadBlobByte(Image *image)
2923 register const unsigned char
2932 assert(image != (Image *) NULL);
2933 assert(image->signature == MagickSignature);
2934 p=ReadBlobStream(image,1,buffer,&count);
2941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2945 + R e a d B l o b D o u b l e %
2949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2951 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2952 % specified by the endian member of the image structure.
2954 % The format of the ReadBlobDouble method is:
2956 % double ReadBlobDouble(Image *image)
2958 % A description of each parameter follows.
2960 % o image: the image.
2963 MagickExport double ReadBlobDouble(Image *image)
2974 quantum.double_value=0.0;
2975 quantum.unsigned_value=ReadBlobLongLong(image);
2976 return(quantum.double_value);
2980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2984 + R e a d B l o b F l o a t %
2988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2990 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2991 % specified by the endian member of the image structure.
2993 % The format of the ReadBlobFloat method is:
2995 % float ReadBlobFloat(Image *image)
2997 % A description of each parameter follows.
2999 % o image: the image.
3002 MagickExport float ReadBlobFloat(Image *image)
3013 quantum.float_value=0.0;
3014 quantum.unsigned_value=ReadBlobLong(image);
3015 return(quantum.float_value);
3019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3023 + R e a d B l o b L o n g %
3027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3029 % ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
3030 % specified by the endian member of the image structure.
3032 % The format of the ReadBlobLong method is:
3034 % unsigned int ReadBlobLong(Image *image)
3036 % A description of each parameter follows.
3038 % o image: the image.
3041 MagickExport unsigned int ReadBlobLong(Image *image)
3043 register const unsigned char
3055 assert(image != (Image *) NULL);
3056 assert(image->signature == MagickSignature);
3058 p=ReadBlobStream(image,4,buffer,&count);
3061 if (image->endian == LSBEndian)
3063 value=(unsigned int) (*p++);
3064 value|=((unsigned int) (*p++)) << 8;
3065 value|=((unsigned int) (*p++)) << 16;
3066 value|=((unsigned int) (*p++)) << 24;
3069 value=((unsigned int) (*p++)) << 24;
3070 value|=((unsigned int) (*p++)) << 16;
3071 value|=((unsigned int) (*p++)) << 8;
3072 value|=((unsigned int) (*p++));
3077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3081 + R e a d B l o b L o n g L o n g %
3085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3087 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3088 % byte-order specified by the endian member of the image structure.
3090 % The format of the ReadBlobLongLong method is:
3092 % MagickSizeType ReadBlobLongLong(Image *image)
3094 % A description of each parameter follows.
3096 % o image: the image.
3099 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3104 register const unsigned char
3113 assert(image != (Image *) NULL);
3114 assert(image->signature == MagickSignature);
3116 p=ReadBlobStream(image,8,buffer,&count);
3118 return(MagickULLConstant(0));
3119 if (image->endian == LSBEndian)
3121 value=(MagickSizeType) (*p++);
3122 value|=((MagickSizeType) (*p++)) << 8;
3123 value|=((MagickSizeType) (*p++)) << 16;
3124 value|=((MagickSizeType) (*p++)) << 24;
3125 value|=((MagickSizeType) (*p++)) << 32;
3126 value|=((MagickSizeType) (*p++)) << 40;
3127 value|=((MagickSizeType) (*p++)) << 48;
3128 value|=((MagickSizeType) (*p++)) << 56;
3129 return(value & MagickULLConstant(0xffffffffffffffff));
3131 value=((MagickSizeType) (*p++)) << 56;
3132 value|=((MagickSizeType) (*p++)) << 48;
3133 value|=((MagickSizeType) (*p++)) << 40;
3134 value|=((MagickSizeType) (*p++)) << 32;
3135 value|=((MagickSizeType) (*p++)) << 24;
3136 value|=((MagickSizeType) (*p++)) << 16;
3137 value|=((MagickSizeType) (*p++)) << 8;
3138 value|=((MagickSizeType) (*p++));
3139 return(value & MagickULLConstant(0xffffffffffffffff));
3143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3147 + R e a d B l o b S h o r t %
3151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3153 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3154 % specified by the endian member of the image structure.
3156 % The format of the ReadBlobShort method is:
3158 % unsigned short ReadBlobShort(Image *image)
3160 % A description of each parameter follows.
3162 % o image: the image.
3165 MagickExport unsigned short ReadBlobShort(Image *image)
3167 register const unsigned char
3170 register unsigned int
3179 assert(image != (Image *) NULL);
3180 assert(image->signature == MagickSignature);
3182 p=ReadBlobStream(image,2,buffer,&count);
3184 return((unsigned short) 0U);
3185 if (image->endian == LSBEndian)
3187 value=(unsigned int) (*p++);
3188 value|=((unsigned int) (*p++)) << 8;
3189 return((unsigned short) (value & 0xffff));
3191 value=(unsigned int) ((*p++) << 8);
3192 value|=(unsigned int) (*p++);
3193 return((unsigned short) (value & 0xffff));
3197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3201 + R e a d B l o b L S B L o n g %
3205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3207 % ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
3208 % least-significant byte first order.
3210 % The format of the ReadBlobLSBLong method is:
3212 % unsigned int ReadBlobLSBLong(Image *image)
3214 % A description of each parameter follows.
3216 % o image: the image.
3219 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3221 register const unsigned char
3224 register unsigned int
3233 assert(image != (Image *) NULL);
3234 assert(image->signature == MagickSignature);
3236 p=ReadBlobStream(image,4,buffer,&count);
3239 value=(unsigned int) (*p++);
3240 value|=((unsigned int) (*p++)) << 8;
3241 value|=((unsigned int) (*p++)) << 16;
3242 value|=((unsigned int) (*p++)) << 24;
3247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3251 + R e a d B l o b L S B S h o r t %
3255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3257 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3258 % least-significant byte first order.
3260 % The format of the ReadBlobLSBShort method is:
3262 % unsigned short ReadBlobLSBShort(Image *image)
3264 % A description of each parameter follows.
3266 % o image: the image.
3269 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3271 register const unsigned char
3274 register unsigned int
3283 assert(image != (Image *) NULL);
3284 assert(image->signature == MagickSignature);
3286 p=ReadBlobStream(image,2,buffer,&count);
3288 return((unsigned short) 0U);
3289 value=(unsigned int) (*p++);
3290 value|=((unsigned int) ((*p++)) << 8);
3291 return((unsigned short) (value & 0xffff));
3295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3299 + R e a d B l o b M S B L o n g %
3303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3305 % ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
3306 % most-significant byte first order.
3308 % The format of the ReadBlobMSBLong method is:
3310 % unsigned int ReadBlobMSBLong(Image *image)
3312 % A description of each parameter follows.
3314 % o image: the image.
3317 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3319 register const unsigned char
3322 register unsigned int
3331 assert(image != (Image *) NULL);
3332 assert(image->signature == MagickSignature);
3334 p=ReadBlobStream(image,4,buffer,&count);
3337 value=((unsigned int) (*p++) << 24);
3338 value|=((unsigned int) (*p++) << 16);
3339 value|=((unsigned int) (*p++) << 8);
3340 value|=(unsigned int) (*p++);
3345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3349 + R e a d B l o b M S B L o n g L o n g %
3353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3355 % ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
3356 % most-significant byte first order.
3358 % The format of the ReadBlobMSBLongLong method is:
3360 % unsigned int ReadBlobMSBLongLong(Image *image)
3362 % A description of each parameter follows.
3364 % o image: the image.
3367 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3369 register const unsigned char
3372 register MagickSizeType
3381 assert(image != (Image *) NULL);
3382 assert(image->signature == MagickSignature);
3384 p=ReadBlobStream(image,8,buffer,&count);
3386 return(MagickULLConstant(0));
3387 value=((MagickSizeType) (*p++)) << 56;
3388 value|=((MagickSizeType) (*p++)) << 48;
3389 value|=((MagickSizeType) (*p++)) << 40;
3390 value|=((MagickSizeType) (*p++)) << 32;
3391 value|=((MagickSizeType) (*p++)) << 24;
3392 value|=((MagickSizeType) (*p++)) << 16;
3393 value|=((MagickSizeType) (*p++)) << 8;
3394 value|=((MagickSizeType) (*p++));
3395 return(value & MagickULLConstant(0xffffffffffffffff));
3399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3403 + R e a d B l o b M S B S h o r t %
3407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3409 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3410 % most-significant byte first order.
3412 % The format of the ReadBlobMSBShort method is:
3414 % unsigned short ReadBlobMSBShort(Image *image)
3416 % A description of each parameter follows.
3418 % o image: the image.
3421 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3423 register const unsigned char
3426 register unsigned int
3435 assert(image != (Image *) NULL);
3436 assert(image->signature == MagickSignature);
3438 p=ReadBlobStream(image,2,buffer,&count);
3440 return((unsigned short) 0U);
3441 value=(unsigned int) ((*p++) << 8);
3442 value|=(unsigned int) (*p++);
3443 return((unsigned short) (value & 0xffff));
3447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3451 + R e a d B l o b S t r i n g %
3455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3457 % ReadBlobString() reads characters from a blob or file until a newline
3458 % character is read or an end-of-file condition is encountered.
3460 % The format of the ReadBlobString method is:
3462 % char *ReadBlobString(Image *image,char *string)
3464 % A description of each parameter follows:
3466 % o image: the image.
3468 % o string: the address of a character buffer.
3471 MagickExport char *ReadBlobString(Image *image,char *string)
3473 register const unsigned char
3485 assert(image != (Image *) NULL);
3486 assert(image->signature == MagickSignature);
3487 for (i=0; i < (MaxTextExtent-1L); i++)
3489 p=ReadBlobStream(image,1,buffer,&count);
3493 return((char *) NULL);
3496 string[i]=(char) (*p);
3497 if ((string[i] == '\r') || (string[i] == '\n'))
3500 if (string[i] == '\r')
3501 (void) ReadBlobStream(image,1,buffer,&count);
3507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3511 + R e f e r e n c e B l o b %
3515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3517 % ReferenceBlob() increments the reference count associated with the pixel
3518 % blob returning a pointer to the blob.
3520 % The format of the ReferenceBlob method is:
3522 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
3524 % A description of each parameter follows:
3526 % o blob_info: the blob_info.
3529 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3531 assert(blob != (BlobInfo *) NULL);
3532 assert(blob->signature == MagickSignature);
3533 if (blob->debug != MagickFalse)
3534 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3535 LockSemaphoreInfo(blob->semaphore);
3536 blob->reference_count++;
3537 UnlockSemaphoreInfo(blob->semaphore);
3542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3552 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
3553 % and returns the resulting offset.
3555 % The format of the SeekBlob method is:
3557 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3560 % A description of each parameter follows:
3562 % o image: the image.
3564 % o offset: Specifies an integer representing the offset in bytes.
3566 % o whence: Specifies an integer representing how the offset is
3567 % treated relative to the beginning of the blob as follows:
3569 % SEEK_SET Set position equal to offset bytes.
3570 % SEEK_CUR Set position to current location plus offset.
3571 % SEEK_END Set position to EOF plus offset.
3574 MagickExport MagickOffsetType SeekBlob(Image *image,
3575 const MagickOffsetType offset,const int whence)
3577 assert(image != (Image *) NULL);
3578 assert(image->signature == MagickSignature);
3579 if (image->debug != MagickFalse)
3580 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3581 assert(image->blob != (BlobInfo *) NULL);
3582 assert(image->blob->type != UndefinedStream);
3583 switch (image->blob->type)
3585 case UndefinedStream:
3587 case StandardStream:
3591 if (fseek(image->blob->file_info.file,offset,whence) < 0)
3593 image->blob->offset=TellBlob(image);
3599 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3600 if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
3603 image->blob->offset=TellBlob(image);
3619 image->blob->offset=offset;
3624 if ((image->blob->offset+offset) < 0)
3626 image->blob->offset+=offset;
3631 if (((MagickOffsetType) image->blob->length+offset) < 0)
3633 image->blob->offset=image->blob->length+offset;
3637 if (image->blob->offset <= (MagickOffsetType)
3638 ((off_t) image->blob->length))
3639 image->blob->eof=MagickFalse;
3641 if (image->blob->mapped != MagickFalse)
3645 image->blob->extent=(size_t) (image->blob->offset+
3646 image->blob->quantum);
3647 image->blob->data=(unsigned char *) ResizeQuantumMemory(
3648 image->blob->data,image->blob->extent+1,
3649 sizeof(*image->blob->data));
3650 (void) SyncBlob(image);
3651 if (image->blob->data == (unsigned char *) NULL)
3653 (void) DetachBlob(image->blob);
3660 return(image->blob->offset);
3664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3668 + S e t B l o b E x e m p t %
3672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3674 % SetBlobExempt() sets the blob exempt status.
3676 % The format of the SetBlobExempt method is:
3678 % MagickBooleanType SetBlobExempt(const Image *image,
3679 % const MagickBooleanType exempt)
3681 % A description of each parameter follows:
3683 % o image: the image.
3685 % o exempt: Set to true if this blob is exempt from being closed.
3688 MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3690 assert(image != (const Image *) NULL);
3691 assert(image->signature == MagickSignature);
3692 if (image->debug != MagickFalse)
3693 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3694 image->blob->exempt=exempt;
3698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3702 + S e t B l o b E x t e n t %
3706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3708 % SetBlobExtent() ensures enough space is allocated for the blob. If the
3709 % method is successful, subsequent writes to bytes in the specified range are
3710 % guaranteed not to fail.
3712 % The format of the SetBlobExtent method is:
3714 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3716 % A description of each parameter follows:
3718 % o image: the image.
3720 % o extent: the blob maximum extent.
3723 MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
3724 const MagickSizeType extent)
3726 assert(image != (Image *) NULL);
3727 assert(image->signature == MagickSignature);
3728 if (image->debug != MagickFalse)
3729 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3730 assert(image->blob != (BlobInfo *) NULL);
3731 assert(image->blob->type != UndefinedStream);
3732 switch (image->blob->type)
3734 case UndefinedStream:
3736 case StandardStream:
3737 return(MagickFalse);
3746 if (extent != (MagickSizeType) ((off_t) extent))
3747 return(MagickFalse);
3748 offset=SeekBlob(image,0,SEEK_END);
3750 return(MagickFalse);
3751 if ((MagickSizeType) offset >= extent)
3753 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3754 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3755 image->blob->file_info.file);
3756 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3757 if (image->blob->synchronize != MagickFalse)
3762 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3765 return(MagickFalse);
3768 offset=SeekBlob(image,offset,SEEK_SET);
3770 return(MagickFalse);
3775 return(MagickFalse);
3777 return(MagickFalse);
3779 return(MagickFalse);
3782 if (extent != (MagickSizeType) ((size_t) extent))
3783 return(MagickFalse);
3784 if (image->blob->mapped != MagickFalse)
3792 (void) UnmapBlob(image->blob->data,image->blob->length);
3793 RelinquishMagickResource(MapResource,image->blob->length);
3794 if (extent != (MagickSizeType) ((off_t) extent))
3795 return(MagickFalse);
3796 offset=SeekBlob(image,0,SEEK_END);
3798 return(MagickFalse);
3799 if ((MagickSizeType) offset >= extent)
3801 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
3802 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
3803 image->blob->file_info.file);
3804 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3805 if (image->blob->synchronize != MagickFalse)
3810 status=posix_fallocate(fileno(image->blob->file_info.file),offset,
3813 return(MagickFalse);
3816 offset=SeekBlob(image,offset,SEEK_SET);
3818 return(MagickFalse);
3819 (void) AcquireMagickResource(MapResource,extent);
3820 image->blob->data=(unsigned char*) MapBlob(fileno(
3821 image->blob->file_info.file),WriteMode,0,(size_t) extent);
3822 image->blob->extent=(size_t) extent;
3823 image->blob->length=(size_t) extent;
3824 (void) SyncBlob(image);
3827 image->blob->extent=(size_t) extent;
3828 image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3829 image->blob->extent+1,sizeof(*image->blob->data));
3830 (void) SyncBlob(image);
3831 if (image->blob->data == (unsigned char *) NULL)
3833 (void) DetachBlob(image->blob);
3834 return(MagickFalse);
3843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3853 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
3854 % attributes if it is an blob.
3856 % The format of the SyncBlob method is:
3858 % int SyncBlob(Image *image)
3860 % A description of each parameter follows:
3862 % o image: the image.
3865 static int SyncBlob(Image *image)
3870 assert(image != (Image *) NULL);
3871 assert(image->signature == MagickSignature);
3872 if (image->debug != MagickFalse)
3873 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3874 assert(image->blob != (BlobInfo *) NULL);
3875 assert(image->blob->type != UndefinedStream);
3877 switch (image->blob->type)
3879 case UndefinedStream:
3880 case StandardStream:
3885 status=fflush(image->blob->file_info.file);
3890 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3891 status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
3897 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3898 status=BZ2_bzflush(image->blob->file_info.bzfile);
3911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3921 % TellBlob() obtains the current value of the blob or file position.
3923 % The format of the TellBlob method is:
3925 % MagickOffsetType TellBlob(const Image *image)
3927 % A description of each parameter follows:
3929 % o image: the image.
3932 MagickExport MagickOffsetType TellBlob(const Image *image)
3937 assert(image != (Image *) NULL);
3938 assert(image->signature == MagickSignature);
3939 if (image->debug != MagickFalse)
3940 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3941 assert(image->blob != (BlobInfo *) NULL);
3942 assert(image->blob->type != UndefinedStream);
3944 switch (image->blob->type)
3946 case UndefinedStream:
3947 case StandardStream:
3951 offset=ftell(image->blob->file_info.file);
3958 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3959 offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
3969 offset=image->blob->offset;
3977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3981 + U n m a p B l o b %
3985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3987 % UnmapBlob() deallocates the binary large object previously allocated with
3988 % the MapBlob method.
3990 % The format of the UnmapBlob method is:
3992 % MagickBooleanType UnmapBlob(void *map,const size_t length)
3994 % A description of each parameter follows:
3996 % o map: the address of the binary large object.
3998 % o length: the length of the binary large object.
4001 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4003 #if defined(MAGICKCORE_HAVE_MMAP)
4007 status=munmap(map,length);
4008 return(status == -1 ? MagickFalse : MagickTrue);
4012 return(MagickFalse);
4017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4021 + W r i t e B l o b %
4025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4027 % WriteBlob() writes data to a blob or image file. It returns the number of
4030 % The format of the WriteBlob method is:
4032 % ssize_t WriteBlob(Image *image,const size_t length,
4033 % const unsigned char *data)
4035 % A description of each parameter follows:
4037 % o image: the image.
4039 % o length: Specifies an integer representing the number of bytes to
4040 % write to the file.
4042 % o data: The address of the data to write to the blob or file.
4045 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4046 const unsigned char *data)
4051 register const unsigned char
4057 assert(image != (Image *) NULL);
4058 assert(image->signature == MagickSignature);
4059 assert(data != (const unsigned char *) NULL);
4060 assert(image->blob != (BlobInfo *) NULL);
4061 assert(image->blob->type != UndefinedStream);
4066 switch (image->blob->type)
4068 case UndefinedStream:
4070 case StandardStream:
4072 count=write(fileno(image->blob->file_info.file),data,length);
4082 count=(ssize_t) fwrite((const char *) data,1,length,
4083 image->blob->file_info.file);
4088 c=putc((int) *p++,image->blob->file_info.file);
4095 c=putc((int) *p++,image->blob->file_info.file);
4107 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4112 count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
4113 (unsigned int) length);
4118 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4125 c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4138 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4139 count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
4146 count=(ssize_t) image->blob->stream(image,data,length);
4151 register unsigned char
4154 if ((image->blob->offset+(MagickOffsetType) length) >=
4155 (MagickOffsetType) image->blob->extent)
4157 if (image->blob->mapped != MagickFalse)
4159 image->blob->quantum<<=1;
4160 image->blob->extent+=length+image->blob->quantum;
4161 image->blob->data=(unsigned char *) ResizeQuantumMemory(
4162 image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4163 (void) SyncBlob(image);
4164 if (image->blob->data == (unsigned char *) NULL)
4166 (void) DetachBlob(image->blob);
4170 q=image->blob->data+image->blob->offset;
4171 (void) memcpy(q,p,length);
4172 image->blob->offset+=length;
4173 if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4174 image->blob->length=(size_t) image->blob->offset;
4175 count=(ssize_t) length;
4182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4186 + W r i t e B l o b B y t e %
4190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4192 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
4193 % written (either 0 or 1);
4195 % The format of the WriteBlobByte method is:
4197 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
4199 % A description of each parameter follows.
4201 % o image: the image.
4203 % o value: Specifies the value to write.
4206 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4208 assert(image != (Image *) NULL);
4209 assert(image->signature == MagickSignature);
4210 return(WriteBlobStream(image,1,&value));
4214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4218 + W r i t e B l o b F l o a t %
4222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4224 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4225 % specified by the endian member of the image structure.
4227 % The format of the WriteBlobFloat method is:
4229 % ssize_t WriteBlobFloat(Image *image,const float value)
4231 % A description of each parameter follows.
4233 % o image: the image.
4235 % o value: Specifies the value to write.
4238 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4249 quantum.unsigned_value=0U;
4250 quantum.float_value=value;
4251 return(WriteBlobLong(image,quantum.unsigned_value));
4255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4259 + W r i t e B l o b L o n g %
4263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4265 % WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
4266 % specified by the endian member of the image structure.
4268 % The format of the WriteBlobLong method is:
4270 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
4272 % A description of each parameter follows.
4274 % o image: the image.
4276 % o value: Specifies the value to write.
4279 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4284 assert(image != (Image *) NULL);
4285 assert(image->signature == MagickSignature);
4286 if (image->endian == LSBEndian)
4288 buffer[0]=(unsigned char) value;
4289 buffer[1]=(unsigned char) (value >> 8);
4290 buffer[2]=(unsigned char) (value >> 16);
4291 buffer[3]=(unsigned char) (value >> 24);
4292 return(WriteBlobStream(image,4,buffer));
4294 buffer[0]=(unsigned char) (value >> 24);
4295 buffer[1]=(unsigned char) (value >> 16);
4296 buffer[2]=(unsigned char) (value >> 8);
4297 buffer[3]=(unsigned char) value;
4298 return(WriteBlobStream(image,4,buffer));
4302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4306 + W r i t e B l o b S h o r t %
4310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4312 % WriteBlobShort() writes a short value as a 16-bit quantity in the
4313 % byte-order specified by the endian member of the image structure.
4315 % The format of the WriteBlobShort method is:
4317 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
4319 % A description of each parameter follows.
4321 % o image: the image.
4323 % o value: Specifies the value to write.
4326 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4331 assert(image != (Image *) NULL);
4332 assert(image->signature == MagickSignature);
4333 if (image->endian == LSBEndian)
4335 buffer[0]=(unsigned char) value;
4336 buffer[1]=(unsigned char) (value >> 8);
4337 return(WriteBlobStream(image,2,buffer));
4339 buffer[0]=(unsigned char) (value >> 8);
4340 buffer[1]=(unsigned char) value;
4341 return(WriteBlobStream(image,2,buffer));
4345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4349 + W r i t e B l o b L S B L o n g %
4353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4355 % WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
4356 % least-significant byte first order.
4358 % The format of the WriteBlobLSBLong method is:
4360 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4362 % A description of each parameter follows.
4364 % o image: the image.
4366 % o value: Specifies the value to write.
4369 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4374 assert(image != (Image *) NULL);
4375 assert(image->signature == MagickSignature);
4376 buffer[0]=(unsigned char) value;
4377 buffer[1]=(unsigned char) (value >> 8);
4378 buffer[2]=(unsigned char) (value >> 16);
4379 buffer[3]=(unsigned char) (value >> 24);
4380 return(WriteBlobStream(image,4,buffer));
4384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4388 + W r i t e B l o b L S B S h o r t %
4392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4394 % WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
4395 % least-significant byte first order.
4397 % The format of the WriteBlobLSBShort method is:
4399 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4401 % A description of each parameter follows.
4403 % o image: the image.
4405 % o value: Specifies the value to write.
4408 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4413 assert(image != (Image *) NULL);
4414 assert(image->signature == MagickSignature);
4415 buffer[0]=(unsigned char) value;
4416 buffer[1]=(unsigned char) (value >> 8);
4417 return(WriteBlobStream(image,2,buffer));
4421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4425 + W r i t e B l o b M S B L o n g %
4429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4431 % WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
4432 % most-significant byte first order.
4434 % The format of the WriteBlobMSBLong method is:
4436 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4438 % A description of each parameter follows.
4440 % o value: Specifies the value to write.
4442 % o image: the image.
4445 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4450 assert(image != (Image *) NULL);
4451 assert(image->signature == MagickSignature);
4452 buffer[0]=(unsigned char) (value >> 24);
4453 buffer[1]=(unsigned char) (value >> 16);
4454 buffer[2]=(unsigned char) (value >> 8);
4455 buffer[3]=(unsigned char) value;
4456 return(WriteBlobStream(image,4,buffer));
4460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4464 + W r i t e B l o b M S B L o n g L o n g %
4468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4470 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4471 % most-significant byte first order.
4473 % The format of the WriteBlobMSBLongLong method is:
4475 % ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4477 % A description of each parameter follows.
4479 % o value: Specifies the value to write.
4481 % o image: the image.
4484 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4485 const MagickSizeType value)
4490 assert(image != (Image *) NULL);
4491 assert(image->signature == MagickSignature);
4492 buffer[0]=(unsigned char) (value >> 56);
4493 buffer[1]=(unsigned char) (value >> 48);
4494 buffer[2]=(unsigned char) (value >> 40);
4495 buffer[3]=(unsigned char) (value >> 32);
4496 buffer[4]=(unsigned char) (value >> 24);
4497 buffer[5]=(unsigned char) (value >> 16);
4498 buffer[6]=(unsigned char) (value >> 8);
4499 buffer[7]=(unsigned char) value;
4500 return(WriteBlobStream(image,8,buffer));
4504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4508 + W r i t e B l o b M S B S h o r t %
4512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4514 % WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
4515 % most-significant byte first order.
4517 % The format of the WriteBlobMSBShort method is:
4519 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4521 % A description of each parameter follows.
4523 % o value: Specifies the value to write.
4525 % o file: Specifies the file to write the data to.
4528 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4533 assert(image != (Image *) NULL);
4534 assert(image->signature == MagickSignature);
4535 buffer[0]=(unsigned char) (value >> 8);
4536 buffer[1]=(unsigned char) value;
4537 return(WriteBlobStream(image,2,buffer));
4541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4545 + W r i t e B l o b S t r i n g %
4549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4551 % WriteBlobString() write a string to a blob. It returns the number of
4552 % characters written.
4554 % The format of the WriteBlobString method is:
4556 % ssize_t WriteBlobString(Image *image,const char *string)
4558 % A description of each parameter follows.
4560 % o image: the image.
4562 % o string: Specifies the string to write.
4565 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4567 assert(image != (Image *) NULL);
4568 assert(image->signature == MagickSignature);
4569 assert(string != (const char *) NULL);
4570 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));