MagickCore 7.1.1-43
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
blob.c
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% BBBB L OOO BBBB %
7% B B L O O B B %
8% BBBB L O O BBBB %
9% B B L O O B B %
10% BBBB LLLLL OOO BBBB %
11% %
12% %
13% MagickCore Binary Large OBjectS Methods %
14% %
15% Software Design %
16% Cristy %
17% July 1999 %
18% %
19% %
20% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% https://imagemagick.org/script/license.php %
27% %
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. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39␌
40/*
41 Include declarations.
42*/
43#ifdef __VMS
44#include <types.h>
45#include <mman.h>
46#endif
47#include "MagickCore/studio.h"
48#include "MagickCore/blob.h"
49#include "MagickCore/blob-private.h"
50#include "MagickCore/cache.h"
51#include "MagickCore/client.h"
52#include "MagickCore/constitute.h"
53#include "MagickCore/delegate.h"
54#include "MagickCore/exception.h"
55#include "MagickCore/exception-private.h"
56#include "MagickCore/geometry.h"
57#include "MagickCore/image-private.h"
58#include "MagickCore/list.h"
59#include "MagickCore/locale_.h"
60#include "MagickCore/log.h"
61#include "MagickCore/magick.h"
62#include "MagickCore/memory_.h"
63#include "MagickCore/memory-private.h"
64#include "MagickCore/nt-base-private.h"
65#include "MagickCore/option.h"
66#include "MagickCore/policy.h"
67#include "MagickCore/resource_.h"
68#include "MagickCore/semaphore.h"
69#include "MagickCore/string_.h"
70#include "MagickCore/string-private.h"
71#include "MagickCore/timer-private.h"
72#include "MagickCore/token.h"
73#include "MagickCore/utility.h"
74#include "MagickCore/utility-private.h"
75#if defined(MAGICKCORE_ZLIB_DELEGATE)
76#include "zlib.h"
77#endif
78#if defined(MAGICKCORE_BZLIB_DELEGATE)
79#include "bzlib.h"
80#endif
81#include "MagickCore/policy-private.h"
82␌
83/*
84 Define declarations.
85*/
86#define MagickMaxBlobExtent (8*8192)
87#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
88# define MAP_ANONYMOUS MAP_ANON
89#endif
90#if !defined(MAP_FAILED)
91#define MAP_FAILED ((void *) -1)
92#endif
93#if defined(__OS2__)
94#include <io.h>
95#define _O_BINARY O_BINARY
96#endif
97#if defined(MAGICKCORE_WINDOWS_SUPPORT)
98# if !defined(fsync)
99# define fsync _commit
100# endif
101# if !defined(mmap)
102# define MAGICKCORE_HAVE_MMAP 1
103# define mmap(address,length,protection,access,file,offset) \
104 NTMapMemory(address,length,protection,access,file,offset)
105# endif
106# if !defined(munmap)
107# define munmap(address,length) NTUnmapMemory(address,length)
108# endif
109# if !defined(pclose)
110# define pclose _pclose
111# endif
112# if !defined(popen)
113# define popen _popen
114# endif
115#endif
116␌
117/*
118 Typedef declarations.
119*/
120typedef union FileInfo
121{
122 FILE
123 *file;
124
125#if defined(MAGICKCORE_ZLIB_DELEGATE)
126 gzFile
127 gzfile;
128#endif
129
130#if defined(MAGICKCORE_BZLIB_DELEGATE)
131 BZFILE
132 *bzfile;
133#endif
134} FileInfo;
135
137{
138 size_t
139 length,
140 extent,
141 quantum;
142
143 BlobMode
144 mode;
145
146 MagickBooleanType
147 mapped,
148 eof;
149
150 int
151 error,
152 error_number;
153
154 MagickOffsetType
155 offset;
156
157 MagickSizeType
158 size;
159
160 MagickBooleanType
161 exempt,
162 synchronize,
163 temporary;
164
165 int
166 status;
167
168 StreamType
169 type;
170
172 file_info;
173
174 struct stat
175 properties;
176
177 StreamHandler
178 stream;
179
181 *custom_stream;
182
183 unsigned char
184 *data;
185
186 MagickBooleanType
187 debug;
188
190 *semaphore;
191
192 ssize_t
193 reference_count;
194
195 size_t
196 signature;
197};
198
200{
201 CustomStreamHandler
202 reader,
203 writer;
204
205 CustomStreamSeeker
206 seeker;
207
208 CustomStreamTeller
209 teller;
210
211 void
212 *data;
213
214 size_t
215 signature;
216};
217␌
218/*
219 Forward declarations.
220*/
221static int
222 SyncBlob(const Image *);
223␌
224/*
225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226% %
227% %
228% %
229+ A c q u i r e C u s t o m S t r e a m I n f o %
230% %
231% %
232% %
233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234%
235% AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
236%
237% The format of the AcquireCustomStreamInfo method is:
238%
239% CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
240%
241% A description of each parameter follows:
242%
243% o exception: return any errors or warnings in this structure.
244%
245*/
246MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
247 ExceptionInfo *magick_unused(exception))
248{
250 *custom_stream;
251
252 magick_unreferenced(exception);
253 custom_stream=(CustomStreamInfo *) AcquireCriticalMemory(
254 sizeof(*custom_stream));
255 (void) memset(custom_stream,0,sizeof(*custom_stream));
256 custom_stream->signature=MagickCoreSignature;
257 return(custom_stream);
258}
259␌
260/*
261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262% %
263% %
264% %
265+ A t t a c h B l o b %
266% %
267% %
268% %
269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270%
271% AttachBlob() attaches a blob to the BlobInfo structure.
272%
273% The format of the AttachBlob method is:
274%
275% void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
276%
277% A description of each parameter follows:
278%
279% o blob_info: Specifies a pointer to a BlobInfo structure.
280%
281% o blob: the address of a character stream in one of the image formats
282% understood by ImageMagick.
283%
284% o length: This size_t integer reflects the length in bytes of the blob.
285%
286*/
287MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
288 const size_t length)
289{
290 assert(blob_info != (BlobInfo *) NULL);
291 if (IsEventLogging() != MagickFalse)
292 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
293 blob_info->length=length;
294 blob_info->extent=length;
295 blob_info->quantum=(size_t) MagickMaxBlobExtent;
296 blob_info->offset=0;
297 blob_info->type=BlobStream;
298 blob_info->file_info.file=(FILE *) NULL;
299 blob_info->data=(unsigned char *) blob;
300 blob_info->mapped=MagickFalse;
301}
302␌
303/*
304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305% %
306% %
307% %
308+ A t t a c h C u s t o m S t r e a m %
309% %
310% %
311% %
312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313%
314% AttachCustomStream() attaches a CustomStreamInfo to the BlobInfo structure.
315%
316% The format of the AttachCustomStream method is:
317%
318% void AttachCustomStream(BlobInfo *blob_info,
319% CustomStreamInfo *custom_stream)
320%
321% A description of each parameter follows:
322%
323% o blob_info: specifies a pointer to a BlobInfo structure.
324%
325% o custom_stream: the custom stream info.
326%
327*/
328MagickExport void AttachCustomStream(BlobInfo *blob_info,
329 CustomStreamInfo *custom_stream)
330{
331 assert(blob_info != (BlobInfo *) NULL);
332 assert(custom_stream != (CustomStreamInfo *) NULL);
333 assert(custom_stream->signature == MagickCoreSignature);
334 if (IsEventLogging() != MagickFalse)
335 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
336 blob_info->type=CustomStream;
337 blob_info->custom_stream=custom_stream;
338}
339␌
340/*
341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342% %
343% %
344% %
345+ B l o b T o F i l e %
346% %
347% %
348% %
349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350%
351% BlobToFile() writes a blob to a file. It returns MagickFalse if an error
352% occurs otherwise MagickTrue.
353%
354% The format of the BlobToFile method is:
355%
356% MagickBooleanType BlobToFile(char *filename,const void *blob,
357% const size_t length,ExceptionInfo *exception)
358%
359% A description of each parameter follows:
360%
361% o filename: Write the blob to this file.
362%
363% o blob: the address of a blob.
364%
365% o length: This length in bytes of the blob.
366%
367% o exception: return any errors or warnings in this structure.
368%
369*/
370MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
371 const size_t length,ExceptionInfo *exception)
372{
373 int
374 file;
375
376 size_t
377 i;
378
379 ssize_t
380 count;
381
382 assert(filename != (const char *) NULL);
383 assert(blob != (const void *) NULL);
384 if (IsEventLogging() != MagickFalse)
385 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
386 if (*filename == '\0')
387 file=AcquireUniqueFileResource(filename);
388 else
389 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
390 if (file == -1)
391 {
392 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
393 return(MagickFalse);
394 }
395 for (i=0; i < length; i+=(size_t) count)
396 {
397 count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
398 MagickMaxBufferExtent));
399 if (count <= 0)
400 {
401 count=0;
402 if (errno != EINTR)
403 break;
404 }
405 }
406 file=close_utf8(file);
407 if ((file == -1) || (i < length))
408 {
409 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
410 return(MagickFalse);
411 }
412 return(MagickTrue);
413}
414␌
415/*
416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417% %
418% %
419% %
420% B l o b T o I m a g e %
421% %
422% %
423% %
424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425%
426% BlobToImage() implements direct to memory image formats. It returns the
427% blob as an image.
428%
429% The format of the BlobToImage method is:
430%
431% Image *BlobToImage(const ImageInfo *image_info,const void *blob,
432% const size_t length,ExceptionInfo *exception)
433%
434% A description of each parameter follows:
435%
436% o image_info: the image info.
437%
438% o blob: the address of a character stream in one of the image formats
439% understood by ImageMagick.
440%
441% o length: This size_t integer reflects the length in bytes of the blob.
442%
443% o exception: return any errors or warnings in this structure.
444%
445*/
446MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
447 const size_t length,ExceptionInfo *exception)
448{
449 const MagickInfo
450 *magick_info;
451
452 Image
453 *image;
454
456 *blob_info,
457 *clone_info;
458
459 MagickBooleanType
460 status;
461
462 assert(image_info != (ImageInfo *) NULL);
463 assert(image_info->signature == MagickCoreSignature);
464 assert(exception != (ExceptionInfo *) NULL);
465 if (IsEventLogging() != MagickFalse)
466 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
467 image_info->filename);
468 if ((blob == (const void *) NULL) || (length == 0))
469 {
470 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
471 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
472 return((Image *) NULL);
473 }
474 blob_info=CloneImageInfo(image_info);
475 blob_info->blob=(void *) blob;
476 blob_info->length=length;
477 if (*blob_info->magick == '\0')
478 (void) SetImageInfo(blob_info,0,exception);
479 magick_info=GetMagickInfo(blob_info->magick,exception);
480 if (magick_info == (const MagickInfo *) NULL)
481 {
482 (void) ThrowMagickException(exception,GetMagickModule(),
483 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
484 blob_info->magick);
485 blob_info=DestroyImageInfo(blob_info);
486 return((Image *) NULL);
487 }
488 if (GetMagickBlobSupport(magick_info) != MagickFalse)
489 {
490 char
491 filename[MagickPathExtent];
492
493 /*
494 Native blob support for this image format.
495 */
496 (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
497 (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
498 blob_info->magick,filename);
499 image=ReadImage(blob_info,exception);
500 if (image != (Image *) NULL)
501 (void) DetachBlob(image->blob);
502 blob_info=DestroyImageInfo(blob_info);
503 return(image);
504 }
505 /*
506 Write blob to a temporary file on disk.
507 */
508 blob_info->blob=(void *) NULL;
509 blob_info->length=0;
510 *blob_info->filename='\0';
511 status=BlobToFile(blob_info->filename,blob,length,exception);
512 if (status == MagickFalse)
513 {
514 (void) RelinquishUniqueFileResource(blob_info->filename);
515 blob_info=DestroyImageInfo(blob_info);
516 return((Image *) NULL);
517 }
518 clone_info=CloneImageInfo(blob_info);
519 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
520 blob_info->magick,blob_info->filename);
521 image=ReadImage(clone_info,exception);
522 if (image != (Image *) NULL)
523 {
524 Image
525 *images;
526
527 /*
528 Restore original filenames and image format.
529 */
530 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
531 {
532 (void) CopyMagickString(images->filename,image_info->filename,
533 MagickPathExtent);
534 (void) CopyMagickString(images->magick_filename,image_info->filename,
535 MagickPathExtent);
536 (void) CopyMagickString(images->magick,magick_info->name,
537 MagickPathExtent);
538 images=GetNextImageInList(images);
539 }
540 }
541 clone_info=DestroyImageInfo(clone_info);
542 (void) RelinquishUniqueFileResource(blob_info->filename);
543 blob_info=DestroyImageInfo(blob_info);
544 return(image);
545}
546␌
547/*
548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549% %
550% %
551% %
552+ C l o n e B l o b I n f o %
553% %
554% %
555% %
556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557%
558% CloneBlobInfo() makes a duplicate of the given blob info structure, or if
559% blob info is NULL, a new one.
560%
561% The format of the CloneBlobInfo method is:
562%
563% BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
564%
565% A description of each parameter follows:
566%
567% o blob_info: the blob info.
568%
569*/
570MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
571{
573 *clone_info;
574
576 *semaphore;
577
578 clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
579 GetBlobInfo(clone_info);
580 if (blob_info == (BlobInfo *) NULL)
581 return(clone_info);
582 semaphore=clone_info->semaphore;
583 (void) memcpy(clone_info,blob_info,sizeof(*clone_info));
584 if (blob_info->mapped != MagickFalse)
585 (void) AcquireMagickResource(MapResource,blob_info->length);
586 clone_info->semaphore=semaphore;
587 LockSemaphoreInfo(clone_info->semaphore);
588 clone_info->reference_count=1;
589 UnlockSemaphoreInfo(clone_info->semaphore);
590 return(clone_info);
591}
592␌
593/*
594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595% %
596% %
597% %
598+ C l o s e B l o b %
599% %
600% %
601% %
602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603%
604% CloseBlob() closes a stream associated with the image.
605%
606% The format of the CloseBlob method is:
607%
608% MagickBooleanType CloseBlob(Image *image)
609%
610% A description of each parameter follows:
611%
612% o image: the image.
613%
614*/
615
616static inline void ThrowBlobException(BlobInfo *blob_info)
617{
618 if ((blob_info->status == 0) && (errno != 0))
619 blob_info->error_number=errno;
620 blob_info->status=(-1);
621}
622
623MagickExport MagickBooleanType CloseBlob(Image *image)
624{
626 *magick_restrict blob_info;
627
628 int
629 status;
630
631 /*
632 Close image file.
633 */
634 assert(image != (Image *) NULL);
635 assert(image->signature == MagickCoreSignature);
636 if (IsEventLogging() != MagickFalse)
637 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
638 blob_info=image->blob;
639 if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
640 return(MagickTrue);
641 (void) SyncBlob(image);
642 status=blob_info->status;
643 switch (blob_info->type)
644 {
645 case UndefinedStream:
646 break;
647 case StandardStream:
648 case FileStream:
649 case PipeStream:
650 {
651 if (blob_info->synchronize != MagickFalse)
652 {
653 status=fflush(blob_info->file_info.file);
654 if (status != 0)
655 ThrowBlobException(blob_info);
656 status=fsync(fileno(blob_info->file_info.file));
657 if (status != 0)
658 ThrowBlobException(blob_info);
659 }
660 if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
661 ThrowBlobException(blob_info);
662 break;
663 }
664 case ZipStream:
665 {
666#if defined(MAGICKCORE_ZLIB_DELEGATE)
667 status=Z_OK;
668 (void) gzerror(blob_info->file_info.gzfile,&status);
669 if (status != Z_OK)
670 ThrowBlobException(blob_info);
671#endif
672 break;
673 }
674 case BZipStream:
675 {
676#if defined(MAGICKCORE_BZLIB_DELEGATE)
677 status=BZ_OK;
678 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
679 if (status != BZ_OK)
680 ThrowBlobException(blob_info);
681#endif
682 break;
683 }
684 case FifoStream:
685 break;
686 case BlobStream:
687 {
688 if (blob_info->file_info.file != (FILE *) NULL)
689 {
690 if (blob_info->synchronize != MagickFalse)
691 {
692 status=fflush(blob_info->file_info.file);
693 if (status != 0)
694 ThrowBlobException(blob_info);
695 status=fsync(fileno(blob_info->file_info.file));
696 if (status != 0)
697 ThrowBlobException(blob_info);
698 }
699 if ((status != 0) && (ferror(blob_info->file_info.file) != 0))
700 ThrowBlobException(blob_info);
701 }
702 break;
703 }
704 case CustomStream:
705 break;
706 }
707 blob_info->size=GetBlobSize(image);
708 image->extent=blob_info->size;
709 blob_info->eof=MagickFalse;
710 blob_info->error=0;
711 blob_info->mode=UndefinedBlobMode;
712 if (blob_info->exempt != MagickFalse)
713 {
714 blob_info->type=UndefinedStream;
715 return(blob_info->status != 0 ? MagickFalse : MagickTrue);
716 }
717 switch (blob_info->type)
718 {
719 case UndefinedStream:
720 case StandardStream:
721 break;
722 case FileStream:
723 {
724 if (blob_info->file_info.file != (FILE *) NULL)
725 {
726 status=fclose(blob_info->file_info.file);
727 if (status != 0)
728 ThrowBlobException(blob_info);
729 }
730 break;
731 }
732 case PipeStream:
733 {
734#if defined(MAGICKCORE_HAVE_PCLOSE)
735 status=pclose(blob_info->file_info.file);
736 if (status != 0)
737 ThrowBlobException(blob_info);
738#endif
739 break;
740 }
741 case ZipStream:
742 {
743#if defined(MAGICKCORE_ZLIB_DELEGATE)
744 status=gzclose(blob_info->file_info.gzfile);
745 if (status != Z_OK)
746 ThrowBlobException(blob_info);
747#endif
748 break;
749 }
750 case BZipStream:
751 {
752#if defined(MAGICKCORE_BZLIB_DELEGATE)
753 BZ2_bzclose(blob_info->file_info.bzfile);
754#endif
755 break;
756 }
757 case FifoStream:
758 break;
759 case BlobStream:
760 {
761 if (blob_info->file_info.file != (FILE *) NULL)
762 {
763 status=fclose(blob_info->file_info.file);
764 if (status != 0)
765 ThrowBlobException(blob_info);
766 }
767 break;
768 }
769 case CustomStream:
770 break;
771 }
772 (void) DetachBlob(blob_info);
773 return(blob_info->status != 0 ? MagickFalse : MagickTrue);
774}
775␌
776/*
777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
778% %
779% %
780% %
781% C u s t o m S t r e a m T o I m a g e %
782% %
783% %
784% %
785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
786%
787% CustomStreamToImage() is the equivalent of ReadImage(), but reads the
788% formatted "file" from the supplied method rather than to an actual file.
789%
790% The format of the CustomStreamToImage method is:
791%
792% Image *CustomStreamToImage(const ImageInfo *image_info,
793% ExceptionInfo *exception)
794%
795% A description of each parameter follows:
796%
797% o image_info: the image info.
798%
799% o exception: return any errors or warnings in this structure.
800%
801*/
802MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
803 ExceptionInfo *exception)
804{
805 const MagickInfo
806 *magick_info;
807
808 Image
809 *image;
810
812 *blob_info;
813
814 assert(image_info != (ImageInfo *) NULL);
815 assert(image_info->signature == MagickCoreSignature);
816 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
817 assert(image_info->custom_stream->signature == MagickCoreSignature);
818 assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
819 assert(exception != (ExceptionInfo *) NULL);
820 if (IsEventLogging() != MagickFalse)
821 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
822 image_info->filename);
823 blob_info=CloneImageInfo(image_info);
824 if (*blob_info->magick == '\0')
825 (void) SetImageInfo(blob_info,0,exception);
826 magick_info=GetMagickInfo(blob_info->magick,exception);
827 if (magick_info == (const MagickInfo *) NULL)
828 {
829 (void) ThrowMagickException(exception,GetMagickModule(),
830 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
831 blob_info->magick);
832 blob_info=DestroyImageInfo(blob_info);
833 return((Image *) NULL);
834 }
835 image=(Image *) NULL;
836 if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
837 (*blob_info->filename != '\0'))
838 {
839 char
840 filename[MagickPathExtent];
841
842 /*
843 Native blob support for this image format or SetImageInfo changed the
844 blob to a file.
845 */
846 (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
847 (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
848 blob_info->magick,filename);
849 image=ReadImage(blob_info,exception);
850 }
851 else
852 {
853 char
854 unique[MagickPathExtent];
855
856 int
857 file;
858
860 *clone_info;
861
862 unsigned char
863 *blob;
864
865 /*
866 Write data to file on disk.
867 */
868 blob_info->custom_stream=(CustomStreamInfo *) NULL;
869 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
870 sizeof(*blob));
871 if (blob == (unsigned char *) NULL)
872 {
873 ThrowFileException(exception,BlobError,"UnableToReadBlob",
874 image_info->filename);
875 blob_info=DestroyImageInfo(blob_info);
876 return((Image *) NULL);
877 }
878 file=AcquireUniqueFileResource(unique);
879 if (file == -1)
880 {
881 ThrowFileException(exception,BlobError,"UnableToReadBlob",
882 image_info->filename);
883 blob=(unsigned char *) RelinquishMagickMemory(blob);
884 blob_info=DestroyImageInfo(blob_info);
885 return((Image *) NULL);
886 }
887 clone_info=CloneImageInfo(blob_info);
888 blob_info->file=fdopen(file,"wb+");
889 if (blob_info->file != (FILE *) NULL)
890 {
891 ssize_t
892 count;
893
894 count=(ssize_t) MagickMaxBufferExtent;
895 while (count == (ssize_t) MagickMaxBufferExtent)
896 {
897 count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
898 image_info->custom_stream->data);
899 if (count > 0)
900 count=(ssize_t) write(file,(const char *) blob,(size_t) count);
901 }
902 (void) fclose(blob_info->file);
903 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
904 "%s:%s",blob_info->magick,unique);
905 image=ReadImage(clone_info,exception);
906 if (image != (Image *) NULL)
907 {
908 Image
909 *images;
910
911 /*
912 Restore original filenames and image format.
913 */
914 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
915 {
916 (void) CopyMagickString(images->filename,image_info->filename,
917 MagickPathExtent);
918 (void) CopyMagickString(images->magick_filename,
919 image_info->filename,MagickPathExtent);
920 (void) CopyMagickString(images->magick,magick_info->name,
921 MagickPathExtent);
922 images=GetNextImageInList(images);
923 }
924 }
925 }
926 clone_info=DestroyImageInfo(clone_info);
927 blob=(unsigned char *) RelinquishMagickMemory(blob);
928 (void) RelinquishUniqueFileResource(unique);
929 }
930 blob_info=DestroyImageInfo(blob_info);
931 if (image != (Image *) NULL)
932 if (CloseBlob(image) == MagickFalse)
933 image=DestroyImageList(image);
934 return(image);
935}
936␌
937/*
938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939% %
940% %
941% %
942+ D e s t r o y B l o b %
943% %
944% %
945% %
946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947%
948% DestroyBlob() deallocates memory associated with a blob.
949%
950% The format of the DestroyBlob method is:
951%
952% void DestroyBlob(Image *image)
953%
954% A description of each parameter follows:
955%
956% o image: the image.
957%
958*/
959MagickExport void DestroyBlob(Image *image)
960{
962 *magick_restrict blob_info;
963
964 MagickBooleanType
965 destroy;
966
967 assert(image != (Image *) NULL);
968 assert(image->signature == MagickCoreSignature);
969 assert(image->blob != (BlobInfo *) NULL);
970 assert(image->blob->signature == MagickCoreSignature);
971 if (IsEventLogging() != MagickFalse)
972 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
973 blob_info=image->blob;
974 destroy=MagickFalse;
975 LockSemaphoreInfo(blob_info->semaphore);
976 blob_info->reference_count--;
977 assert(blob_info->reference_count >= 0);
978 if (blob_info->reference_count == 0)
979 destroy=MagickTrue;
980 UnlockSemaphoreInfo(blob_info->semaphore);
981 if (destroy == MagickFalse)
982 {
983 image->blob=(BlobInfo *) NULL;
984 return;
985 }
986 (void) CloseBlob(image);
987 if (blob_info->mapped != MagickFalse)
988 {
989 (void) UnmapBlob(blob_info->data,blob_info->length);
990 RelinquishMagickResource(MapResource,blob_info->length);
991 }
992 if (blob_info->semaphore != (SemaphoreInfo *) NULL)
993 RelinquishSemaphoreInfo(&blob_info->semaphore);
994 blob_info->signature=(~MagickCoreSignature);
995 image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
996}
997␌
998/*
999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000% %
1001% %
1002% %
1003+ D e s t r o y C u s t o m S t r e a m I n f o %
1004% %
1005% %
1006% %
1007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008%
1009% DestroyCustomStreamInfo() destroys memory associated with the
1010% CustomStreamInfo structure.
1011%
1012% The format of the DestroyCustomStreamInfo method is:
1013%
1014% CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
1015%
1016% A description of each parameter follows:
1017%
1018% o custom_stream: the custom stream info.
1019%
1020*/
1021MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
1022 CustomStreamInfo *custom_stream)
1023{
1024 assert(custom_stream != (CustomStreamInfo *) NULL);
1025 assert(custom_stream->signature == MagickCoreSignature);
1026 if (IsEventLogging() != MagickFalse)
1027 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1028 custom_stream->signature=(~MagickCoreSignature);
1029 custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
1030 return(custom_stream);
1031}
1032␌
1033/*
1034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035% %
1036% %
1037% %
1038+ D e t a c h B l o b %
1039% %
1040% %
1041% %
1042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043%
1044% DetachBlob() detaches a blob from the BlobInfo structure.
1045%
1046% The format of the DetachBlob method is:
1047%
1048% void *DetachBlob(BlobInfo *blob_info)
1049%
1050% A description of each parameter follows:
1051%
1052% o blob_info: Specifies a pointer to a BlobInfo structure.
1053%
1054*/
1055MagickExport void *DetachBlob(BlobInfo *blob_info)
1056{
1057 void
1058 *data;
1059
1060 assert(blob_info != (BlobInfo *) NULL);
1061 if (IsEventLogging() != MagickFalse)
1062 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1063 if (blob_info->mapped != MagickFalse)
1064 {
1065 (void) UnmapBlob(blob_info->data,blob_info->length);
1066 blob_info->data=NULL;
1067 RelinquishMagickResource(MapResource,blob_info->length);
1068 }
1069 blob_info->mapped=MagickFalse;
1070 blob_info->length=0;
1071 /*
1072 We should not reset blob_info->extent because we use it to check if the
1073 blob was opened inside ImagesToBlob and ImagesToBlob.
1074 */
1075 blob_info->offset=0;
1076 blob_info->mode=UndefinedBlobMode;
1077 blob_info->eof=MagickFalse;
1078 blob_info->error=0;
1079 blob_info->exempt=MagickFalse;
1080 blob_info->type=UndefinedStream;
1081 blob_info->file_info.file=(FILE *) NULL;
1082 data=blob_info->data;
1083 blob_info->data=(unsigned char *) NULL;
1084 blob_info->stream=(StreamHandler) NULL;
1085 blob_info->custom_stream=(CustomStreamInfo *) NULL;
1086 return(data);
1087}
1088␌
1089/*
1090%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091% %
1092% %
1093% %
1094+ D i s a s s o c i a t e B l o b %
1095% %
1096% %
1097% %
1098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1099%
1100% DisassociateBlob() disassociates the image stream. It checks if the
1101% blob of the specified image is referenced by other images. If the reference
1102% count is higher then 1 a new blob is assigned to the specified image.
1103%
1104% The format of the DisassociateBlob method is:
1105%
1106% void DisassociateBlob(const Image *image)
1107%
1108% A description of each parameter follows:
1109%
1110% o image: the image.
1111%
1112*/
1113MagickExport void DisassociateBlob(Image *image)
1114{
1115 BlobInfo
1116 *magick_restrict blob_info,
1117 *clone_info;
1118
1119 MagickBooleanType
1120 clone;
1121
1122 assert(image != (Image *) NULL);
1123 assert(image->signature == MagickCoreSignature);
1124 assert(image->blob != (BlobInfo *) NULL);
1125 assert(image->blob->signature == MagickCoreSignature);
1126 if (IsEventLogging() != MagickFalse)
1127 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1128 blob_info=image->blob;
1129 clone=MagickFalse;
1130 LockSemaphoreInfo(blob_info->semaphore);
1131 assert(blob_info->reference_count >= 0);
1132 if (blob_info->reference_count > 1)
1133 clone=MagickTrue;
1134 UnlockSemaphoreInfo(blob_info->semaphore);
1135 if (clone == MagickFalse)
1136 return;
1137 clone_info=CloneBlobInfo(blob_info);
1138 DestroyBlob(image);
1139 image->blob=clone_info;
1140}
1141␌
1142/*
1143%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1144% %
1145% %
1146% %
1147+ D i s c a r d B l o b B y t e s %
1148% %
1149% %
1150% %
1151%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1152%
1153% DiscardBlobBytes() discards bytes in a blob.
1154%
1155% The format of the DiscardBlobBytes method is:
1156%
1157% MagickBooleanType DiscardBlobBytes(Image *image,
1158% const MagickSizeType length)
1159%
1160% A description of each parameter follows.
1161%
1162% o image: the image.
1163%
1164% o length: the number of bytes to skip.
1165%
1166*/
1167MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
1168 const MagickSizeType length)
1169{
1170 MagickSizeType
1171 i;
1172
1173 size_t
1174 quantum;
1175
1176 ssize_t
1177 count;
1178
1179 unsigned char
1180 buffer[MagickMinBufferExtent >> 1];
1181
1182 assert(image != (Image *) NULL);
1183 assert(image->signature == MagickCoreSignature);
1184 if (length != (MagickSizeType) ((MagickOffsetType) length))
1185 return(MagickFalse);
1186 count=0;
1187 for (i=0; i < length; i+=(MagickSizeType) count)
1188 {
1189 quantum=(size_t) MagickMin(length-i,sizeof(buffer));
1190 (void) ReadBlobStream(image,quantum,buffer,&count);
1191 if (count <= 0)
1192 {
1193 count=0;
1194 if (errno != EINTR)
1195 break;
1196 }
1197 }
1198 return(i < (MagickSizeType) length ? MagickFalse : MagickTrue);
1199}
1200␌
1201/*
1202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203% %
1204% %
1205% %
1206+ D u p l i c a t e s B l o b %
1207% %
1208% %
1209% %
1210%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1211%
1212% DuplicateBlob() duplicates a blob descriptor.
1213%
1214% The format of the DuplicateBlob method is:
1215%
1216% void DuplicateBlob(Image *image,const Image *duplicate)
1217%
1218% A description of each parameter follows:
1219%
1220% o image: the image.
1221%
1222% o duplicate: the duplicate image.
1223%
1224*/
1225MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
1226{
1227 assert(image != (Image *) NULL);
1228 assert(image->signature == MagickCoreSignature);
1229 assert(duplicate != (Image *) NULL);
1230 assert(duplicate->signature == MagickCoreSignature);
1231 if (IsEventLogging() != MagickFalse)
1232 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1233 DestroyBlob(image);
1234 image->blob=ReferenceBlob(duplicate->blob);
1235}
1236␌
1237/*
1238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1239% %
1240% %
1241% %
1242+ E O F B l o b %
1243% %
1244% %
1245% %
1246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1247%
1248% EOFBlob() returns a non-zero value when EOF has been detected reading from
1249% a blob or file.
1250%
1251% The format of the EOFBlob method is:
1252%
1253% int EOFBlob(const Image *image)
1254%
1255% A description of each parameter follows:
1256%
1257% o image: the image.
1258%
1259*/
1260MagickExport int EOFBlob(const Image *image)
1261{
1262 BlobInfo
1263 *magick_restrict blob_info;
1264
1265 assert(image != (Image *) NULL);
1266 assert(image->signature == MagickCoreSignature);
1267 assert(image->blob != (BlobInfo *) NULL);
1268 assert(image->blob->type != UndefinedStream);
1269 if (IsEventLogging() != MagickFalse)
1270 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1271 blob_info=image->blob;
1272 switch (blob_info->type)
1273 {
1274 case UndefinedStream:
1275 case StandardStream:
1276 break;
1277 case FileStream:
1278 case PipeStream:
1279 {
1280 blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
1281 MagickFalse;
1282 break;
1283 }
1284 case ZipStream:
1285 {
1286#if defined(MAGICKCORE_ZLIB_DELEGATE)
1287 blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
1288 MagickFalse;
1289#endif
1290 break;
1291 }
1292 case BZipStream:
1293 {
1294#if defined(MAGICKCORE_BZLIB_DELEGATE)
1295 int
1296 status;
1297
1298 status=0;
1299 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
1300 if (status == BZ_UNEXPECTED_EOF)
1301 blob_info->eof=MagickTrue;
1302#endif
1303 break;
1304 }
1305 case FifoStream:
1306 {
1307 blob_info->eof=MagickFalse;
1308 break;
1309 }
1310 case BlobStream:
1311 break;
1312 case CustomStream:
1313 break;
1314 }
1315 return((int) blob_info->eof);
1316}
1317␌
1318/*
1319%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1320% %
1321% %
1322% %
1323+ E r r o r B l o b %
1324% %
1325% %
1326% %
1327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1328%
1329% ErrorBlob() returns a non-zero value when an error has been detected reading
1330% from a blob or file.
1331%
1332% The format of the ErrorBlob method is:
1333%
1334% int ErrorBlob(const Image *image)
1335%
1336% A description of each parameter follows:
1337%
1338% o image: the image.
1339%
1340*/
1341MagickExport int ErrorBlob(const Image *image)
1342{
1343 BlobInfo
1344 *magick_restrict blob_info;
1345
1346 assert(image != (Image *) NULL);
1347 assert(image->signature == MagickCoreSignature);
1348 assert(image->blob != (BlobInfo *) NULL);
1349 assert(image->blob->type != UndefinedStream);
1350 if (IsEventLogging() != MagickFalse)
1351 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1352 blob_info=image->blob;
1353 switch (blob_info->type)
1354 {
1355 case UndefinedStream:
1356 case StandardStream:
1357 break;
1358 case FileStream:
1359 case PipeStream:
1360 {
1361 blob_info->error=ferror(blob_info->file_info.file);
1362 break;
1363 }
1364 case ZipStream:
1365 {
1366#if defined(MAGICKCORE_ZLIB_DELEGATE)
1367 (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1368#endif
1369 break;
1370 }
1371 case BZipStream:
1372 {
1373#if defined(MAGICKCORE_BZLIB_DELEGATE)
1374 (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1375#endif
1376 break;
1377 }
1378 case FifoStream:
1379 {
1380 blob_info->error=0;
1381 break;
1382 }
1383 case BlobStream:
1384 break;
1385 case CustomStream:
1386 break;
1387 }
1388 return(blob_info->error);
1389}
1390␌
1391/*
1392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1393% %
1394% %
1395% %
1396% F i l e T o B l o b %
1397% %
1398% %
1399% %
1400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1401%
1402% FileToBlob() returns the contents of a file as a buffer terminated with
1403% the '\0' character. The length of the buffer (not including the extra
1404% terminating '\0' character) is returned via the 'length' parameter. Free
1405% the buffer with RelinquishMagickMemory().
1406%
1407% The format of the FileToBlob method is:
1408%
1409% void *FileToBlob(const char *filename,const size_t extent,
1410% size_t *length,ExceptionInfo *exception)
1411%
1412% A description of each parameter follows:
1413%
1414% o blob: FileToBlob() returns the contents of a file as a blob. If
1415% an error occurs NULL is returned.
1416%
1417% o filename: the filename.
1418%
1419% o extent: The maximum length of the blob.
1420%
1421% o length: On return, this reflects the actual length of the blob.
1422%
1423% o exception: return any errors or warnings in this structure.
1424%
1425*/
1426MagickExport void *FileToBlob(const char *filename,const size_t extent,
1427 size_t *length,ExceptionInfo *exception)
1428{
1429 int
1430 file;
1431
1432 MagickBooleanType
1433 status;
1434
1435 MagickOffsetType
1436 offset;
1437
1438 size_t
1439 i;
1440
1441 ssize_t
1442 count;
1443
1444 struct stat
1445 attributes;
1446
1447 unsigned char
1448 *blob;
1449
1450 void
1451 *map;
1452
1453 assert(filename != (const char *) NULL);
1454 assert(exception != (ExceptionInfo *) NULL);
1455 assert(exception->signature == MagickCoreSignature);
1456 if (IsEventLogging() != MagickFalse)
1457 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1458 *length=0;
1459 status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1460 if (status == MagickFalse)
1461 {
1462 errno=EPERM;
1463 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1464 "NotAuthorized","`%s'",filename);
1465 return(NULL);
1466 }
1467 file=fileno(stdin);
1468 if (LocaleCompare(filename,"-") != 0)
1469 {
1470 int
1471 flags = O_RDONLY | O_BINARY;
1472
1473 status=GetPathAttributes(filename,&attributes);
1474 if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1475 {
1476 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1477 return(NULL);
1478 }
1479#if defined(O_NOFOLLOW)
1480 status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights,"follow");
1481 if (status == MagickFalse)
1482 flags|=O_NOFOLLOW;
1483#endif
1484 file=open_utf8(filename,flags,0);
1485 }
1486 if (file == -1)
1487 {
1488 ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1489 return(NULL);
1490 }
1491 status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1492 if (status == MagickFalse)
1493 {
1494 file=close_utf8(file)-1;
1495 errno=EPERM;
1496 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1497 "NotAuthorized","`%s'",filename);
1498 return(NULL);
1499 }
1500 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1501 count=0;
1502 if ((file == fileno(stdin)) || (offset < 0) ||
1503 (offset != (MagickOffsetType) ((ssize_t) offset)))
1504 {
1505 size_t
1506 quantum;
1507
1508 struct stat
1509 file_stats;
1510
1511 /*
1512 Stream is not seekable.
1513 */
1514 offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1515 quantum=(size_t) MagickMaxBufferExtent;
1516 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1517 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1518 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1519 for (i=0; blob != (unsigned char *) NULL; i+=(size_t) count)
1520 {
1521 count=read(file,blob+i,quantum);
1522 if (count <= 0)
1523 {
1524 count=0;
1525 if (errno != EINTR)
1526 break;
1527 }
1528 if (~i < ((size_t) count+quantum+1))
1529 {
1530 blob=(unsigned char *) RelinquishMagickMemory(blob);
1531 break;
1532 }
1533 blob=(unsigned char *) ResizeQuantumMemory(blob,i+(size_t) count+
1534 quantum+1,sizeof(*blob));
1535 if ((i+(size_t) count) >= extent)
1536 break;
1537 }
1538 if (LocaleCompare(filename,"-") != 0)
1539 file=close_utf8(file);
1540 if (blob == (unsigned char *) NULL)
1541 {
1542 (void) ThrowMagickException(exception,GetMagickModule(),
1543 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1544 return(NULL);
1545 }
1546 if (file == -1)
1547 {
1548 blob=(unsigned char *) RelinquishMagickMemory(blob);
1549 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1550 return(NULL);
1551 }
1552 *length=(size_t) MagickMin(i+(size_t) count,extent);
1553 blob[*length]='\0';
1554 return(blob);
1555 }
1556 *length=(size_t) MagickMin(offset,(MagickOffsetType)
1557 MagickMin(extent,(size_t) MAGICK_SSIZE_MAX));
1558 blob=(unsigned char *) NULL;
1559 if (~(*length) >= (MagickPathExtent-1))
1560 blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1561 sizeof(*blob));
1562 if (blob == (unsigned char *) NULL)
1563 {
1564 file=close_utf8(file);
1565 (void) ThrowMagickException(exception,GetMagickModule(),
1566 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1567 return(NULL);
1568 }
1569 map=MapBlob(file,ReadMode,0,*length);
1570 if (map != (unsigned char *) NULL)
1571 {
1572 (void) memcpy(blob,map,*length);
1573 (void) UnmapBlob(map,*length);
1574 }
1575 else
1576 {
1577 (void) lseek(file,0,SEEK_SET);
1578 for (i=0; i < *length; i+=(size_t) count)
1579 {
1580 count=read(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
1581 MagickMaxBufferExtent));
1582 if (count <= 0)
1583 {
1584 count=0;
1585 if (errno != EINTR)
1586 break;
1587 }
1588 }
1589 if (i < *length)
1590 {
1591 file=close_utf8(file)-1;
1592 blob=(unsigned char *) RelinquishMagickMemory(blob);
1593 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1594 return(NULL);
1595 }
1596 }
1597 blob[*length]='\0';
1598 if (LocaleCompare(filename,"-") != 0)
1599 file=close_utf8(file);
1600 if (file == -1)
1601 {
1602 blob=(unsigned char *) RelinquishMagickMemory(blob);
1603 ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1604 }
1605 return(blob);
1606}
1607␌
1608/*
1609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1610% %
1611% %
1612% %
1613% F i l e T o I m a g e %
1614% %
1615% %
1616% %
1617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1618%
1619% FileToImage() write the contents of a file to an image.
1620%
1621% The format of the FileToImage method is:
1622%
1623% MagickBooleanType FileToImage(Image *,const char *filename)
1624%
1625% A description of each parameter follows:
1626%
1627% o image: the image.
1628%
1629% o filename: the filename.
1630%
1631*/
1632static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1633 const void *magick_restrict data)
1634{
1635 BlobInfo
1636 *magick_restrict blob_info;
1637
1638 MagickSizeType
1639 extent;
1640
1641 unsigned char
1642 *magick_restrict q;
1643
1644 assert(image->blob != (BlobInfo *) NULL);
1645 assert(image->blob->type != UndefinedStream);
1646 assert(data != NULL);
1647 blob_info=image->blob;
1648 if (blob_info->type != BlobStream)
1649 return(WriteBlob(image,length,(const unsigned char *) data));
1650 extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1651 if (extent >= blob_info->extent)
1652 {
1653 extent+=blob_info->quantum+length;
1654 blob_info->quantum<<=1;
1655 if (SetBlobExtent(image,extent) == MagickFalse)
1656 return(0);
1657 }
1658 q=blob_info->data+blob_info->offset;
1659 (void) memcpy(q,data,length);
1660 blob_info->offset+=(MagickOffsetType) length;
1661 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1662 blob_info->length=(size_t) blob_info->offset;
1663 return((ssize_t) length);
1664}
1665
1666MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1667 ExceptionInfo *exception)
1668{
1669 int
1670 file;
1671
1672 MagickBooleanType
1673 status;
1674
1675 size_t
1676 length,
1677 quantum;
1678
1679 ssize_t
1680 count;
1681
1682 struct stat
1683 file_stats;
1684
1685 unsigned char
1686 *blob;
1687
1688 assert(image != (const Image *) NULL);
1689 assert(image->signature == MagickCoreSignature);
1690 assert(filename != (const char *) NULL);
1691 if (IsEventLogging() != MagickFalse)
1692 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1693 status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1694 if (status == MagickFalse)
1695 {
1696 errno=EPERM;
1697 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1698 "NotAuthorized","`%s'",filename);
1699 return(MagickFalse);
1700 }
1701 file=fileno(stdin);
1702 if (LocaleCompare(filename,"-") != 0)
1703 {
1704 int
1705 flags = O_RDONLY | O_BINARY;
1706
1707#if defined(O_NOFOLLOW)
1708 status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights,"follow");
1709 if (status == MagickFalse)
1710 flags|=O_NOFOLLOW;
1711#endif
1712 file=open_utf8(filename,flags,0);
1713 }
1714 if (file == -1)
1715 {
1716 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1717 return(MagickFalse);
1718 }
1719 status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1720 if (status == MagickFalse)
1721 {
1722 file=close_utf8(file);
1723 errno=EPERM;
1724 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1725 "NotAuthorized","`%s'",filename);
1726 return(MagickFalse);
1727 }
1728 quantum=(size_t) MagickMaxBufferExtent;
1729 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1730 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1731 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1732 if (blob == (unsigned char *) NULL)
1733 {
1734 file=close_utf8(file);
1735 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1736 filename);
1737 return(MagickFalse);
1738 }
1739 for ( ; ; )
1740 {
1741 count=read(file,blob,quantum);
1742 if (count <= 0)
1743 {
1744 count=0;
1745 if (errno != EINTR)
1746 break;
1747 }
1748 length=(size_t) count;
1749 count=WriteBlobStream(image,length,blob);
1750 if (count != (ssize_t) length)
1751 {
1752 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1753 break;
1754 }
1755 }
1756 file=close_utf8(file);
1757 if (file == -1)
1758 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1759 blob=(unsigned char *) RelinquishMagickMemory(blob);
1760 return(MagickTrue);
1761}
1762␌
1763/*
1764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1765% %
1766% %
1767% %
1768+ G e t B l o b E r r o r %
1769% %
1770% %
1771% %
1772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773%
1774% GetBlobError() returns MagickTrue if the blob associated with the specified
1775% image encountered an error.
1776%
1777% The format of the GetBlobError method is:
1778%
1779% MagickBooleanType GetBlobError(const Image *image)
1780%
1781% A description of each parameter follows:
1782%
1783% o image: the image.
1784%
1785*/
1786MagickExport MagickBooleanType GetBlobError(const Image *image)
1787{
1788 assert(image != (const Image *) NULL);
1789 assert(image->signature == MagickCoreSignature);
1790 if (IsEventLogging() != MagickFalse)
1791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1792 if ((image->blob->status != 0) && (image->blob->error_number != 0))
1793 errno=image->blob->error_number;
1794 return(image->blob->status == 0 ? MagickFalse : MagickTrue);
1795}
1796␌
1797/*
1798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1799% %
1800% %
1801% %
1802+ G e t B l o b F i l e H a n d l e %
1803% %
1804% %
1805% %
1806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1807%
1808% GetBlobFileHandle() returns the stdio file handle associated with the image
1809% blob. If the blob is not backed by a FILE object, NULL is returned.
1810%
1811% The format of the GetBlobFile method is:
1812%
1813% FILE *GetBlobFileHandle(const Image *image)
1814%
1815% A description of each parameter follows:
1816%
1817% o image: the image.
1818%
1819*/
1820MagickExport FILE *GetBlobFileHandle(const Image *image)
1821{
1822 assert(image != (const Image *) NULL);
1823 assert(image->signature == MagickCoreSignature);
1824 assert(image->blob != (BlobInfo *) NULL);
1825 assert(image->blob->signature == MagickCoreSignature);
1826 switch (image->blob->type)
1827 {
1828 case StandardStream:
1829 case FileStream:
1830 case PipeStream:
1831 return(image->blob->file_info.file);
1832 case UndefinedStream:
1833 case ZipStream:
1834 case BZipStream:
1835 case FifoStream:
1836 case BlobStream:
1837 case CustomStream:
1838 break;
1839 }
1840 return((FILE *) NULL);
1841}
1842␌
1843/*
1844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1845% %
1846% %
1847% %
1848+ G e t B l o b I n f o %
1849% %
1850% %
1851% %
1852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1853%
1854% GetBlobInfo() initializes the BlobInfo structure.
1855%
1856% The format of the GetBlobInfo method is:
1857%
1858% void GetBlobInfo(BlobInfo *blob_info)
1859%
1860% A description of each parameter follows:
1861%
1862% o blob_info: Specifies a pointer to a BlobInfo structure.
1863%
1864*/
1865MagickExport void GetBlobInfo(BlobInfo *blob_info)
1866{
1867 assert(blob_info != (BlobInfo *) NULL);
1868 (void) memset(blob_info,0,sizeof(*blob_info));
1869 blob_info->type=UndefinedStream;
1870 blob_info->quantum=(size_t) MagickMaxBlobExtent;
1871 blob_info->properties.st_mtime=GetMagickTime();
1872 blob_info->properties.st_ctime=blob_info->properties.st_mtime;
1873 blob_info->debug=GetLogEventMask() & BlobEvent ? MagickTrue : MagickFalse;
1874 blob_info->reference_count=1;
1875 blob_info->semaphore=AcquireSemaphoreInfo();
1876 blob_info->signature=MagickCoreSignature;
1877}
1878␌
1879/*
1880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1881% %
1882% %
1883% %
1884% G e t B l o b P r o p e r t i e s %
1885% %
1886% %
1887% %
1888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1889%
1890% GetBlobProperties() returns information about an image blob.
1891%
1892% The format of the GetBlobProperties method is:
1893%
1894% const struct stat *GetBlobProperties(const Image *image)
1895%
1896% A description of each parameter follows:
1897%
1898% o image: the image.
1899%
1900*/
1901MagickExport const struct stat *GetBlobProperties(const Image *image)
1902{
1903 assert(image != (Image *) NULL);
1904 assert(image->signature == MagickCoreSignature);
1905 if (IsEventLogging() != MagickFalse)
1906 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1907 return(&image->blob->properties);
1908}
1909␌
1910/*
1911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1912% %
1913% %
1914% %
1915+ G e t B l o b S i z e %
1916% %
1917% %
1918% %
1919%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1920%
1921% GetBlobSize() returns the current length of the image file or blob; zero is
1922% returned if the size cannot be determined.
1923%
1924% The format of the GetBlobSize method is:
1925%
1926% MagickSizeType GetBlobSize(const Image *image)
1927%
1928% A description of each parameter follows:
1929%
1930% o image: the image.
1931%
1932*/
1933MagickExport MagickSizeType GetBlobSize(const Image *image)
1934{
1935 BlobInfo
1936 *magick_restrict blob_info;
1937
1938 MagickSizeType
1939 extent;
1940
1941 assert(image != (Image *) NULL);
1942 assert(image->signature == MagickCoreSignature);
1943 assert(image->blob != (BlobInfo *) NULL);
1944 if (IsEventLogging() != MagickFalse)
1945 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1946 blob_info=image->blob;
1947 extent=0;
1948 switch (blob_info->type)
1949 {
1950 case UndefinedStream:
1951 case StandardStream:
1952 {
1953 extent=blob_info->size;
1954 break;
1955 }
1956 case FileStream:
1957 {
1958 int
1959 file_descriptor;
1960
1961 extent=(MagickSizeType) blob_info->properties.st_size;
1962 if (extent == 0)
1963 extent=blob_info->size;
1964 file_descriptor=fileno(blob_info->file_info.file);
1965 if (file_descriptor == -1)
1966 break;
1967 if (fstat(file_descriptor,&blob_info->properties) == 0)
1968 extent=(MagickSizeType) blob_info->properties.st_size;
1969 break;
1970 }
1971 case PipeStream:
1972 {
1973 extent=blob_info->size;
1974 break;
1975 }
1976 case ZipStream:
1977 case BZipStream:
1978 {
1979 MagickBooleanType
1980 status;
1981
1982 status=GetPathAttributes(image->filename,&blob_info->properties);
1983 if (status != MagickFalse)
1984 extent=(MagickSizeType) blob_info->properties.st_size;
1985 break;
1986 }
1987 case FifoStream:
1988 break;
1989 case BlobStream:
1990 {
1991 extent=(MagickSizeType) blob_info->length;
1992 break;
1993 }
1994 case CustomStream:
1995 {
1996 if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
1997 (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
1998 {
1999 MagickOffsetType
2000 offset;
2001
2002 offset=blob_info->custom_stream->teller(
2003 blob_info->custom_stream->data);
2004 extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
2005 blob_info->custom_stream->data);
2006 (void) blob_info->custom_stream->seeker(offset,SEEK_SET,
2007 blob_info->custom_stream->data);
2008 }
2009 break;
2010 }
2011 }
2012 return(extent);
2013}
2014␌
2015/*
2016%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2017% %
2018% %
2019% %
2020+ G e t B l o b S t r e a m D a t a %
2021% %
2022% %
2023% %
2024%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2025%
2026% GetBlobStreamData() returns the stream data for the image.
2027%
2028% The format of the GetBlobStreamData method is:
2029%
2030% void *GetBlobStreamData(const Image *image)
2031%
2032% A description of each parameter follows:
2033%
2034% o image: the image.
2035%
2036*/
2037MagickExport void *GetBlobStreamData(const Image *image)
2038{
2039 assert(image != (const Image *) NULL);
2040 assert(image->signature == MagickCoreSignature);
2041 return(image->blob->data);
2042}
2043␌
2044/*
2045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2046% %
2047% %
2048% %
2049+ G e t B l o b S t r e a m H a n d l e r %
2050% %
2051% %
2052% %
2053%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2054%
2055% GetBlobStreamHandler() returns the stream handler for the image.
2056%
2057% The format of the GetBlobStreamHandler method is:
2058%
2059% StreamHandler GetBlobStreamHandler(const Image *image)
2060%
2061% A description of each parameter follows:
2062%
2063% o image: the image.
2064%
2065*/
2066MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
2067{
2068 assert(image != (const Image *) NULL);
2069 assert(image->signature == MagickCoreSignature);
2070 if (IsEventLogging() != MagickFalse)
2071 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2072 return(image->blob->stream);
2073}
2074␌
2075/*
2076%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2077% %
2078% %
2079% %
2080% I m a g e T o B l o b %
2081% %
2082% %
2083% %
2084%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2085%
2086% ImageToBlob() implements direct to memory image formats. It returns the
2087% image as a formatted blob and its length. The magick member of the Image
2088% structure determines the format of the returned blob (GIF, JPEG, PNG,
2089% etc.). This method is the equivalent of WriteImage(), but writes the
2090% formatted "file" to a memory buffer rather than to an actual file.
2091%
2092% The format of the ImageToBlob method is:
2093%
2094% void *ImageToBlob(const ImageInfo *image_info,Image *image,
2095% size_t *length,ExceptionInfo *exception)
2096%
2097% A description of each parameter follows:
2098%
2099% o image_info: the image info.
2100%
2101% o image: the image.
2102%
2103% o length: return the actual length of the blob.
2104%
2105% o exception: return any errors or warnings in this structure.
2106%
2107*/
2108MagickExport void *ImageToBlob(const ImageInfo *image_info,
2109 Image *image,size_t *length,ExceptionInfo *exception)
2110{
2111 const MagickInfo
2112 *magick_info;
2113
2114 ImageInfo
2115 *blob_info;
2116
2117 MagickBooleanType
2118 status;
2119
2120 void
2121 *blob;
2122
2123 assert(image_info != (const ImageInfo *) NULL);
2124 assert(image_info->signature == MagickCoreSignature);
2125 assert(image != (Image *) NULL);
2126 assert(image->signature == MagickCoreSignature);
2127 assert(exception != (ExceptionInfo *) NULL);
2128 assert(exception->signature == MagickCoreSignature);
2129 if (IsEventLogging() != MagickFalse)
2130 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2131 image_info->filename);
2132 *length=0;
2133 blob=(unsigned char *) NULL;
2134 blob_info=CloneImageInfo(image_info);
2135 blob_info->adjoin=MagickFalse;
2136 (void) SetImageInfo(blob_info,1,exception);
2137 if (*blob_info->magick != '\0')
2138 (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
2139 magick_info=GetMagickInfo(image->magick,exception);
2140 if (magick_info == (const MagickInfo *) NULL)
2141 {
2142 (void) ThrowMagickException(exception,GetMagickModule(),
2143 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2144 image->magick);
2145 blob_info=DestroyImageInfo(blob_info);
2146 return(blob);
2147 }
2148 (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
2149 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2150 {
2151 /*
2152 Native blob support for this image format.
2153 */
2154 blob_info->length=0;
2155 blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2156 sizeof(unsigned char));
2157 if (blob_info->blob == NULL)
2158 (void) ThrowMagickException(exception,GetMagickModule(),
2159 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2160 else
2161 {
2162 (void) CloseBlob(image);
2163 image->blob->exempt=MagickTrue;
2164 image->blob->extent=0;
2165 *image->filename='\0';
2166 status=WriteImage(blob_info,image,exception);
2167 SyncBlobStream(blob_info,image,image);
2168 *length=image->blob->length;
2169 blob=DetachBlob(image->blob);
2170 if (blob != (void *) NULL)
2171 {
2172 if (status == MagickFalse)
2173 blob=RelinquishMagickMemory(blob);
2174 else
2175 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2176 }
2177 else
2178 if ((status == MagickFalse) && (image->blob->extent == 0))
2179 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2180 }
2181 }
2182 else
2183 {
2184 char
2185 unique[MagickPathExtent];
2186
2187 int
2188 file;
2189
2190 /*
2191 Write file to disk in blob image format.
2192 */
2193 file=AcquireUniqueFileResource(unique);
2194 if (file == -1)
2195 {
2196 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2197 image_info->filename);
2198 }
2199 else
2200 {
2201 blob_info->file=fdopen(file,"wb");
2202 if (blob_info->file != (FILE *) NULL)
2203 {
2204 (void) FormatLocaleString(image->filename,MagickPathExtent,
2205 "%s:%s",image->magick,unique);
2206 status=WriteImage(blob_info,image,exception);
2207 (void) fclose(blob_info->file);
2208 if (status != MagickFalse)
2209 blob=FileToBlob(unique,SIZE_MAX,length,exception);
2210 }
2211 (void) RelinquishUniqueFileResource(unique);
2212 }
2213 }
2214 blob_info=DestroyImageInfo(blob_info);
2215 return(blob);
2216}
2217␌
2218/*
2219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2220% %
2221% %
2222% %
2223+ I m a g e T o C u s t o m S t r e a m %
2224% %
2225% %
2226% %
2227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2228%
2229% ImageToCustomStream() is the equivalent of WriteImage(), but writes the
2230% formatted "file" to the custom stream rather than to an actual file.
2231%
2232% The format of the ImageToCustomStream method is:
2233%
2234% void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2235% ExceptionInfo *exception)
2236%
2237% A description of each parameter follows:
2238%
2239% o image_info: the image info.
2240%
2241% o image: the image.
2242%
2243% o exception: return any errors or warnings in this structure.
2244%
2245*/
2246MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2247 ExceptionInfo *exception)
2248{
2249 const MagickInfo
2250 *magick_info;
2251
2252 ImageInfo
2253 *clone_info;
2254
2255 MagickBooleanType
2256 blob_support,
2257 status;
2258
2259 assert(image_info != (const ImageInfo *) NULL);
2260 assert(image_info->signature == MagickCoreSignature);
2261 assert(image != (Image *) NULL);
2262 assert(image->signature == MagickCoreSignature);
2263 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2264 assert(image_info->custom_stream->signature == MagickCoreSignature);
2265 assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2266 assert(exception != (ExceptionInfo *) NULL);
2267 if (IsEventLogging() != MagickFalse)
2268 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2269 image_info->filename);
2270 clone_info=CloneImageInfo(image_info);
2271 clone_info->adjoin=MagickFalse;
2272 (void) SetImageInfo(clone_info,1,exception);
2273 if (*clone_info->magick != '\0')
2274 (void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
2275 magick_info=GetMagickInfo(image->magick,exception);
2276 if (magick_info == (const MagickInfo *) NULL)
2277 {
2278 (void) ThrowMagickException(exception,GetMagickModule(),
2279 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2280 image->magick);
2281 clone_info=DestroyImageInfo(clone_info);
2282 return;
2283 }
2284 (void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
2285 blob_support=GetMagickBlobSupport(magick_info);
2286 if ((blob_support != MagickFalse) &&
2287 (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2288 {
2289 if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2290 (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2291 blob_support=MagickFalse;
2292 }
2293 if (blob_support != MagickFalse)
2294 {
2295 /*
2296 Native blob support for this image format.
2297 */
2298 (void) CloseBlob(image);
2299 *image->filename='\0';
2300 (void) WriteImage(clone_info,image,exception);
2301 }
2302 else
2303 {
2304 char
2305 unique[MagickPathExtent];
2306
2307 int
2308 file;
2309
2310 unsigned char
2311 *blob;
2312
2313 /*
2314 Write file to disk in blob image format.
2315 */
2316 clone_info->custom_stream=(CustomStreamInfo *) NULL;
2317 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2318 sizeof(*blob));
2319 if (blob == (unsigned char *) NULL)
2320 {
2321 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2322 image_info->filename);
2323 clone_info=DestroyImageInfo(clone_info);
2324 return;
2325 }
2326 file=AcquireUniqueFileResource(unique);
2327 if (file == -1)
2328 {
2329 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2330 image_info->filename);
2331 blob=(unsigned char *) RelinquishMagickMemory(blob);
2332 clone_info=DestroyImageInfo(clone_info);
2333 return;
2334 }
2335 clone_info->file=fdopen(file,"wb+");
2336 if (clone_info->file != (FILE *) NULL)
2337 {
2338 ssize_t
2339 count;
2340
2341 (void) FormatLocaleString(image->filename,MagickPathExtent,
2342 "%s:%s",image->magick,unique);
2343 status=WriteImage(clone_info,image,exception);
2344 if (status != MagickFalse)
2345 {
2346 (void) fseek(clone_info->file,0,SEEK_SET);
2347 count=(ssize_t) MagickMaxBufferExtent;
2348 while (count == (ssize_t) MagickMaxBufferExtent)
2349 {
2350 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2351 clone_info->file);
2352 (void) image_info->custom_stream->writer(blob,(size_t) count,
2353 image_info->custom_stream->data);
2354 }
2355 }
2356 (void) fclose(clone_info->file);
2357 }
2358 blob=(unsigned char *) RelinquishMagickMemory(blob);
2359 (void) RelinquishUniqueFileResource(unique);
2360 }
2361 clone_info=DestroyImageInfo(clone_info);
2362}
2363␌
2364/*
2365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2366% %
2367% %
2368% %
2369% I m a g e T o F i l e %
2370% %
2371% %
2372% %
2373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2374%
2375% ImageToFile() writes an image to a file. It returns MagickFalse if an error
2376% occurs otherwise MagickTrue.
2377%
2378% The format of the ImageToFile method is:
2379%
2380% MagickBooleanType ImageToFile(Image *image,char *filename,
2381% ExceptionInfo *exception)
2382%
2383% A description of each parameter follows:
2384%
2385% o image: the image.
2386%
2387% o filename: Write the image to this file.
2388%
2389% o exception: return any errors or warnings in this structure.
2390%
2391*/
2392MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
2393 ExceptionInfo *exception)
2394{
2395 int
2396 file;
2397
2398 const unsigned char
2399 *p;
2400
2401 size_t
2402 i;
2403
2404 size_t
2405 length,
2406 quantum;
2407
2408 ssize_t
2409 count;
2410
2411 struct stat
2412 file_stats;
2413
2414 unsigned char
2415 *buffer;
2416
2417 assert(image != (Image *) NULL);
2418 assert(image->signature == MagickCoreSignature);
2419 assert(image->blob != (BlobInfo *) NULL);
2420 assert(image->blob->type != UndefinedStream);
2421 assert(filename != (const char *) NULL);
2422 if (IsEventLogging() != MagickFalse)
2423 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
2424 if (*filename == '\0')
2425 file=AcquireUniqueFileResource(filename);
2426 else
2427 if (LocaleCompare(filename,"-") == 0)
2428 file=fileno(stdout);
2429 else
2430 file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
2431 if (file == -1)
2432 {
2433 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2434 return(MagickFalse);
2435 }
2436 quantum=(size_t) MagickMaxBufferExtent;
2437 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2438 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2439 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2440 if (buffer == (unsigned char *) NULL)
2441 {
2442 file=close_utf8(file)-1;
2443 (void) ThrowMagickException(exception,GetMagickModule(),
2444 ResourceLimitError,"MemoryAllocationError","`%s'",filename);
2445 return(MagickFalse);
2446 }
2447 length=0;
2448 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2449 for (i=0; count > 0; )
2450 {
2451 length=(size_t) count;
2452 for (i=0; i < length; i+=(size_t) count)
2453 {
2454 count=write(file,p+i,(size_t) (length-i));
2455 if (count <= 0)
2456 {
2457 count=0;
2458 if (errno != EINTR)
2459 break;
2460 }
2461 }
2462 if (i < length)
2463 break;
2464 p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2465 }
2466 if (LocaleCompare(filename,"-") != 0)
2467 file=close_utf8(file);
2468 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2469 if ((file == -1) || (i < length))
2470 {
2471 if (file != -1)
2472 file=close_utf8(file);
2473 ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2474 return(MagickFalse);
2475 }
2476 return(MagickTrue);
2477}
2478␌
2479/*
2480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2481% %
2482% %
2483% %
2484% I m a g e s T o B l o b %
2485% %
2486% %
2487% %
2488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2489%
2490% ImagesToBlob() implements direct to memory image formats. It returns the
2491% image sequence as a blob and its length. The magick member of the ImageInfo
2492% structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
2493%
2494% Note, some image formats do not permit multiple images to the same image
2495% stream (e.g. JPEG). in this instance, just the first image of the
2496% sequence is returned as a blob.
2497%
2498% The format of the ImagesToBlob method is:
2499%
2500% void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2501% size_t *length,ExceptionInfo *exception)
2502%
2503% A description of each parameter follows:
2504%
2505% o image_info: the image info.
2506%
2507% o images: the image list.
2508%
2509% o length: return the actual length of the blob.
2510%
2511% o exception: return any errors or warnings in this structure.
2512%
2513*/
2514MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2515 size_t *length,ExceptionInfo *exception)
2516{
2517 const MagickInfo
2518 *magick_info;
2519
2520 ImageInfo
2521 *blob_info;
2522
2523 MagickBooleanType
2524 status;
2525
2526 void
2527 *blob;
2528
2529 assert(image_info != (const ImageInfo *) NULL);
2530 assert(image_info->signature == MagickCoreSignature);
2531 assert(images != (Image *) NULL);
2532 assert(images->signature == MagickCoreSignature);
2533 assert(exception != (ExceptionInfo *) NULL);
2534 if (IsEventLogging() != MagickFalse)
2535 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2536 image_info->filename);
2537 *length=0;
2538 blob=(unsigned char *) NULL;
2539 blob_info=CloneImageInfo(image_info);
2540 (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2541 exception);
2542 if (*blob_info->magick != '\0')
2543 (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2544 magick_info=GetMagickInfo(images->magick,exception);
2545 if (magick_info == (const MagickInfo *) NULL)
2546 {
2547 (void) ThrowMagickException(exception,GetMagickModule(),
2548 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2549 images->magick);
2550 blob_info=DestroyImageInfo(blob_info);
2551 return(blob);
2552 }
2553 if (GetMagickAdjoin(magick_info) == MagickFalse)
2554 {
2555 blob_info=DestroyImageInfo(blob_info);
2556 return(ImageToBlob(image_info,images,length,exception));
2557 }
2558 (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2559 if (GetMagickBlobSupport(magick_info) != MagickFalse)
2560 {
2561 /*
2562 Native blob support for this images format.
2563 */
2564 blob_info->length=0;
2565 blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2566 sizeof(unsigned char));
2567 if (blob_info->blob == (void *) NULL)
2568 (void) ThrowMagickException(exception,GetMagickModule(),
2569 ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2570 else
2571 {
2572 (void) CloseBlob(images);
2573 images->blob->exempt=MagickTrue;
2574 images->blob->extent=0;
2575 *images->filename='\0';
2576 status=WriteImages(blob_info,images,images->filename,exception);
2577 SyncBlobStream(blob_info,images,images);
2578 *length=images->blob->length;
2579 blob=DetachBlob(images->blob);
2580 if (blob != (void *) NULL)
2581 {
2582 if (status == MagickFalse)
2583 blob=RelinquishMagickMemory(blob);
2584 else
2585 blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2586 }
2587 else if ((status == MagickFalse) && (images->blob->extent == 0))
2588 blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2589 }
2590 }
2591 else
2592 {
2593 char
2594 filename[MagickPathExtent],
2595 unique[MagickPathExtent];
2596
2597 int
2598 file;
2599
2600 /*
2601 Write file to disk in blob images format.
2602 */
2603 file=AcquireUniqueFileResource(unique);
2604 if (file == -1)
2605 {
2606 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2607 image_info->filename);
2608 }
2609 else
2610 {
2611 blob_info->file=fdopen(file,"wb");
2612 if (blob_info->file != (FILE *) NULL)
2613 {
2614 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2615 images->magick,unique);
2616 status=WriteImages(blob_info,images,filename,exception);
2617 (void) fclose(blob_info->file);
2618 if (status != MagickFalse)
2619 blob=FileToBlob(unique,SIZE_MAX,length,exception);
2620 }
2621 (void) RelinquishUniqueFileResource(unique);
2622 }
2623 }
2624 blob_info=DestroyImageInfo(blob_info);
2625 return(blob);
2626}
2627␌
2628/*
2629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2630% %
2631% %
2632% %
2633+ I m a g e s T o C u s t o m B l o b %
2634% %
2635% %
2636% %
2637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2638%
2639% ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2640% formatted "file" to the custom stream rather than to an actual file.
2641%
2642% The format of the ImageToCustomStream method is:
2643%
2644% void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2645% ExceptionInfo *exception)
2646%
2647% A description of each parameter follows:
2648%
2649% o image_info: the image info.
2650%
2651% o images: the image list.
2652%
2653% o exception: return any errors or warnings in this structure.
2654%
2655*/
2656MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2657 Image *images,ExceptionInfo *exception)
2658{
2659 const MagickInfo
2660 *magick_info;
2661
2662 ImageInfo
2663 *clone_info;
2664
2665 MagickBooleanType
2666 blob_support,
2667 status;
2668
2669 assert(image_info != (const ImageInfo *) NULL);
2670 assert(image_info->signature == MagickCoreSignature);
2671 assert(images != (Image *) NULL);
2672 assert(images->signature == MagickCoreSignature);
2673 assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2674 assert(image_info->custom_stream->signature == MagickCoreSignature);
2675 assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2676 assert(exception != (ExceptionInfo *) NULL);
2677 if (IsEventLogging() != MagickFalse)
2678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2679 image_info->filename);
2680 clone_info=CloneImageInfo(image_info);
2681 (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2682 exception);
2683 if (*clone_info->magick != '\0')
2684 (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2685 magick_info=GetMagickInfo(images->magick,exception);
2686 if (magick_info == (const MagickInfo *) NULL)
2687 {
2688 (void) ThrowMagickException(exception,GetMagickModule(),
2689 MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2690 images->magick);
2691 clone_info=DestroyImageInfo(clone_info);
2692 return;
2693 }
2694 (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2695 blob_support=GetMagickBlobSupport(magick_info);
2696 if ((blob_support != MagickFalse) &&
2697 (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2698 {
2699 if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2700 (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2701 blob_support=MagickFalse;
2702 }
2703 if (blob_support != MagickFalse)
2704 {
2705 /*
2706 Native blob support for this image format.
2707 */
2708 (void) CloseBlob(images);
2709 *images->filename='\0';
2710 (void) WriteImages(clone_info,images,images->filename,exception);
2711 }
2712 else
2713 {
2714 char
2715 filename[MagickPathExtent],
2716 unique[MagickPathExtent];
2717
2718 int
2719 file;
2720
2721 unsigned char
2722 *blob;
2723
2724 /*
2725 Write file to disk in blob image format.
2726 */
2727 clone_info->custom_stream=(CustomStreamInfo *) NULL;
2728 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2729 sizeof(*blob));
2730 if (blob == (unsigned char *) NULL)
2731 {
2732 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2733 image_info->filename);
2734 clone_info=DestroyImageInfo(clone_info);
2735 return;
2736 }
2737 file=AcquireUniqueFileResource(unique);
2738 if (file == -1)
2739 {
2740 ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2741 image_info->filename);
2742 blob=(unsigned char *) RelinquishMagickMemory(blob);
2743 clone_info=DestroyImageInfo(clone_info);
2744 return;
2745 }
2746 clone_info->file=fdopen(file,"wb+");
2747 if (clone_info->file != (FILE *) NULL)
2748 {
2749 ssize_t
2750 count;
2751
2752 (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2753 images->magick,unique);
2754 status=WriteImages(clone_info,images,filename,exception);
2755 if (status != MagickFalse)
2756 {
2757 (void) fseek(clone_info->file,0,SEEK_SET);
2758 count=(ssize_t) MagickMaxBufferExtent;
2759 while (count == (ssize_t) MagickMaxBufferExtent)
2760 {
2761 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2762 clone_info->file);
2763 (void) image_info->custom_stream->writer(blob,(size_t) count,
2764 image_info->custom_stream->data);
2765 }
2766 }
2767 (void) fclose(clone_info->file);
2768 }
2769 blob=(unsigned char *) RelinquishMagickMemory(blob);
2770 (void) RelinquishUniqueFileResource(unique);
2771 }
2772 clone_info=DestroyImageInfo(clone_info);
2773}
2774␌
2775/*
2776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2777% %
2778% %
2779% %
2780% I n j e c t I m a g e B l o b %
2781% %
2782% %
2783% %
2784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2785%
2786% InjectImageBlob() injects the image with a copy of itself in the specified
2787% format (e.g. inject JPEG into a PDF image).
2788%
2789% The format of the InjectImageBlob method is:
2790%
2791% MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2792% Image *image,Image *inject_image,const char *format,
2793% ExceptionInfo *exception)
2794%
2795% A description of each parameter follows:
2796%
2797% o image_info: the image info..
2798%
2799% o image: the image.
2800%
2801% o inject_image: inject into the image stream.
2802%
2803% o format: the image format.
2804%
2805% o exception: return any errors or warnings in this structure.
2806%
2807*/
2808MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2809 Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2810{
2811 char
2812 filename[MagickPathExtent];
2813
2814 FILE
2815 *unique_file;
2816
2817 Image
2818 *byte_image;
2819
2820 ImageInfo
2821 *write_info;
2822
2823 int
2824 file;
2825
2826 MagickBooleanType
2827 status;
2828
2829 size_t
2830 quantum;
2831
2832 struct stat
2833 file_stats;
2834
2835 unsigned char
2836 *buffer;
2837
2838 /*
2839 Write inject image to a temporary file.
2840 */
2841 assert(image_info != (ImageInfo *) NULL);
2842 assert(image_info->signature == MagickCoreSignature);
2843 assert(image != (Image *) NULL);
2844 assert(image->signature == MagickCoreSignature);
2845 assert(inject_image != (Image *) NULL);
2846 assert(inject_image->signature == MagickCoreSignature);
2847 assert(exception != (ExceptionInfo *) NULL);
2848 if (IsEventLogging() != MagickFalse)
2849 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2850 unique_file=(FILE *) NULL;
2851 file=AcquireUniqueFileResource(filename);
2852 if (file != -1)
2853 unique_file=fdopen(file,"wb");
2854 if ((file == -1) || (unique_file == (FILE *) NULL))
2855 {
2856 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2857 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2858 image->filename);
2859 return(MagickFalse);
2860 }
2861 byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2862 if (byte_image == (Image *) NULL)
2863 {
2864 (void) fclose(unique_file);
2865 (void) RelinquishUniqueFileResource(filename);
2866 return(MagickFalse);
2867 }
2868 (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2869 format,filename);
2870 DestroyBlob(byte_image);
2871 byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2872 write_info=CloneImageInfo(image_info);
2873 SetImageInfoFile(write_info,unique_file);
2874 status=WriteImage(write_info,byte_image,exception);
2875 write_info=DestroyImageInfo(write_info);
2876 byte_image=DestroyImage(byte_image);
2877 (void) fclose(unique_file);
2878 if (status == MagickFalse)
2879 {
2880 (void) RelinquishUniqueFileResource(filename);
2881 return(MagickFalse);
2882 }
2883 /*
2884 Inject into image stream.
2885 */
2886 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2887 if (file == -1)
2888 {
2889 (void) RelinquishUniqueFileResource(filename);
2890 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2891 image_info->filename);
2892 return(MagickFalse);
2893 }
2894 quantum=(size_t) MagickMaxBufferExtent;
2895 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2896 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2897 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2898 if (buffer == (unsigned char *) NULL)
2899 {
2900 (void) RelinquishUniqueFileResource(filename);
2901 file=close_utf8(file);
2902 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2903 image->filename);
2904 }
2905 for ( ; ; )
2906 {
2907 ssize_t count = read(file,buffer,quantum);
2908 if (count <= 0)
2909 {
2910 count=0;
2911 if (errno != EINTR)
2912 break;
2913 }
2914 status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2915 MagickFalse;
2916 }
2917 file=close_utf8(file);
2918 if (file == -1)
2919 ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2920 (void) RelinquishUniqueFileResource(filename);
2921 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2922 return(status);
2923}
2924␌
2925/*
2926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2927% %
2928% %
2929% %
2930% I s B l o b E x e m p t %
2931% %
2932% %
2933% %
2934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2935%
2936% IsBlobExempt() returns true if the blob is exempt.
2937%
2938% The format of the IsBlobExempt method is:
2939%
2940% MagickBooleanType IsBlobExempt(const Image *image)
2941%
2942% A description of each parameter follows:
2943%
2944% o image: the image.
2945%
2946*/
2947MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2948{
2949 assert(image != (const Image *) NULL);
2950 assert(image->signature == MagickCoreSignature);
2951 if (IsEventLogging() != MagickFalse)
2952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2953 return(image->blob->exempt);
2954}
2955␌
2956/*
2957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2958% %
2959% %
2960% %
2961% I s B l o b S e e k a b l e %
2962% %
2963% %
2964% %
2965%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2966%
2967% IsBlobSeekable() returns true if the blob is seekable.
2968%
2969% The format of the IsBlobSeekable method is:
2970%
2971% MagickBooleanType IsBlobSeekable(const Image *image)
2972%
2973% A description of each parameter follows:
2974%
2975% o image: the image.
2976%
2977*/
2978MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2979{
2980 BlobInfo
2981 *magick_restrict blob_info;
2982
2983 assert(image != (const Image *) NULL);
2984 assert(image->signature == MagickCoreSignature);
2985 if (IsEventLogging() != MagickFalse)
2986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2987 blob_info=image->blob;
2988 switch (blob_info->type)
2989 {
2990 case BlobStream:
2991 return(MagickTrue);
2992 case FileStream:
2993 {
2994 int
2995 status;
2996
2997 if (blob_info->file_info.file == (FILE *) NULL)
2998 return(MagickFalse);
2999 status=fseek(blob_info->file_info.file,0,SEEK_CUR);
3000 return(status == -1 ? MagickFalse : MagickTrue);
3001 }
3002 case ZipStream:
3003 {
3004#if defined(MAGICKCORE_ZLIB_DELEGATE)
3005 MagickOffsetType
3006 offset;
3007
3008 if (blob_info->file_info.gzfile == (gzFile) NULL)
3009 return(MagickFalse);
3010 offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
3011 return(offset < 0 ? MagickFalse : MagickTrue);
3012#else
3013 break;
3014#endif
3015 }
3016 case UndefinedStream:
3017 case BZipStream:
3018 case FifoStream:
3019 case PipeStream:
3020 case StandardStream:
3021 break;
3022 case CustomStream:
3023 {
3024 if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
3025 (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
3026 return(MagickTrue);
3027 break;
3028 }
3029 default:
3030 break;
3031 }
3032 return(MagickFalse);
3033}
3034␌
3035/*
3036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3037% %
3038% %
3039% %
3040% I s B l o b T e m p o r a r y %
3041% %
3042% %
3043% %
3044%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3045%
3046% IsBlobTemporary() returns true if the blob is temporary.
3047%
3048% The format of the IsBlobTemporary method is:
3049%
3050% MagickBooleanType IsBlobTemporary(const Image *image)
3051%
3052% A description of each parameter follows:
3053%
3054% o image: the image.
3055%
3056*/
3057MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
3058{
3059 assert(image != (const Image *) NULL);
3060 assert(image->signature == MagickCoreSignature);
3061 if (IsEventLogging() != MagickFalse)
3062 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3063 return(image->blob->temporary);
3064}
3065␌
3066/*
3067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3068% %
3069% %
3070% %
3071+ M a p B l o b %
3072% %
3073% %
3074% %
3075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3076%
3077% MapBlob() creates a mapping from a file to a binary large object.
3078%
3079% The format of the MapBlob method is:
3080%
3081% void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
3082% const size_t length)
3083%
3084% A description of each parameter follows:
3085%
3086% o file: map this file descriptor.
3087%
3088% o mode: ReadMode, WriteMode, or IOMode.
3089%
3090% o offset: starting at this offset within the file.
3091%
3092% o length: the length of the mapping is returned in this pointer.
3093%
3094*/
3095MagickExport void *MapBlob(int file,const MapMode mode,
3096 const MagickOffsetType offset,const size_t length)
3097{
3098#if defined(MAGICKCORE_HAVE_MMAP)
3099 int
3100 flags,
3101 protection;
3102
3103 void
3104 *map;
3105
3106 /*
3107 Map file.
3108 */
3109 flags=0;
3110 if (file == -1)
3111#if defined(MAP_ANONYMOUS)
3112 flags|=MAP_ANONYMOUS;
3113#else
3114 return(NULL);
3115#endif
3116 switch (mode)
3117 {
3118 case ReadMode:
3119 default:
3120 {
3121 protection=PROT_READ;
3122 flags|=MAP_PRIVATE;
3123 break;
3124 }
3125 case WriteMode:
3126 {
3127 protection=PROT_WRITE;
3128 flags|=MAP_SHARED;
3129 break;
3130 }
3131 case IOMode:
3132 {
3133 protection=PROT_READ | PROT_WRITE;
3134 flags|=MAP_SHARED;
3135 break;
3136 }
3137 }
3138#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
3139 map=mmap((char *) NULL,length,protection,flags,file,offset);
3140#else
3141 map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,offset);
3142 if (map == MAP_FAILED)
3143 map=mmap((char *) NULL,length,protection,flags,file,offset);
3144#endif
3145 if (map == MAP_FAILED)
3146 return(NULL);
3147 return(map);
3148#else
3149 (void) file;
3150 (void) mode;
3151 (void) offset;
3152 (void) length;
3153 return(NULL);
3154#endif
3155}
3156␌
3157/*
3158%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3159% %
3160% %
3161% %
3162+ M S B O r d e r L o n g %
3163% %
3164% %
3165% %
3166%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3167%
3168% MSBOrderLong() converts a least-significant byte first buffer of integers to
3169% most-significant byte first.
3170%
3171% The format of the MSBOrderLong method is:
3172%
3173% void MSBOrderLong(unsigned char *buffer,const size_t length)
3174%
3175% A description of each parameter follows.
3176%
3177% o buffer: Specifies a pointer to a buffer of integers.
3178%
3179% o length: Specifies the length of the buffer.
3180%
3181*/
3182MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
3183{
3184 int
3185 c;
3186
3187 unsigned char
3188 *p,
3189 *q;
3190
3191 assert(buffer != (unsigned char *) NULL);
3192 q=buffer+length;
3193 while (buffer < q)
3194 {
3195 p=buffer+3;
3196 c=(int) (*p);
3197 *p=(*buffer);
3198 *buffer++=(unsigned char) c;
3199 p=buffer+1;
3200 c=(int) (*p);
3201 *p=(*buffer);
3202 *buffer++=(unsigned char) c;
3203 buffer+=2;
3204 }
3205}
3206␌
3207/*
3208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3209% %
3210% %
3211% %
3212+ M S B O r d e r S h o r t %
3213% %
3214% %
3215% %
3216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3217%
3218% MSBOrderShort() converts a least-significant byte first buffer of integers
3219% to most-significant byte first.
3220%
3221% The format of the MSBOrderShort method is:
3222%
3223% void MSBOrderShort(unsigned char *p,const size_t length)
3224%
3225% A description of each parameter follows.
3226%
3227% o p: Specifies a pointer to a buffer of integers.
3228%
3229% o length: Specifies the length of the buffer.
3230%
3231*/
3232MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
3233{
3234 int
3235 c;
3236
3237 unsigned char
3238 *q;
3239
3240 assert(p != (unsigned char *) NULL);
3241 q=p+length;
3242 while (p < q)
3243 {
3244 c=(int) (*p);
3245 *p=(*(p+1));
3246 p++;
3247 *p++=(unsigned char) c;
3248 }
3249}
3250␌
3251/*
3252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3253% %
3254% %
3255% %
3256+ O p e n B l o b %
3257% %
3258% %
3259% %
3260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3261%
3262% OpenBlob() opens a file associated with the image. A file name of '-' sets
3263% the file to stdin for type 'r' and stdout for type 'w'. If the filename
3264% suffix is '.gz', the image is decompressed for type 'r' and compressed for
3265% type 'w'. If the filename prefix is '|', it is piped to or from a system
3266% command.
3267%
3268% The format of the OpenBlob method is:
3269%
3270% MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
3271% const BlobMode mode,ExceptionInfo *exception)
3272%
3273% A description of each parameter follows:
3274%
3275% o image_info: the image info.
3276%
3277% o image: the image.
3278%
3279% o mode: the mode for opening the file.
3280%
3281*/
3282
3283static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
3284 const BlobInfo *blob_info)
3285{
3286 const char
3287 *option;
3288
3289 int
3290 status;
3291
3292 size_t
3293 size;
3294
3295 size=MagickMinBufferExtent;
3296 option=GetImageOption(image_info,"stream:buffer-size");
3297 if (option != (const char *) NULL)
3298 size=StringToUnsignedLong(option);
3299 status=setvbuf(blob_info->file_info.file,(char *) NULL,size == 0 ?
3300 _IONBF : _IOFBF,size);
3301 return(status == 0 ? MagickTrue : MagickFalse);
3302}
3303
3304#if defined(MAGICKCORE_ZLIB_DELEGATE)
3305static inline gzFile gzopen_utf8(const char *path,const char *mode)
3306{
3307#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
3308 return(gzopen(path,mode));
3309#else
3310 gzFile
3311 file;
3312
3313 wchar_t
3314 *path_wide;
3315
3316 path_wide=create_wchar_path(path);
3317 if (path_wide == (wchar_t *) NULL)
3318 return((gzFile) NULL);
3319 file=gzopen_w(path_wide,mode);
3320 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
3321 return(file);
3322#endif
3323}
3324#endif
3325
3326MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
3327 Image *image,const BlobMode mode,ExceptionInfo *exception)
3328{
3329 BlobInfo
3330 *magick_restrict blob_info;
3331
3332 char
3333 extension[MagickPathExtent],
3334 filename[MagickPathExtent];
3335
3336 const char
3337 *type;
3338
3339 int
3340 flags = O_RDONLY;
3341
3342 MagickBooleanType
3343 status;
3344
3345 PolicyRights
3346 rights;
3347
3348 assert(image_info != (ImageInfo *) NULL);
3349 assert(image_info->signature == MagickCoreSignature);
3350 assert(image != (Image *) NULL);
3351 assert(image->signature == MagickCoreSignature);
3352 if (IsEventLogging() != MagickFalse)
3353 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3354 image_info->filename);
3355 blob_info=image->blob;
3356 if (image_info->blob != (void *) NULL)
3357 {
3358 if (image_info->stream != (StreamHandler) NULL)
3359 blob_info->stream=(StreamHandler) image_info->stream;
3360 AttachBlob(blob_info,image_info->blob,image_info->length);
3361 return(MagickTrue);
3362 }
3363 if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3364 (*image->filename == '\0'))
3365 {
3366 blob_info->type=CustomStream;
3367 blob_info->custom_stream=image_info->custom_stream;
3368 return(MagickTrue);
3369 }
3370 (void) DetachBlob(blob_info);
3371 blob_info->mode=mode;
3372 switch (mode)
3373 {
3374 case ReadBlobMode:
3375 {
3376 flags=O_RDONLY;
3377 type="r";
3378 break;
3379 }
3380 case ReadBinaryBlobMode:
3381 {
3382 flags=O_RDONLY | O_BINARY;
3383 type="rb";
3384 break;
3385 }
3386 case WriteBlobMode:
3387 {
3388 flags=O_WRONLY | O_CREAT | O_TRUNC;
3389 type="w";
3390 break;
3391 }
3392 case WriteBinaryBlobMode:
3393 {
3394 flags=O_RDWR | O_CREAT | O_TRUNC | O_BINARY;
3395 type="w+b";
3396 break;
3397 }
3398 case AppendBlobMode:
3399 {
3400 flags=O_WRONLY | O_CREAT | O_APPEND;
3401 type="a";
3402 break;
3403 }
3404 case AppendBinaryBlobMode:
3405 {
3406 flags=O_RDWR | O_CREAT | O_APPEND | O_BINARY;
3407 type="a+b";
3408 break;
3409 }
3410 default:
3411 {
3412 flags=O_RDONLY;
3413 type="r";
3414 break;
3415 }
3416 }
3417 if (*type != 'r')
3418 blob_info->synchronize=image_info->synchronize;
3419 if (image_info->stream != (StreamHandler) NULL)
3420 {
3421 blob_info->stream=image_info->stream;
3422 if (*type == 'w')
3423 {
3424 blob_info->type=FifoStream;
3425 return(MagickTrue);
3426 }
3427 }
3428 /*
3429 Open image file.
3430 */
3431 *filename='\0';
3432 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3433 rights=ReadPolicyRights;
3434 if (*type == 'w')
3435 rights=WritePolicyRights;
3436 if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
3437 {
3438 errno=EPERM;
3439 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
3440 "NotAuthorized","`%s'",filename);
3441 return(MagickFalse);
3442 }
3443 if ((LocaleCompare(filename,"-") == 0) ||
3444 ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3445 {
3446 blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3447#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3448 if (strchr(type,'b') != (char *) NULL)
3449 (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
3450#endif
3451 blob_info->type=StandardStream;
3452 blob_info->exempt=MagickTrue;
3453 return(SetStreamBuffering(image_info,blob_info));
3454 }
3455 if ((LocaleNCompare(filename,"fd:",3) == 0) &&
3456 (IsGeometry(filename+3) != MagickFalse))
3457 {
3458 char
3459 fileMode[2];
3460
3461 *fileMode=(*type);
3462 fileMode[1]='\0';
3463 blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
3464 if (blob_info->file_info.file == (FILE *) NULL)
3465 {
3466 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3467 return(MagickFalse);
3468 }
3469#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3470 if (strchr(type,'b') != (char *) NULL)
3471 (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
3472#endif
3473 blob_info->type=FileStream;
3474 blob_info->exempt=MagickTrue;
3475 return(SetStreamBuffering(image_info,blob_info));
3476 }
3477#if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3478 if (*filename == '|')
3479 {
3480 char
3481 fileMode[MagickPathExtent],
3482 *sanitize_command;
3483
3484 /*
3485 Pipe image to or from a system command.
3486 */
3487#if defined(SIGPIPE)
3488 if (*type == 'w')
3489 (void) signal(SIGPIPE,SIG_IGN);
3490#endif
3491 *fileMode=(*type);
3492 fileMode[1]='\0';
3493 sanitize_command=SanitizeString(filename+1);
3494 blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3495 sanitize_command=DestroyString(sanitize_command);
3496 if (blob_info->file_info.file == (FILE *) NULL)
3497 {
3498 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3499 return(MagickFalse);
3500 }
3501 blob_info->type=PipeStream;
3502 blob_info->exempt=MagickTrue;
3503 return(SetStreamBuffering(image_info,blob_info));
3504 }
3505#endif
3506 status=GetPathAttributes(filename,&blob_info->properties);
3507#if defined(S_ISFIFO)
3508 if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3509 {
3510 blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3511 if (blob_info->file_info.file == (FILE *) NULL)
3512 {
3513 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3514 return(MagickFalse);
3515 }
3516 blob_info->type=FileStream;
3517 blob_info->exempt=MagickTrue;
3518 return(SetStreamBuffering(image_info,blob_info));
3519 }
3520#endif
3521 GetPathComponent(image->filename,ExtensionPath,extension);
3522 if (*type == 'w')
3523 {
3524 (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3525 if ((image_info->adjoin == MagickFalse) ||
3526 (strchr(filename,'%') != (char *) NULL))
3527 {
3528 /*
3529 Form filename for multi-part images.
3530 */
3531 (void) InterpretImageFilename(image_info,image,image->filename,(int)
3532 image->scene,filename,exception);
3533 if ((LocaleCompare(filename,image->filename) == 0) &&
3534 ((GetPreviousImageInList(image) != (Image *) NULL) ||
3535 (GetNextImageInList(image) != (Image *) NULL)))
3536 {
3537 char
3538 path[MagickPathExtent];
3539
3540 GetPathComponent(image->filename,RootPath,path);
3541 if (*extension == '\0')
3542 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
3543 path,(double) image->scene);
3544 else
3545 (void) FormatLocaleString(filename,MagickPathExtent,
3546 "%s-%.20g.%s",path,(double) image->scene,extension);
3547 }
3548 (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3549 }
3550 if (IsPathAuthorized(rights,filename) == MagickFalse)
3551 {
3552 errno=EPERM;
3553 (void) ThrowMagickException(exception,GetMagickModule(),
3554 PolicyError,"NotAuthorized","`%s'",filename);
3555 return(MagickFalse);
3556 }
3557 }
3558 if (image_info->file != (FILE *) NULL)
3559 {
3560 blob_info->file_info.file=image_info->file;
3561 blob_info->type=FileStream;
3562 blob_info->exempt=MagickTrue;
3563 }
3564 else
3565 if (*type == 'r')
3566 {
3567 int
3568 file;
3569
3570 blob_info->file_info.file=(FILE *) NULL;
3571#if defined(O_NOFOLLOW)
3572 status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights,"follow");
3573 if (status == MagickFalse)
3574 flags|=O_NOFOLLOW;
3575#endif
3576 file=open_utf8(filename,flags,0);
3577 if (file >= 0)
3578 blob_info->file_info.file=fdopen(file,type);
3579 if (blob_info->file_info.file != (FILE *) NULL)
3580 {
3581 size_t
3582 count;
3583
3584 unsigned char
3585 magick[3];
3586
3587 blob_info->type=FileStream;
3588 (void) SetStreamBuffering(image_info,blob_info);
3589 (void) memset(magick,0,sizeof(magick));
3590 count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3591 (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3592#if defined(MAGICKCORE_POSIX_SUPPORT)
3593 (void) fflush(blob_info->file_info.file);
3594#endif
3595 (void) LogMagickEvent(BlobEvent,GetMagickModule(),
3596 " read %.20g magic header bytes",(double) count);
3597#if defined(MAGICKCORE_ZLIB_DELEGATE)
3598 if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3599 ((int) magick[2] == 0x08))
3600 {
3601 gzFile
3602 gzfile = gzopen_utf8(filename,"rb");
3603
3604 if (gzfile != (gzFile) NULL)
3605 {
3606 if (blob_info->file_info.file != (FILE *) NULL)
3607 (void) fclose(blob_info->file_info.file);
3608 blob_info->file_info.file=(FILE *) NULL;
3609 blob_info->file_info.gzfile=gzfile;
3610 blob_info->type=ZipStream;
3611 }
3612 }
3613#endif
3614#if defined(MAGICKCORE_BZLIB_DELEGATE)
3615 if (strncmp((char *) magick,"BZh",3) == 0)
3616 {
3617 BZFILE
3618 *bzfile = BZ2_bzopen(filename,"r");
3619
3620 if (bzfile != (BZFILE *) NULL)
3621 {
3622 if (blob_info->file_info.file != (FILE *) NULL)
3623 (void) fclose(blob_info->file_info.file);
3624 blob_info->file_info.file=(FILE *) NULL;
3625 blob_info->file_info.bzfile=bzfile;
3626 blob_info->type=BZipStream;
3627 }
3628 }
3629#endif
3630 if (blob_info->type == FileStream)
3631 {
3632 const MagickInfo
3633 *magick_info;
3634
3636 *sans_exception;
3637
3638 size_t
3639 length;
3640
3641 sans_exception=AcquireExceptionInfo();
3642 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3643 sans_exception=DestroyExceptionInfo(sans_exception);
3644 length=(size_t) blob_info->properties.st_size;
3645 if ((magick_info != (const MagickInfo *) NULL) &&
3646 (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3647 (length > MagickMaxBufferExtent) &&
3648 (AcquireMagickResource(MapResource,length) != MagickFalse))
3649 {
3650 void
3651 *blob;
3652
3653 blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3654 length);
3655 if (blob == (void *) NULL)
3656 RelinquishMagickResource(MapResource,length);
3657 else
3658 {
3659 /*
3660 Format supports blobs-- use memory-mapped I/O.
3661 */
3662 if (image_info->file != (FILE *) NULL)
3663 blob_info->exempt=MagickFalse;
3664 else
3665 {
3666 (void) fclose(blob_info->file_info.file);
3667 blob_info->file_info.file=(FILE *) NULL;
3668 }
3669 AttachBlob(blob_info,blob,length);
3670 blob_info->mapped=MagickTrue;
3671 }
3672 }
3673 }
3674 }
3675 }
3676 else
3677#if defined(MAGICKCORE_ZLIB_DELEGATE)
3678 if ((LocaleCompare(extension,"gz") == 0) ||
3679 (LocaleCompare(extension,"wmz") == 0) ||
3680 (LocaleCompare(extension,"svgz") == 0))
3681 {
3682 blob_info->file_info.gzfile=gzopen_utf8(filename,"wb");
3683 if (blob_info->file_info.gzfile != (gzFile) NULL)
3684 blob_info->type=ZipStream;
3685 }
3686 else
3687#endif
3688#if defined(MAGICKCORE_BZLIB_DELEGATE)
3689 if (LocaleCompare(extension,"bz2") == 0)
3690 {
3691 blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
3692 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3693 blob_info->type=BZipStream;
3694 }
3695 else
3696#endif
3697 {
3698 int
3699 file;
3700
3701 blob_info->file_info.file=(FILE *) NULL;
3702#if defined(O_NOFOLLOW)
3703 status=IsRightsAuthorized(SystemPolicyDomain,WritePolicyRights,
3704 "follow");
3705 if (status == MagickFalse)
3706 flags|=O_NOFOLLOW;
3707#endif
3708 file=open_utf8(filename,flags,0666);
3709 if (file >= 0)
3710 blob_info->file_info.file=fdopen(file,type);
3711 if (blob_info->file_info.file != (FILE *) NULL)
3712 {
3713 blob_info->type=FileStream;
3714 (void) SetStreamBuffering(image_info,blob_info);
3715 }
3716 }
3717 blob_info->status=0;
3718 blob_info->error_number=0;
3719 if (blob_info->type != UndefinedStream)
3720 blob_info->size=GetBlobSize(image);
3721 else
3722 {
3723 ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3724 return(MagickFalse);
3725 }
3726 return(MagickTrue);
3727}
3728␌
3729/*
3730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3731% %
3732% %
3733% %
3734+ P i n g B l o b %
3735% %
3736% %
3737% %
3738%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3739%
3740% PingBlob() returns all the attributes of an image or image sequence except
3741% for the pixels. It is much faster and consumes far less memory than
3742% BlobToImage(). On failure, a NULL image is returned and exception
3743% describes the reason for the failure.
3744%
3745% The format of the PingBlob method is:
3746%
3747% Image *PingBlob(const ImageInfo *image_info,const void *blob,
3748% const size_t length,ExceptionInfo *exception)
3749%
3750% A description of each parameter follows:
3751%
3752% o image_info: the image info.
3753%
3754% o blob: the address of a character stream in one of the image formats
3755% understood by ImageMagick.
3756%
3757% o length: This size_t integer reflects the length in bytes of the blob.
3758%
3759% o exception: return any errors or warnings in this structure.
3760%
3761*/
3762
3763#if defined(__cplusplus) || defined(c_plusplus)
3764extern "C" {
3765#endif
3766
3767static size_t PingStream(const Image *magick_unused(image),
3768 const void *magick_unused(pixels),const size_t columns)
3769{
3770 magick_unreferenced(image);
3771 magick_unreferenced(pixels);
3772 return(columns);
3773}
3774
3775#if defined(__cplusplus) || defined(c_plusplus)
3776}
3777#endif
3778
3779MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3780 const size_t length,ExceptionInfo *exception)
3781{
3782 const MagickInfo
3783 *magick_info;
3784
3785 Image
3786 *image;
3787
3788 ImageInfo
3789 *clone_info,
3790 *ping_info;
3791
3792 MagickBooleanType
3793 status;
3794
3795 assert(image_info != (ImageInfo *) NULL);
3796 assert(image_info->signature == MagickCoreSignature);
3797 assert(exception != (ExceptionInfo *) NULL);
3798 if (IsEventLogging() != MagickFalse)
3799 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3800 image_info->filename);
3801 if ((blob == (const void *) NULL) || (length == 0))
3802 {
3803 (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3804 "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3805 return((Image *) NULL);
3806 }
3807 ping_info=CloneImageInfo(image_info);
3808 ping_info->blob=(void *) blob;
3809 ping_info->length=length;
3810 ping_info->ping=MagickTrue;
3811 if (*ping_info->magick == '\0')
3812 (void) SetImageInfo(ping_info,0,exception);
3813 magick_info=GetMagickInfo(ping_info->magick,exception);
3814 if (magick_info == (const MagickInfo *) NULL)
3815 {
3816 (void) ThrowMagickException(exception,GetMagickModule(),
3817 MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3818 ping_info->magick);
3819 ping_info=DestroyImageInfo(ping_info);
3820 return((Image *) NULL);
3821 }
3822 if (GetMagickBlobSupport(magick_info) != MagickFalse)
3823 {
3824 char
3825 filename[MagickPathExtent];
3826
3827 /*
3828 Native blob support for this image format.
3829 */
3830 (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3831 (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3832 ping_info->magick,filename);
3833 image=ReadStream(ping_info,&PingStream,exception);
3834 if (image != (Image *) NULL)
3835 (void) DetachBlob(image->blob);
3836 ping_info=DestroyImageInfo(ping_info);
3837 return(image);
3838 }
3839 /*
3840 Write blob to a temporary file on disk.
3841 */
3842 ping_info->blob=(void *) NULL;
3843 ping_info->length=0;
3844 *ping_info->filename='\0';
3845 status=BlobToFile(ping_info->filename,blob,length,exception);
3846 if (status == MagickFalse)
3847 {
3848 (void) RelinquishUniqueFileResource(ping_info->filename);
3849 ping_info=DestroyImageInfo(ping_info);
3850 return((Image *) NULL);
3851 }
3852 clone_info=CloneImageInfo(ping_info);
3853 (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3854 ping_info->magick,ping_info->filename);
3855 image=ReadStream(clone_info,&PingStream,exception);
3856 if (image != (Image *) NULL)
3857 {
3858 Image
3859 *images;
3860
3861 /*
3862 Restore original filenames and image format.
3863 */
3864 for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3865 {
3866 (void) CopyMagickString(images->filename,image_info->filename,
3867 MagickPathExtent);
3868 (void) CopyMagickString(images->magick_filename,image_info->filename,
3869 MagickPathExtent);
3870 (void) CopyMagickString(images->magick,magick_info->name,
3871 MagickPathExtent);
3872 images=GetNextImageInList(images);
3873 }
3874 }
3875 clone_info=DestroyImageInfo(clone_info);
3876 (void) RelinquishUniqueFileResource(ping_info->filename);
3877 ping_info=DestroyImageInfo(ping_info);
3878 return(image);
3879}
3880␌
3881/*
3882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3883% %
3884% %
3885% %
3886+ R e a d B l o b %
3887% %
3888% %
3889% %
3890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3891%
3892% ReadBlob() reads data from the blob or image file and returns it. It
3893% returns the number of bytes read. If length is zero, ReadBlob() returns
3894% zero and has no other results. If length is greater than MAGICK_SSIZE_MAX,
3895% the result is unspecified.
3896%
3897% The format of the ReadBlob method is:
3898%
3899% ssize_t ReadBlob(Image *image,const size_t length,void *data)
3900%
3901% A description of each parameter follows:
3902%
3903% o image: the image.
3904%
3905% o length: Specifies an integer representing the number of bytes to read
3906% from the file.
3907%
3908% o data: Specifies an area to place the information requested from the
3909% file.
3910%
3911*/
3912MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3913{
3914 BlobInfo
3915 *magick_restrict blob_info;
3916
3917 int
3918 c;
3919
3920 ssize_t
3921 count;
3922
3923 unsigned char
3924 *q;
3925
3926 assert(image != (Image *) NULL);
3927 assert(image->signature == MagickCoreSignature);
3928 assert(image->blob != (BlobInfo *) NULL);
3929 assert(image->blob->type != UndefinedStream);
3930 if (length == 0)
3931 return(0);
3932 assert(data != (void *) NULL);
3933 blob_info=image->blob;
3934 count=0;
3935 q=(unsigned char *) data;
3936 switch (blob_info->type)
3937 {
3938 case UndefinedStream:
3939 break;
3940 case StandardStream:
3941 case FileStream:
3942 case PipeStream:
3943 {
3944 switch (length)
3945 {
3946 default:
3947 {
3948 count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3949 break;
3950 }
3951 case 4:
3952 {
3953 c=getc(blob_info->file_info.file);
3954 if (c == EOF)
3955 break;
3956 *q++=(unsigned char) c;
3957 count++;
3958 magick_fallthrough;
3959 }
3960 case 3:
3961 {
3962 c=getc(blob_info->file_info.file);
3963 if (c == EOF)
3964 break;
3965 *q++=(unsigned char) c;
3966 count++;
3967 magick_fallthrough;
3968 }
3969 case 2:
3970 {
3971 c=getc(blob_info->file_info.file);
3972 if (c == EOF)
3973 break;
3974 *q++=(unsigned char) c;
3975 count++;
3976 magick_fallthrough;
3977 }
3978 case 1:
3979 {
3980 c=getc(blob_info->file_info.file);
3981 if (c == EOF)
3982 break;
3983 *q++=(unsigned char) c;
3984 count++;
3985 magick_fallthrough;
3986 }
3987 case 0:
3988 break;
3989 }
3990 if ((count != (ssize_t) length) &&
3991 (ferror(blob_info->file_info.file) != 0))
3992 ThrowBlobException(blob_info);
3993 break;
3994 }
3995 case ZipStream:
3996 {
3997#if defined(MAGICKCORE_ZLIB_DELEGATE)
3998 int
3999 status;
4000
4001 switch (length)
4002 {
4003 default:
4004 {
4005 size_t
4006 i;
4007
4008 for (i=0; i < length; i+=(size_t) count)
4009 {
4010 count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
4011 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
4012 if (count <= 0)
4013 {
4014 count=0;
4015 if (errno != EINTR)
4016 break;
4017 }
4018 }
4019 count=(ssize_t) i;
4020 break;
4021 }
4022 case 4:
4023 {
4024 c=gzgetc(blob_info->file_info.gzfile);
4025 if (c == EOF)
4026 break;
4027 *q++=(unsigned char) c;
4028 count++;
4029 magick_fallthrough;
4030 }
4031 case 3:
4032 {
4033 c=gzgetc(blob_info->file_info.gzfile);
4034 if (c == EOF)
4035 break;
4036 *q++=(unsigned char) c;
4037 count++;
4038 magick_fallthrough;
4039 }
4040 case 2:
4041 {
4042 c=gzgetc(blob_info->file_info.gzfile);
4043 if (c == EOF)
4044 break;
4045 *q++=(unsigned char) c;
4046 count++;
4047 magick_fallthrough;
4048 }
4049 case 1:
4050 {
4051 c=gzgetc(blob_info->file_info.gzfile);
4052 if (c == EOF)
4053 break;
4054 *q++=(unsigned char) c;
4055 count++;
4056 }
4057 case 0:
4058 break;
4059 }
4060 status=Z_OK;
4061 (void) gzerror(blob_info->file_info.gzfile,&status);
4062 if ((count != (ssize_t) length) && (status != Z_OK))
4063 ThrowBlobException(blob_info);
4064 if (blob_info->eof == MagickFalse)
4065 blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
4066 MagickFalse;
4067#endif
4068 break;
4069 }
4070 case BZipStream:
4071 {
4072#if defined(MAGICKCORE_BZLIB_DELEGATE)
4073 int
4074 status;
4075
4076 size_t
4077 i;
4078
4079 if (blob_info->status != 0)
4080 break;
4081 for (i=0; i < length; i+=(size_t) count)
4082 {
4083 count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,(int)
4084 MagickMin(length-i,MagickMaxBufferExtent));
4085 if (count <= 0)
4086 {
4087 count=0;
4088 if (errno != EINTR)
4089 break;
4090 }
4091 }
4092 count=(ssize_t) i;
4093 status=BZ_OK;
4094 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
4095 if ((count != (ssize_t) length) && (status != BZ_OK))
4096 ThrowBlobException(blob_info);
4097 if ((count != (ssize_t) length) && (status == BZ_OK))
4098 blob_info->eof=MagickTrue;
4099#endif
4100 break;
4101 }
4102 case FifoStream:
4103 break;
4104 case BlobStream:
4105 {
4106 const unsigned char
4107 *p;
4108
4109 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4110 {
4111 blob_info->eof=MagickTrue;
4112 break;
4113 }
4114 p=blob_info->data+blob_info->offset;
4115 count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4116 blob_info->length-blob_info->offset);
4117 blob_info->offset+=count;
4118 if (count != (ssize_t) length)
4119 blob_info->eof=MagickTrue;
4120 (void) memcpy(q,p,(size_t) count);
4121 break;
4122 }
4123 case CustomStream:
4124 {
4125 if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
4126 count=blob_info->custom_stream->reader(q,length,
4127 blob_info->custom_stream->data);
4128 break;
4129 }
4130 }
4131 return(count);
4132}
4133␌
4134/*
4135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4136% %
4137% %
4138% %
4139+ R e a d B l o b B y t e %
4140% %
4141% %
4142% %
4143%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4144%
4145% ReadBlobByte() reads a single byte from the image file and returns it.
4146%
4147% The format of the ReadBlobByte method is:
4148%
4149% int ReadBlobByte(Image *image)
4150%
4151% A description of each parameter follows.
4152%
4153% o image: the image.
4154%
4155*/
4156MagickExport int ReadBlobByte(Image *image)
4157{
4158 BlobInfo
4159 *magick_restrict blob_info;
4160
4161 int
4162 c;
4163
4164 assert(image != (Image *) NULL);
4165 assert(image->signature == MagickCoreSignature);
4166 assert(image->blob != (BlobInfo *) NULL);
4167 assert(image->blob->type != UndefinedStream);
4168 blob_info=image->blob;
4169 switch (blob_info->type)
4170 {
4171 case StandardStream:
4172 case FileStream:
4173 case PipeStream:
4174 {
4175 c=getc(blob_info->file_info.file);
4176 if (c == EOF)
4177 {
4178 if (ferror(blob_info->file_info.file) != 0)
4179 ThrowBlobException(blob_info);
4180 return(EOF);
4181 }
4182 break;
4183 }
4184 case BlobStream:
4185 {
4186 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4187 {
4188 blob_info->eof=MagickTrue;
4189 return(EOF);
4190 }
4191 c=(int) (*((unsigned char *) blob_info->data+blob_info->offset));
4192 blob_info->offset++;
4193 break;
4194 }
4195 default:
4196 {
4197 ssize_t
4198 count;
4199
4200 unsigned char
4201 buffer[1];
4202
4203 count=ReadBlob(image,1,buffer);
4204 if (count != 1)
4205 return(EOF);
4206 c=(int) *buffer;
4207 break;
4208 }
4209 }
4210 return(c);
4211}
4212␌
4213/*
4214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4215% %
4216% %
4217% %
4218+ R e a d B l o b D o u b l e %
4219% %
4220% %
4221% %
4222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4223%
4224% ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
4225% specified by the endian member of the image structure.
4226%
4227% The format of the ReadBlobDouble method is:
4228%
4229% double ReadBlobDouble(Image *image)
4230%
4231% A description of each parameter follows.
4232%
4233% o image: the image.
4234%
4235*/
4236MagickExport double ReadBlobDouble(Image *image)
4237{
4238 union
4239 {
4240 MagickSizeType
4241 unsigned_value;
4242
4243 double
4244 double_value;
4245 } quantum;
4246
4247 quantum.double_value=0.0;
4248 quantum.unsigned_value=ReadBlobLongLong(image);
4249 return(quantum.double_value);
4250}
4251␌
4252/*
4253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4254% %
4255% %
4256% %
4257+ R e a d B l o b F l o a t %
4258% %
4259% %
4260% %
4261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4262%
4263% ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
4264% specified by the endian member of the image structure.
4265%
4266% The format of the ReadBlobFloat method is:
4267%
4268% float ReadBlobFloat(Image *image)
4269%
4270% A description of each parameter follows.
4271%
4272% o image: the image.
4273%
4274*/
4275MagickExport float ReadBlobFloat(Image *image)
4276{
4277 union
4278 {
4279 unsigned int
4280 unsigned_value;
4281
4282 float
4283 float_value;
4284 } quantum;
4285
4286 quantum.float_value=0.0;
4287 quantum.unsigned_value=ReadBlobLong(image);
4288 return(quantum.float_value);
4289}
4290␌
4291/*
4292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4293% %
4294% %
4295% %
4296+ R e a d B l o b L o n g %
4297% %
4298% %
4299% %
4300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4301%
4302% ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
4303% byte-order specified by the endian member of the image structure.
4304%
4305% The format of the ReadBlobLong method is:
4306%
4307% unsigned int ReadBlobLong(Image *image)
4308%
4309% A description of each parameter follows.
4310%
4311% o image: the image.
4312%
4313*/
4314MagickExport unsigned int ReadBlobLong(Image *image)
4315{
4316 const unsigned char
4317 *p;
4318
4319 ssize_t
4320 count;
4321
4322 unsigned char
4323 buffer[4];
4324
4325 unsigned int
4326 value;
4327
4328 assert(image != (Image *) NULL);
4329 assert(image->signature == MagickCoreSignature);
4330 *buffer='\0';
4331 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4332 if (count != 4)
4333 return(0UL);
4334 if (image->endian == LSBEndian)
4335 {
4336 value=(unsigned int) (*p++);
4337 value|=(unsigned int) (*p++) << 8;
4338 value|=(unsigned int) (*p++) << 16;
4339 value|=(unsigned int) (*p++) << 24;
4340 return(value);
4341 }
4342 value=(unsigned int) (*p++) << 24;
4343 value|=(unsigned int) (*p++) << 16;
4344 value|=(unsigned int) (*p++) << 8;
4345 value|=(unsigned int) (*p++);
4346 return(value);
4347}
4348␌
4349/*
4350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4351% %
4352% %
4353% %
4354+ R e a d B l o b L o n g L o n g %
4355% %
4356% %
4357% %
4358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4359%
4360% ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
4361% byte-order specified by the endian member of the image structure.
4362%
4363% The format of the ReadBlobLongLong method is:
4364%
4365% MagickSizeType ReadBlobLongLong(Image *image)
4366%
4367% A description of each parameter follows.
4368%
4369% o image: the image.
4370%
4371*/
4372MagickExport MagickSizeType ReadBlobLongLong(Image *image)
4373{
4374 MagickSizeType
4375 value;
4376
4377 const unsigned char
4378 *p;
4379
4380 ssize_t
4381 count;
4382
4383 unsigned char
4384 buffer[8];
4385
4386 assert(image != (Image *) NULL);
4387 assert(image->signature == MagickCoreSignature);
4388 *buffer='\0';
4389 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4390 if (count != 8)
4391 return(MagickULLConstant(0));
4392 if (image->endian == LSBEndian)
4393 {
4394 value=(MagickSizeType) (*p++);
4395 value|=(MagickSizeType) (*p++) << 8;
4396 value|=(MagickSizeType) (*p++) << 16;
4397 value|=(MagickSizeType) (*p++) << 24;
4398 value|=(MagickSizeType) (*p++) << 32;
4399 value|=(MagickSizeType) (*p++) << 40;
4400 value|=(MagickSizeType) (*p++) << 48;
4401 value|=(MagickSizeType) (*p++) << 56;
4402 return(value);
4403 }
4404 value=(MagickSizeType) (*p++) << 56;
4405 value|=(MagickSizeType) (*p++) << 48;
4406 value|=(MagickSizeType) (*p++) << 40;
4407 value|=(MagickSizeType) (*p++) << 32;
4408 value|=(MagickSizeType) (*p++) << 24;
4409 value|=(MagickSizeType) (*p++) << 16;
4410 value|=(MagickSizeType) (*p++) << 8;
4411 value|=(MagickSizeType) (*p++);
4412 return(value);
4413}
4414␌
4415/*
4416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4417% %
4418% %
4419% %
4420+ R e a d B l o b S h o r t %
4421% %
4422% %
4423% %
4424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4425%
4426% ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
4427% specified by the endian member of the image structure.
4428%
4429% The format of the ReadBlobShort method is:
4430%
4431% unsigned short ReadBlobShort(Image *image)
4432%
4433% A description of each parameter follows.
4434%
4435% o image: the image.
4436%
4437*/
4438MagickExport unsigned short ReadBlobShort(Image *image)
4439{
4440 const unsigned char
4441 *p;
4442
4443 unsigned short
4444 value;
4445
4446 ssize_t
4447 count;
4448
4449 unsigned char
4450 buffer[2];
4451
4452 assert(image != (Image *) NULL);
4453 assert(image->signature == MagickCoreSignature);
4454 *buffer='\0';
4455 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4456 if (count != 2)
4457 return((unsigned short) 0U);
4458 if (image->endian == LSBEndian)
4459 {
4460 value=(unsigned short) (*p++);
4461 value|=(unsigned short) (*p++) << 8;
4462 return(value);
4463 }
4464 value=(unsigned short) ((unsigned short) (*p++) << 8);
4465 value|=(unsigned short) (*p++);
4466 return(value);
4467}
4468␌
4469/*
4470%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4471% %
4472% %
4473% %
4474+ R e a d B l o b L S B L o n g %
4475% %
4476% %
4477% %
4478%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4479%
4480% ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
4481% least-significant byte first order.
4482%
4483% The format of the ReadBlobLSBLong method is:
4484%
4485% unsigned int ReadBlobLSBLong(Image *image)
4486%
4487% A description of each parameter follows.
4488%
4489% o image: the image.
4490%
4491*/
4492MagickExport unsigned int ReadBlobLSBLong(Image *image)
4493{
4494 const unsigned char
4495 *p;
4496
4497 unsigned int
4498 value;
4499
4500 ssize_t
4501 count;
4502
4503 unsigned char
4504 buffer[4];
4505
4506 assert(image != (Image *) NULL);
4507 assert(image->signature == MagickCoreSignature);
4508 *buffer='\0';
4509 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4510 if (count != 4)
4511 return(0U);
4512 value=(unsigned int) (*p++);
4513 value|=(unsigned int) (*p++) << 8;
4514 value|=(unsigned int) (*p++) << 16;
4515 value|=(unsigned int) (*p++) << 24;
4516 return(value);
4517}
4518␌
4519/*
4520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4521% %
4522% %
4523% %
4524+ R e a d B l o b L S B S i g n e d L o n g %
4525% %
4526% %
4527% %
4528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4529%
4530% ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
4531% least-significant byte first order.
4532%
4533% The format of the ReadBlobLSBSignedLong method is:
4534%
4535% signed int ReadBlobLSBSignedLong(Image *image)
4536%
4537% A description of each parameter follows.
4538%
4539% o image: the image.
4540%
4541*/
4542MagickExport signed int ReadBlobLSBSignedLong(Image *image)
4543{
4544 union
4545 {
4546 unsigned int
4547 unsigned_value;
4548
4549 signed int
4550 signed_value;
4551 } quantum;
4552
4553 quantum.unsigned_value=ReadBlobLSBLong(image);
4554 return(quantum.signed_value);
4555}
4556␌
4557/*
4558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4559% %
4560% %
4561% %
4562+ R e a d B l o b L S B S h o r t %
4563% %
4564% %
4565% %
4566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4567%
4568% ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4569% least-significant byte first order.
4570%
4571% The format of the ReadBlobLSBShort method is:
4572%
4573% unsigned short ReadBlobLSBShort(Image *image)
4574%
4575% A description of each parameter follows.
4576%
4577% o image: the image.
4578%
4579*/
4580MagickExport unsigned short ReadBlobLSBShort(Image *image)
4581{
4582 const unsigned char
4583 *p;
4584
4585 unsigned short
4586 value;
4587
4588 ssize_t
4589 count;
4590
4591 unsigned char
4592 buffer[2];
4593
4594 assert(image != (Image *) NULL);
4595 assert(image->signature == MagickCoreSignature);
4596 *buffer='\0';
4597 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4598 if (count != 2)
4599 return((unsigned short) 0U);
4600 value=(unsigned short) (*p++);
4601 value|=(unsigned short) (*p++) << 8;
4602 return(value);
4603}
4604␌
4605/*
4606%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4607% %
4608% %
4609% %
4610+ R e a d B l o b L S B S i g n e d S h o r t %
4611% %
4612% %
4613% %
4614%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4615%
4616% ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4617% least-significant byte-order.
4618%
4619% The format of the ReadBlobLSBSignedShort method is:
4620%
4621% signed short ReadBlobLSBSignedShort(Image *image)
4622%
4623% A description of each parameter follows.
4624%
4625% o image: the image.
4626%
4627*/
4628MagickExport signed short ReadBlobLSBSignedShort(Image *image)
4629{
4630 union
4631 {
4632 unsigned short
4633 unsigned_value;
4634
4635 signed short
4636 signed_value;
4637 } quantum;
4638
4639 quantum.unsigned_value=ReadBlobLSBShort(image);
4640 return(quantum.signed_value);
4641}
4642␌
4643/*
4644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4645% %
4646% %
4647% %
4648+ R e a d B l o b M S B L o n g %
4649% %
4650% %
4651% %
4652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4653%
4654% ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4655% most-significant byte first order.
4656%
4657% The format of the ReadBlobMSBLong method is:
4658%
4659% unsigned int ReadBlobMSBLong(Image *image)
4660%
4661% A description of each parameter follows.
4662%
4663% o image: the image.
4664%
4665*/
4666MagickExport unsigned int ReadBlobMSBLong(Image *image)
4667{
4668 const unsigned char
4669 *p;
4670
4671 unsigned int
4672 value;
4673
4674 ssize_t
4675 count;
4676
4677 unsigned char
4678 buffer[4];
4679
4680 assert(image != (Image *) NULL);
4681 assert(image->signature == MagickCoreSignature);
4682 *buffer='\0';
4683 p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4684 if (count != 4)
4685 return(0UL);
4686 value=(unsigned int) (*p++) << 24;
4687 value|=(unsigned int) (*p++) << 16;
4688 value|=(unsigned int) (*p++) << 8;
4689 value|=(unsigned int) (*p++);
4690 return(value);
4691}
4692␌
4693/*
4694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4695% %
4696% %
4697% %
4698+ R e a d B l o b M S B L o n g L o n g %
4699% %
4700% %
4701% %
4702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4703%
4704% ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4705% in most-significant byte first order.
4706%
4707% The format of the ReadBlobMSBLongLong method is:
4708%
4709% unsigned int ReadBlobMSBLongLong(Image *image)
4710%
4711% A description of each parameter follows.
4712%
4713% o image: the image.
4714%
4715*/
4716MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
4717{
4718 const unsigned char
4719 *p;
4720
4721 MagickSizeType
4722 value;
4723
4724 ssize_t
4725 count;
4726
4727 unsigned char
4728 buffer[8];
4729
4730 assert(image != (Image *) NULL);
4731 assert(image->signature == MagickCoreSignature);
4732 *buffer='\0';
4733 p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4734 if (count != 8)
4735 return(MagickULLConstant(0));
4736 value=(MagickSizeType) (*p++) << 56;
4737 value|=(MagickSizeType) (*p++) << 48;
4738 value|=(MagickSizeType) (*p++) << 40;
4739 value|=(MagickSizeType) (*p++) << 32;
4740 value|=(MagickSizeType) (*p++) << 24;
4741 value|=(MagickSizeType) (*p++) << 16;
4742 value|=(MagickSizeType) (*p++) << 8;
4743 value|=(MagickSizeType) (*p++);
4744 return(value);
4745}
4746␌
4747/*
4748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4749% %
4750% %
4751% %
4752+ R e a d B l o b M S B S h o r t %
4753% %
4754% %
4755% %
4756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4757%
4758% ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4759% most-significant byte first order.
4760%
4761% The format of the ReadBlobMSBShort method is:
4762%
4763% unsigned short ReadBlobMSBShort(Image *image)
4764%
4765% A description of each parameter follows.
4766%
4767% o image: the image.
4768%
4769*/
4770MagickExport unsigned short ReadBlobMSBShort(Image *image)
4771{
4772 const unsigned char
4773 *p;
4774
4775 unsigned short
4776 value;
4777
4778 ssize_t
4779 count;
4780
4781 unsigned char
4782 buffer[2];
4783
4784 assert(image != (Image *) NULL);
4785 assert(image->signature == MagickCoreSignature);
4786 *buffer='\0';
4787 p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4788 if (count != 2)
4789 return((unsigned short) 0U);
4790 value=(unsigned short) ((*p++) << 8);
4791 value|=(unsigned short) (*p++);
4792 return((unsigned short) (value & 0xffff));
4793}
4794␌
4795/*
4796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4797% %
4798% %
4799% %
4800+ R e a d B l o b M S B S i g n e d L o n g %
4801% %
4802% %
4803% %
4804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4805%
4806% ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4807% most-significant byte-order.
4808%
4809% The format of the ReadBlobMSBSignedLong method is:
4810%
4811% signed int ReadBlobMSBSignedLong(Image *image)
4812%
4813% A description of each parameter follows.
4814%
4815% o image: the image.
4816%
4817*/
4818MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4819{
4820 union
4821 {
4822 unsigned int
4823 unsigned_value;
4824
4825 signed int
4826 signed_value;
4827 } quantum;
4828
4829 quantum.unsigned_value=ReadBlobMSBLong(image);
4830 return(quantum.signed_value);
4831}
4832␌
4833/*
4834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4835% %
4836% %
4837% %
4838+ R e a d B l o b M S B S i g n e d S h o r t %
4839% %
4840% %
4841% %
4842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4843%
4844% ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4845% most-significant byte-order.
4846%
4847% The format of the ReadBlobMSBSignedShort method is:
4848%
4849% signed short ReadBlobMSBSignedShort(Image *image)
4850%
4851% A description of each parameter follows.
4852%
4853% o image: the image.
4854%
4855*/
4856MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4857{
4858 union
4859 {
4860 unsigned short
4861 unsigned_value;
4862
4863 signed short
4864 signed_value;
4865 } quantum;
4866
4867 quantum.unsigned_value=ReadBlobMSBShort(image);
4868 return(quantum.signed_value);
4869}
4870␌
4871/*
4872%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4873% %
4874% %
4875% %
4876+ R e a d B l o b S i g n e d L o n g %
4877% %
4878% %
4879% %
4880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4881%
4882% ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4883% byte-order specified by the endian member of the image structure.
4884%
4885% The format of the ReadBlobSignedLong method is:
4886%
4887% signed int ReadBlobSignedLong(Image *image)
4888%
4889% A description of each parameter follows.
4890%
4891% o image: the image.
4892%
4893*/
4894MagickExport signed int ReadBlobSignedLong(Image *image)
4895{
4896 union
4897 {
4898 unsigned int
4899 unsigned_value;
4900
4901 signed int
4902 signed_value;
4903 } quantum;
4904
4905 quantum.unsigned_value=ReadBlobLong(image);
4906 return(quantum.signed_value);
4907}
4908␌
4909/*
4910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4911% %
4912% %
4913% %
4914+ R e a d B l o b S i g n e d S h o r t %
4915% %
4916% %
4917% %
4918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4919%
4920% ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4921% byte-order specified by the endian member of the image structure.
4922%
4923% The format of the ReadBlobSignedShort method is:
4924%
4925% signed short ReadBlobSignedShort(Image *image)
4926%
4927% A description of each parameter follows.
4928%
4929% o image: the image.
4930%
4931*/
4932MagickExport signed short ReadBlobSignedShort(Image *image)
4933{
4934 union
4935 {
4936 unsigned short
4937 unsigned_value;
4938
4939 signed short
4940 signed_value;
4941 } quantum;
4942
4943 quantum.unsigned_value=ReadBlobShort(image);
4944 return(quantum.signed_value);
4945}
4946␌
4947/*
4948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4949% %
4950% %
4951% %
4952+ R e a d B l o b S t r e a m %
4953% %
4954% %
4955% %
4956%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4957%
4958% ReadBlobStream() reads data from the blob or image file and returns it. It
4959% returns a pointer to the data buffer you supply or to the image memory
4960% buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4961% returns a count of zero and has no other results. If length is greater than
4962% MAGICK_SSIZE_MAX, the result is unspecified.
4963%
4964% The format of the ReadBlobStream method is:
4965%
4966% const void *ReadBlobStream(Image *image,const size_t length,
4967% void *magick_restrict data,ssize_t *count)
4968%
4969% A description of each parameter follows:
4970%
4971% o image: the image.
4972%
4973% o length: Specifies an integer representing the number of bytes to read
4974% from the file.
4975%
4976% o count: returns the number of bytes read.
4977%
4978% o data: Specifies an area to place the information requested from the
4979% file.
4980%
4981*/
4982MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
4983 const size_t length,void *magick_restrict data,ssize_t *count)
4984{
4985 BlobInfo
4986 *magick_restrict blob_info;
4987
4988 assert(image != (Image *) NULL);
4989 assert(image->signature == MagickCoreSignature);
4990 assert(image->blob != (BlobInfo *) NULL);
4991 assert(image->blob->type != UndefinedStream);
4992 assert(count != (ssize_t *) NULL);
4993 blob_info=image->blob;
4994 if (blob_info->type != BlobStream)
4995 {
4996 assert(data != NULL);
4997 *count=ReadBlob(image,length,(unsigned char *) data);
4998 return(data);
4999 }
5000 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5001 {
5002 *count=0;
5003 blob_info->eof=MagickTrue;
5004 return(data);
5005 }
5006 data=blob_info->data+blob_info->offset;
5007 *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
5008 blob_info->length-blob_info->offset);
5009 blob_info->offset+=(*count);
5010 if (*count != (ssize_t) length)
5011 blob_info->eof=MagickTrue;
5012 return(data);
5013}
5014␌
5015/*
5016%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5017% %
5018% %
5019% %
5020+ R e a d B l o b S t r i n g %
5021% %
5022% %
5023% %
5024%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5025%
5026% ReadBlobString() reads characters from a blob or file until a newline
5027% character is read or an end-of-file condition is encountered.
5028%
5029% The format of the ReadBlobString method is:
5030%
5031% char *ReadBlobString(Image *image,char *string)
5032%
5033% A description of each parameter follows:
5034%
5035% o image: the image.
5036%
5037% o string: the address of a character buffer.
5038%
5039*/
5040MagickExport char *ReadBlobString(Image *image,char *string)
5041{
5042 BlobInfo
5043 *magick_restrict blob_info;
5044
5045 int
5046 c = -1;
5047
5048 size_t
5049 i = 0;
5050
5051 assert(image != (Image *) NULL);
5052 assert(image->signature == MagickCoreSignature);
5053 assert(image->blob != (BlobInfo *) NULL);
5054 assert(image->blob->type != UndefinedStream);
5055 if (IsEventLogging() != MagickFalse)
5056 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5057 *string='\0';
5058 blob_info=image->blob;
5059 switch (blob_info->type)
5060 {
5061 case UndefinedStream:
5062 break;
5063 case StandardStream:
5064 case FileStream:
5065 {
5066 char *p = fgets(string,MagickPathExtent,blob_info->file_info.file);
5067 if (p == (char *) NULL)
5068 {
5069 if (ferror(blob_info->file_info.file) != 0)
5070 ThrowBlobException(blob_info);
5071 return((char *) NULL);
5072 }
5073 i=strlen(string);
5074 break;
5075 }
5076 case ZipStream:
5077 {
5078#if defined(MAGICKCORE_ZLIB_DELEGATE)
5079 char *p = gzgets(blob_info->file_info.gzfile,string,MagickPathExtent);
5080 if (p == (char *) NULL)
5081 {
5082 int status = Z_OK;
5083 (void) gzerror(blob_info->file_info.gzfile,&status);
5084 if (status != Z_OK)
5085 ThrowBlobException(blob_info);
5086 return((char *) NULL);
5087 }
5088 i=strlen(string);
5089 break;
5090#endif
5091 }
5092 default:
5093 {
5094 do
5095 {
5096 c=ReadBlobByte(image);
5097 if (c == EOF)
5098 {
5099 blob_info->eof=MagickTrue;
5100 break;
5101 }
5102 string[i++]=c;
5103 if (c == '\n')
5104 break;
5105 } while (i < (MaxTextExtent-2));
5106 string[i]='\0';
5107 break;
5108 }
5109 }
5110 /*
5111 Strip trailing newline.
5112 */
5113 if ((string[i] == '\r') || (string[i] == '\n'))
5114 string[i]='\0';
5115 if (i >= 1)
5116 if ((string[i-1] == '\r') || (string[i-1] == '\n'))
5117 string[i-1]='\0';
5118 if ((*string == '\0') && (blob_info->eof != MagickFalse))
5119 return((char *) NULL);
5120 return(string);
5121}
5122␌
5123/*
5124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5125% %
5126% %
5127% %
5128+ R e f e r e n c e B l o b %
5129% %
5130% %
5131% %
5132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5133%
5134% ReferenceBlob() increments the reference count associated with the pixel
5135% blob returning a pointer to the blob.
5136%
5137% The format of the ReferenceBlob method is:
5138%
5139% BlobInfo ReferenceBlob(BlobInfo *blob_info)
5140%
5141% A description of each parameter follows:
5142%
5143% o blob_info: the blob_info.
5144%
5145*/
5146MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
5147{
5148 assert(blob != (BlobInfo *) NULL);
5149 assert(blob->signature == MagickCoreSignature);
5150 if (IsEventLogging() != MagickFalse)
5151 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5152 LockSemaphoreInfo(blob->semaphore);
5153 blob->reference_count++;
5154 UnlockSemaphoreInfo(blob->semaphore);
5155 return(blob);
5156}
5157␌
5158/*
5159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5160% %
5161% %
5162% %
5163+ S e e k B l o b %
5164% %
5165% %
5166% %
5167%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5168%
5169% SeekBlob() sets the offset in bytes from the beginning of a blob or file
5170% and returns the resulting offset.
5171%
5172% The format of the SeekBlob method is:
5173%
5174% MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
5175% const int whence)
5176%
5177% A description of each parameter follows:
5178%
5179% o image: the image.
5180%
5181% o offset: Specifies an integer representing the offset in bytes.
5182%
5183% o whence: Specifies an integer representing how the offset is
5184% treated relative to the beginning of the blob as follows:
5185%
5186% SEEK_SET Set position equal to offset bytes.
5187% SEEK_CUR Set position to current location plus offset.
5188% SEEK_END Set position to EOF plus offset.
5189%
5190*/
5191MagickExport MagickOffsetType SeekBlob(Image *image,
5192 const MagickOffsetType offset,const int whence)
5193{
5194 BlobInfo
5195 *magick_restrict blob_info;
5196
5197 assert(image != (Image *) NULL);
5198 assert(image->signature == MagickCoreSignature);
5199 assert(image->blob != (BlobInfo *) NULL);
5200 assert(image->blob->type != UndefinedStream);
5201 if (IsEventLogging() != MagickFalse)
5202 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5203 blob_info=image->blob;
5204 switch (blob_info->type)
5205 {
5206 case UndefinedStream:
5207 break;
5208 case StandardStream:
5209 case PipeStream:
5210 return(-1);
5211 case FileStream:
5212 {
5213 if ((offset < 0) && (whence == SEEK_SET))
5214 return(-1);
5215 if (fseek(blob_info->file_info.file,offset,whence) < 0)
5216 return(-1);
5217 blob_info->offset=TellBlob(image);
5218 break;
5219 }
5220 case ZipStream:
5221 {
5222#if defined(MAGICKCORE_ZLIB_DELEGATE)
5223 if (gzseek(blob_info->file_info.gzfile,offset,whence) < 0)
5224 return(-1);
5225#endif
5226 blob_info->offset=TellBlob(image);
5227 break;
5228 }
5229 case BZipStream:
5230 return(-1);
5231 case FifoStream:
5232 return(-1);
5233 case BlobStream:
5234 {
5235 switch (whence)
5236 {
5237 case SEEK_SET:
5238 default:
5239 {
5240 if (offset < 0)
5241 return(-1);
5242 blob_info->offset=offset;
5243 break;
5244 }
5245 case SEEK_CUR:
5246 {
5247 if (((offset > 0) && (blob_info->offset > (MAGICK_SSIZE_MAX-offset))) ||
5248 ((offset < 0) && (blob_info->offset < (MAGICK_SSIZE_MIN-offset))))
5249 {
5250 errno=EOVERFLOW;
5251 return(-1);
5252 }
5253 if ((blob_info->offset+offset) < 0)
5254 return(-1);
5255 blob_info->offset+=offset;
5256 break;
5257 }
5258 case SEEK_END:
5259 {
5260 if (((MagickOffsetType) blob_info->length+offset) < 0)
5261 return(-1);
5262 blob_info->offset=(MagickOffsetType) blob_info->length+offset;
5263 break;
5264 }
5265 }
5266 if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
5267 {
5268 blob_info->eof=MagickFalse;
5269 break;
5270 }
5271 break;
5272 }
5273 case CustomStream:
5274 {
5275 if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
5276 return(-1);
5277 blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
5278 blob_info->custom_stream->data);
5279 break;
5280 }
5281 }
5282 return(blob_info->offset);
5283}
5284␌
5285/*
5286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5287% %
5288% %
5289% %
5290+ S e t B l o b E x e m p t %
5291% %
5292% %
5293% %
5294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5295%
5296% SetBlobExempt() sets the blob exempt status.
5297%
5298% The format of the SetBlobExempt method is:
5299%
5300% MagickBooleanType SetBlobExempt(const Image *image,
5301% const MagickBooleanType exempt)
5302%
5303% A description of each parameter follows:
5304%
5305% o image: the image.
5306%
5307% o exempt: Set to true if this blob is exempt from being closed.
5308%
5309*/
5310MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
5311{
5312 assert(image != (const Image *) NULL);
5313 assert(image->signature == MagickCoreSignature);
5314 if (IsEventLogging() != MagickFalse)
5315 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5316 image->blob->exempt=exempt;
5317}
5318␌
5319/*
5320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5321% %
5322% %
5323% %
5324+ S e t B l o b E x t e n t %
5325% %
5326% %
5327% %
5328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5329%
5330% SetBlobExtent() ensures enough space is allocated for the blob. If the
5331% method is successful, subsequent writes to bytes in the specified range are
5332% guaranteed not to fail.
5333%
5334% The format of the SetBlobExtent method is:
5335%
5336% MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
5337%
5338% A description of each parameter follows:
5339%
5340% o image: the image.
5341%
5342% o extent: the blob maximum extent.
5343%
5344*/
5345MagickExport MagickBooleanType SetBlobExtent(Image *image,
5346 const MagickSizeType extent)
5347{
5348 BlobInfo
5349 *magick_restrict blob_info;
5350
5351 assert(image != (Image *) NULL);
5352 assert(image->signature == MagickCoreSignature);
5353 assert(image->blob != (BlobInfo *) NULL);
5354 assert(image->blob->type != UndefinedStream);
5355 if (IsEventLogging() != MagickFalse)
5356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5357 blob_info=image->blob;
5358 switch (blob_info->type)
5359 {
5360 case UndefinedStream:
5361 break;
5362 case StandardStream:
5363 return(MagickFalse);
5364 case FileStream:
5365 {
5366 MagickOffsetType
5367 offset;
5368
5369 ssize_t
5370 count;
5371
5372 if (extent != (MagickSizeType) ((off_t) extent))
5373 return(MagickFalse);
5374 offset=SeekBlob(image,0,SEEK_END);
5375 if (offset < 0)
5376 return(MagickFalse);
5377 if ((MagickSizeType) offset >= extent)
5378 break;
5379 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5380 if (offset < 0)
5381 break;
5382 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5383 blob_info->file_info.file);
5384#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5385 if (blob_info->synchronize != MagickFalse)
5386 {
5387 int
5388 file;
5389
5390 file=fileno(blob_info->file_info.file);
5391 if ((file == -1) || (offset < 0))
5392 return(MagickFalse);
5393 (void) posix_fallocate(file,offset,(MagickOffsetType) extent-offset);
5394 }
5395#endif
5396 offset=SeekBlob(image,offset,SEEK_SET);
5397 if (count != 1)
5398 return(MagickFalse);
5399 break;
5400 }
5401 case PipeStream:
5402 case ZipStream:
5403 return(MagickFalse);
5404 case BZipStream:
5405 return(MagickFalse);
5406 case FifoStream:
5407 return(MagickFalse);
5408 case BlobStream:
5409 {
5410 if (extent != (MagickSizeType) ((size_t) extent))
5411 return(MagickFalse);
5412 if (blob_info->mapped != MagickFalse)
5413 {
5414 MagickOffsetType
5415 offset;
5416
5417 ssize_t
5418 count;
5419
5420 (void) UnmapBlob(blob_info->data,blob_info->length);
5421 RelinquishMagickResource(MapResource,blob_info->length);
5422 if (extent != (MagickSizeType) ((off_t) extent))
5423 return(MagickFalse);
5424 offset=SeekBlob(image,0,SEEK_END);
5425 if (offset < 0)
5426 return(MagickFalse);
5427 if ((MagickSizeType) offset >= extent)
5428 break;
5429 offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5430 count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5431 blob_info->file_info.file);
5432#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5433 if (blob_info->synchronize != MagickFalse)
5434 {
5435 int
5436 file;
5437
5438 file=fileno(blob_info->file_info.file);
5439 if ((file == -1) || (offset < 0))
5440 return(MagickFalse);
5441 (void) posix_fallocate(file,offset,(MagickOffsetType) extent-
5442 offset);
5443 }
5444#endif
5445 offset=SeekBlob(image,offset,SEEK_SET);
5446 if (count != 1)
5447 return(MagickFalse);
5448 (void) AcquireMagickResource(MapResource,extent);
5449 blob_info->data=(unsigned char*) MapBlob(fileno(
5450 blob_info->file_info.file),WriteMode,0,(size_t) extent);
5451 blob_info->extent=(size_t) extent;
5452 blob_info->length=(size_t) extent;
5453 (void) SyncBlob(image);
5454 break;
5455 }
5456 blob_info->extent=(size_t) extent;
5457 blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
5458 blob_info->extent+1,sizeof(*blob_info->data));
5459 (void) SyncBlob(image);
5460 if (blob_info->data == (unsigned char *) NULL)
5461 {
5462 (void) DetachBlob(blob_info);
5463 return(MagickFalse);
5464 }
5465 break;
5466 }
5467 case CustomStream:
5468 break;
5469 }
5470 return(MagickTrue);
5471}
5472␌
5473/*
5474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5475% %
5476% %
5477% %
5478+ S e t C u s t o m S t r e a m D a t a %
5479% %
5480% %
5481% %
5482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5483%
5484% SetCustomStreamData() sets the stream info data member.
5485%
5486% The format of the SetCustomStreamData method is:
5487%
5488% void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
5489%
5490% A description of each parameter follows:
5491%
5492% o custom_stream: the custom stream info.
5493%
5494% o data: an object containing information about the custom stream.
5495%
5496*/
5497MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
5498 void *data)
5499{
5500 assert(custom_stream != (CustomStreamInfo *) NULL);
5501 assert(custom_stream->signature == MagickCoreSignature);
5502 custom_stream->data=data;
5503}
5504␌
5505/*
5506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5507% %
5508% %
5509% %
5510+ S e t C u s t o m S t r e a m R e a d e r %
5511% %
5512% %
5513% %
5514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5515%
5516% SetCustomStreamReader() sets the stream info reader member.
5517%
5518% The format of the SetCustomStreamReader method is:
5519%
5520% void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5521% CustomStreamHandler reader)
5522%
5523% A description of each parameter follows:
5524%
5525% o custom_stream: the custom stream info.
5526%
5527% o reader: a function to read from the stream.
5528%
5529*/
5530MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5531 CustomStreamHandler reader)
5532{
5533 assert(custom_stream != (CustomStreamInfo *) NULL);
5534 assert(custom_stream->signature == MagickCoreSignature);
5535 custom_stream->reader=reader;
5536}
5537␌
5538/*
5539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5540% %
5541% %
5542% %
5543+ S e t C u s t o m S t r e a m S e e k e r %
5544% %
5545% %
5546% %
5547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5548%
5549% SetCustomStreamSeeker() sets the stream info seeker member.
5550%
5551% The format of the SetCustomStreamReader method is:
5552%
5553% void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5554% CustomStreamSeeker seeker)
5555%
5556% A description of each parameter follows:
5557%
5558% o custom_stream: the custom stream info.
5559%
5560% o seeker: a function to seek in the custom stream.
5561%
5562*/
5563MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5564 CustomStreamSeeker seeker)
5565{
5566 assert(custom_stream != (CustomStreamInfo *) NULL);
5567 assert(custom_stream->signature == MagickCoreSignature);
5568 custom_stream->seeker=seeker;
5569}
5570␌
5571/*
5572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5573% %
5574% %
5575% %
5576+ S e t C u s t o m S t r e a m T e l l e r %
5577% %
5578% %
5579% %
5580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5581%
5582% SetCustomStreamTeller() sets the stream info teller member.
5583%
5584% The format of the SetCustomStreamTeller method is:
5585%
5586% void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5587% CustomStreamTeller *teller)
5588%
5589% A description of each parameter follows:
5590%
5591% o custom_stream: the custom stream info.
5592%
5593% o teller: a function to set the position in the stream.
5594%
5595*/
5596MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5597 CustomStreamTeller teller)
5598{
5599 assert(custom_stream != (CustomStreamInfo *) NULL);
5600 assert(custom_stream->signature == MagickCoreSignature);
5601 custom_stream->teller=teller;
5602}
5603␌
5604/*
5605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5606% %
5607% %
5608% %
5609+ S e t C u s t o m S t r e a m W r i t e r %
5610% %
5611% %
5612% %
5613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5614%
5615% SetCustomStreamWriter() sets the stream info writer member.
5616%
5617% The format of the SetCustomStreamWriter method is:
5618%
5619% void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5620% CustomStreamHandler *writer)
5621%
5622% A description of each parameter follows:
5623%
5624% o custom_stream: the custom stream info.
5625%
5626% o writer: a function to write to the custom stream.
5627%
5628*/
5629MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5630 CustomStreamHandler writer)
5631{
5632 assert(custom_stream != (CustomStreamInfo *) NULL);
5633 assert(custom_stream->signature == MagickCoreSignature);
5634 custom_stream->writer=writer;
5635}
5636␌
5637/*
5638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5639% %
5640% %
5641% %
5642+ S y n c B l o b %
5643% %
5644% %
5645% %
5646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5647%
5648% SyncBlob() flushes the datastream if it is a file or synchronizes the data
5649% attributes if it is an blob. It returns 0 on success; otherwise, it returns
5650% -1 and set errno to indicate the error.
5651%
5652% The format of the SyncBlob method is:
5653%
5654% int SyncBlob(const Image *image)
5655%
5656% A description of each parameter follows:
5657%
5658% o image: the image.
5659%
5660*/
5661static int SyncBlob(const Image *image)
5662{
5663 BlobInfo
5664 *magick_restrict blob_info;
5665
5666 int
5667 status;
5668
5669 assert(image != (Image *) NULL);
5670 assert(image->signature == MagickCoreSignature);
5671 assert(image->blob != (BlobInfo *) NULL);
5672 if (IsEventLogging() != MagickFalse)
5673 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5674 if (EOFBlob(image) != 0)
5675 return(0);
5676 blob_info=image->blob;
5677 status=0;
5678 switch (blob_info->type)
5679 {
5680 case UndefinedStream:
5681 case StandardStream:
5682 break;
5683 case FileStream:
5684 case PipeStream:
5685 {
5686 status=fflush(blob_info->file_info.file);
5687 break;
5688 }
5689 case ZipStream:
5690 {
5691#if defined(MAGICKCORE_ZLIB_DELEGATE)
5692 (void) gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5693#endif
5694 break;
5695 }
5696 case BZipStream:
5697 {
5698#if defined(MAGICKCORE_BZLIB_DELEGATE)
5699 status=BZ2_bzflush(blob_info->file_info.bzfile);
5700#endif
5701 break;
5702 }
5703 case FifoStream:
5704 break;
5705 case BlobStream:
5706 break;
5707 case CustomStream:
5708 break;
5709 }
5710 return(status);
5711}
5712␌
5713/*
5714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5715% %
5716% %
5717% %
5718+ S y n c B l o b S t r e a m %
5719% %
5720% %
5721% %
5722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5723%
5724% SyncBlobStream() transfers ownership of an in-memory blob stream from the
5725% image that has just been written back to the owner image and to image info.
5726% The method copies the current buffer state onto the owner, refreshes
5727% image info, and detaches the borrower so exactly one object owns the memory.
5728%
5729% The format of the SyncBlobStream method is:
5730%
5731% void SyncBlobStream(ImageInfo *image,const Image *image,Image *owner)
5732%
5733% A description of each parameter follows:
5734%
5735% o image_info: image info whose blob/length members are refreshed; may be
5736% NULL.
5737%
5738% o owner: the image ImagesToBlob()/ImageToBlob() harvests the blob from
5739% (the head of the list).
5740%
5741% o image: the image that was just written; may be the owner.
5742%
5743*/
5744MagickPrivate void SyncBlobStream(ImageInfo *image_info,Image *image,
5745 Image *owner)
5746{
5747 assert(owner != (Image *) NULL);
5748 assert(image != (Image *) NULL);
5749 assert(image->signature == MagickCoreSignature);
5750 if (image->blob == (BlobInfo *) NULL)
5751 return;
5752 if (image->blob->data == (unsigned char *) NULL)
5753 return;
5754 if (image_info != (ImageInfo *) NULL)
5755 {
5756 image_info->blob=(void *) image->blob->data;
5757 image_info->length=image->blob->length;
5758 }
5759 if ((image == owner) || (owner->blob == (BlobInfo *) NULL))
5760 return;
5761 if (owner->blob == (BlobInfo *) NULL)
5762 return;
5763 /*
5764 Promote the live buffer onto the owner before detaching the borrower;
5765 DetachBlob() clears image->blob->data.
5766 */
5767 owner->blob->data=image->blob->data;
5768 owner->blob->extent=image->blob->extent;
5769 owner->blob->length=image->blob->length;
5770 owner->blob->offset=image->blob->offset;
5771 owner->blob->quantum=image->blob->quantum;
5772 owner->blob->type=BlobStream;
5773 owner->blob->exempt=MagickTrue;
5774 (void) DetachBlob(image->blob);
5775}
5776␌
5777/*
5778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5779% %
5780% %
5781% %
5782+ T e l l B l o b %
5783% %
5784% %
5785% %
5786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5787%
5788% TellBlob() obtains the current value of the blob or file position.
5789%
5790% The format of the TellBlob method is:
5791%
5792% MagickOffsetType TellBlob(const Image *image)
5793%
5794% A description of each parameter follows:
5795%
5796% o image: the image.
5797%
5798*/
5799MagickExport MagickOffsetType TellBlob(const Image *image)
5800{
5801 BlobInfo
5802 *magick_restrict blob_info;
5803
5804 MagickOffsetType
5805 offset;
5806
5807 assert(image != (Image *) NULL);
5808 assert(image->signature == MagickCoreSignature);
5809 assert(image->blob != (BlobInfo *) NULL);
5810 assert(image->blob->type != UndefinedStream);
5811 if (IsEventLogging() != MagickFalse)
5812 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5813 blob_info=image->blob;
5814 offset=(-1);
5815 switch (blob_info->type)
5816 {
5817 case UndefinedStream:
5818 case StandardStream:
5819 break;
5820 case FileStream:
5821 {
5822 offset=ftell(blob_info->file_info.file);
5823 break;
5824 }
5825 case PipeStream:
5826 break;
5827 case ZipStream:
5828 {
5829#if defined(MAGICKCORE_ZLIB_DELEGATE)
5830 offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5831#endif
5832 break;
5833 }
5834 case BZipStream:
5835 break;
5836 case FifoStream:
5837 break;
5838 case BlobStream:
5839 {
5840 offset=blob_info->offset;
5841 break;
5842 }
5843 case CustomStream:
5844 {
5845 if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5846 offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5847 break;
5848 }
5849 }
5850 return(offset);
5851}
5852␌
5853/*
5854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5855% %
5856% %
5857% %
5858+ U n m a p B l o b %
5859% %
5860% %
5861% %
5862%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5863%
5864% UnmapBlob() deallocates the binary large object previously allocated with
5865% the MapBlob method.
5866%
5867% The format of the UnmapBlob method is:
5868%
5869% MagickBooleanType UnmapBlob(void *map,const size_t length)
5870%
5871% A description of each parameter follows:
5872%
5873% o map: the address of the binary large object.
5874%
5875% o length: the length of the binary large object.
5876%
5877*/
5878MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5879{
5880#if defined(MAGICKCORE_HAVE_MMAP)
5881 int
5882 status;
5883
5884 status=munmap(map,length);
5885 return(status == -1 ? MagickFalse : MagickTrue);
5886#else
5887 (void) map;
5888 (void) length;
5889 return(MagickFalse);
5890#endif
5891}
5892␌
5893/*
5894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5895% %
5896% %
5897% %
5898+ W r i t e B l o b %
5899% %
5900% %
5901% %
5902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5903%
5904% WriteBlob() writes data to a blob or image file. It returns the number of
5905% bytes written.
5906%
5907% The format of the WriteBlob method is:
5908%
5909% ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5910%
5911% A description of each parameter follows:
5912%
5913% o image: the image.
5914%
5915% o length: Specifies an integer representing the number of bytes to
5916% write to the file.
5917%
5918% o data: The address of the data to write to the blob or file.
5919%
5920*/
5921MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5922 const void *data)
5923{
5924 BlobInfo
5925 *magick_restrict blob_info;
5926
5927 int
5928 c;
5929
5930 const unsigned char
5931 *p;
5932
5933 unsigned char
5934 *q;
5935
5936 ssize_t
5937 count;
5938
5939 assert(image != (Image *) NULL);
5940 assert(image->signature == MagickCoreSignature);
5941 assert(image->blob != (BlobInfo *) NULL);
5942 assert(image->blob->type != UndefinedStream);
5943 if (length == 0)
5944 return(0);
5945 assert(data != (const void *) NULL);
5946 blob_info=image->blob;
5947 count=0;
5948 p=(const unsigned char *) data;
5949 q=(unsigned char *) data;
5950 switch (blob_info->type)
5951 {
5952 case UndefinedStream:
5953 break;
5954 case StandardStream:
5955 case FileStream:
5956 case PipeStream:
5957 {
5958 switch (length)
5959 {
5960 default:
5961 {
5962 count=(ssize_t) fwrite((const char *) data,1,length,
5963 blob_info->file_info.file);
5964 break;
5965 }
5966 case 4:
5967 {
5968 c=putc((int) *p++,blob_info->file_info.file);
5969 if (c == EOF)
5970 break;
5971 count++;
5972 magick_fallthrough;
5973 }
5974 case 3:
5975 {
5976 c=putc((int) *p++,blob_info->file_info.file);
5977 if (c == EOF)
5978 break;
5979 count++;
5980 magick_fallthrough;
5981 }
5982 case 2:
5983 {
5984 c=putc((int) *p++,blob_info->file_info.file);
5985 if (c == EOF)
5986 break;
5987 count++;
5988 magick_fallthrough;
5989 }
5990 case 1:
5991 {
5992 c=putc((int) *p++,blob_info->file_info.file);
5993 if (c == EOF)
5994 break;
5995 count++;
5996 magick_fallthrough;
5997 }
5998 case 0:
5999 break;
6000 }
6001 if ((count != (ssize_t) length) &&
6002 (ferror(blob_info->file_info.file) != 0))
6003 ThrowBlobException(blob_info);
6004 break;
6005 }
6006 case ZipStream:
6007 {
6008#if defined(MAGICKCORE_ZLIB_DELEGATE)
6009 int
6010 status;
6011
6012 switch (length)
6013 {
6014 default:
6015 {
6016 size_t
6017 i;
6018
6019 for (i=0; i < length; i+=(size_t) count)
6020 {
6021 count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
6022 (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
6023 if (count <= 0)
6024 {
6025 count=0;
6026 if (errno != EINTR)
6027 break;
6028 }
6029 }
6030 count=(ssize_t) i;
6031 break;
6032 }
6033 case 4:
6034 {
6035 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6036 if (c == EOF)
6037 break;
6038 count++;
6039 magick_fallthrough;
6040 }
6041 case 3:
6042 {
6043 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6044 if (c == EOF)
6045 break;
6046 count++;
6047 magick_fallthrough;
6048 }
6049 case 2:
6050 {
6051 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6052 if (c == EOF)
6053 break;
6054 count++;
6055 magick_fallthrough;
6056 }
6057 case 1:
6058 {
6059 c=gzputc(blob_info->file_info.gzfile,(int) *p++);
6060 if (c == EOF)
6061 break;
6062 count++;
6063 magick_fallthrough;
6064 }
6065 case 0:
6066 break;
6067 }
6068 status=Z_OK;
6069 (void) gzerror(blob_info->file_info.gzfile,&status);
6070 if ((count != (ssize_t) length) && (status != Z_OK))
6071 ThrowBlobException(blob_info);
6072#endif
6073 break;
6074 }
6075 case BZipStream:
6076 {
6077#if defined(MAGICKCORE_BZLIB_DELEGATE)
6078 int
6079 status;
6080
6081 size_t
6082 i;
6083
6084 for (i=0; i < length; i+=(size_t) count)
6085 {
6086 count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
6087 (int) MagickMin(length-i,MagickMaxBufferExtent));
6088 if (count <= 0)
6089 {
6090 count=0;
6091 if (errno != EINTR)
6092 break;
6093 }
6094 }
6095 count=(ssize_t) i;
6096 status=BZ_OK;
6097 (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
6098 if ((count != (ssize_t) length) && (status != BZ_OK))
6099 ThrowBlobException(blob_info);
6100#endif
6101 break;
6102 }
6103 case FifoStream:
6104 {
6105 count=(ssize_t) blob_info->stream(image,data,length);
6106 break;
6107 }
6108 case BlobStream:
6109 {
6110 MagickSizeType
6111 extent;
6112
6113 extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
6114 if (extent >= blob_info->extent)
6115 {
6116 if (blob_info->mapped != MagickFalse)
6117 return(0);
6118 blob_info->extent=extent+blob_info->quantum+length;
6119 blob_info->quantum<<=1;
6120 blob_info->data=(unsigned char *) ResizeQuantumMemory(
6121 blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
6122 (void) SyncBlob(image);
6123 if (blob_info->data == (unsigned char *) NULL)
6124 {
6125 (void) DetachBlob(blob_info);
6126 return(0);
6127 }
6128 }
6129 q=blob_info->data+blob_info->offset;
6130 (void) memcpy(q,p,length);
6131 blob_info->offset+=(MagickOffsetType) length;
6132 if (blob_info->offset >= (MagickOffsetType) blob_info->length)
6133 blob_info->length=(size_t) blob_info->offset;
6134 count=(ssize_t) length;
6135 break;
6136 }
6137 case CustomStream:
6138 {
6139 if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
6140 count=blob_info->custom_stream->writer((unsigned char *) data,
6141 length,blob_info->custom_stream->data);
6142 break;
6143 }
6144 }
6145 return(count);
6146}
6147␌
6148/*
6149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6150% %
6151% %
6152% %
6153+ W r i t e B l o b B y t e %
6154% %
6155% %
6156% %
6157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6158%
6159% WriteBlobByte() write an integer to a blob. It returns the number of bytes
6160% written (either 0 or 1);
6161%
6162% The format of the WriteBlobByte method is:
6163%
6164% ssize_t WriteBlobByte(Image *image,const unsigned char value)
6165%
6166% A description of each parameter follows.
6167%
6168% o image: the image.
6169%
6170% o value: Specifies the value to write.
6171%
6172*/
6173MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
6174{
6175 BlobInfo
6176 *magick_restrict blob_info;
6177
6178 ssize_t
6179 count;
6180
6181 assert(image != (Image *) NULL);
6182 assert(image->signature == MagickCoreSignature);
6183 assert(image->blob != (BlobInfo *) NULL);
6184 assert(image->blob->type != UndefinedStream);
6185 blob_info=image->blob;
6186 count=0;
6187 switch (blob_info->type)
6188 {
6189 case StandardStream:
6190 case FileStream:
6191 case PipeStream:
6192 {
6193 int
6194 c;
6195
6196 c=putc((int) value,blob_info->file_info.file);
6197 if (c == EOF)
6198 {
6199 if (ferror(blob_info->file_info.file) != 0)
6200 ThrowBlobException(blob_info);
6201 break;
6202 }
6203 count++;
6204 break;
6205 }
6206 default:
6207 {
6208 count=WriteBlobStream(image,1,&value);
6209 break;
6210 }
6211 }
6212 return(count);
6213}
6214␌
6215/*
6216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6217% %
6218% %
6219% %
6220+ W r i t e B l o b F l o a t %
6221% %
6222% %
6223% %
6224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6225%
6226% WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
6227% specified by the endian member of the image structure.
6228%
6229% The format of the WriteBlobFloat method is:
6230%
6231% ssize_t WriteBlobFloat(Image *image,const float value)
6232%
6233% A description of each parameter follows.
6234%
6235% o image: the image.
6236%
6237% o value: Specifies the value to write.
6238%
6239*/
6240MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
6241{
6242 union
6243 {
6244 unsigned int
6245 unsigned_value;
6246
6247 float
6248 float_value;
6249 } quantum;
6250
6251 quantum.unsigned_value=0U;
6252 quantum.float_value=value;
6253 return(WriteBlobLong(image,quantum.unsigned_value));
6254}
6255␌
6256/*
6257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6258% %
6259% %
6260% %
6261+ W r i t e B l o b L o n g %
6262% %
6263% %
6264% %
6265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6266%
6267% WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
6268% byte-order specified by the endian member of the image structure.
6269%
6270% The format of the WriteBlobLong method is:
6271%
6272% ssize_t WriteBlobLong(Image *image,const unsigned int value)
6273%
6274% A description of each parameter follows.
6275%
6276% o image: the image.
6277%
6278% o value: Specifies the value to write.
6279%
6280*/
6281MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
6282{
6283 unsigned char
6284 buffer[4];
6285
6286 assert(image != (Image *) NULL);
6287 assert(image->signature == MagickCoreSignature);
6288 if (image->endian == LSBEndian)
6289 {
6290 buffer[0]=(unsigned char) value;
6291 buffer[1]=(unsigned char) (value >> 8);
6292 buffer[2]=(unsigned char) (value >> 16);
6293 buffer[3]=(unsigned char) (value >> 24);
6294 return(WriteBlobStream(image,4,buffer));
6295 }
6296 buffer[0]=(unsigned char) (value >> 24);
6297 buffer[1]=(unsigned char) (value >> 16);
6298 buffer[2]=(unsigned char) (value >> 8);
6299 buffer[3]=(unsigned char) value;
6300 return(WriteBlobStream(image,4,buffer));
6301}
6302␌
6303/*
6304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6305% %
6306% %
6307% %
6308+ W r i t e B l o b L o n g L o n g %
6309% %
6310% %
6311% %
6312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6313%
6314% WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
6315% byte-order specified by the endian member of the image structure.
6316%
6317% The format of the WriteBlobLongLong method is:
6318%
6319% ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
6320%
6321% A description of each parameter follows.
6322%
6323% o value: Specifies the value to write.
6324%
6325% o image: the image.
6326%
6327*/
6328MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
6329{
6330 unsigned char
6331 buffer[8];
6332
6333 assert(image != (Image *) NULL);
6334 assert(image->signature == MagickCoreSignature);
6335 if (image->endian == LSBEndian)
6336 {
6337 buffer[0]=(unsigned char) value;
6338 buffer[1]=(unsigned char) (value >> 8);
6339 buffer[2]=(unsigned char) (value >> 16);
6340 buffer[3]=(unsigned char) (value >> 24);
6341 buffer[4]=(unsigned char) (value >> 32);
6342 buffer[5]=(unsigned char) (value >> 40);
6343 buffer[6]=(unsigned char) (value >> 48);
6344 buffer[7]=(unsigned char) (value >> 56);
6345 return(WriteBlobStream(image,8,buffer));
6346 }
6347 buffer[0]=(unsigned char) (value >> 56);
6348 buffer[1]=(unsigned char) (value >> 48);
6349 buffer[2]=(unsigned char) (value >> 40);
6350 buffer[3]=(unsigned char) (value >> 32);
6351 buffer[4]=(unsigned char) (value >> 24);
6352 buffer[5]=(unsigned char) (value >> 16);
6353 buffer[6]=(unsigned char) (value >> 8);
6354 buffer[7]=(unsigned char) value;
6355 return(WriteBlobStream(image,8,buffer));
6356}
6357␌
6358/*
6359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6360% %
6361% %
6362% %
6363+ W r i t e B l o b S h o r t %
6364% %
6365% %
6366% %
6367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6368%
6369% WriteBlobShort() writes a short value as a 16-bit quantity in the
6370% byte-order specified by the endian member of the image structure.
6371%
6372% The format of the WriteBlobShort method is:
6373%
6374% ssize_t WriteBlobShort(Image *image,const unsigned short value)
6375%
6376% A description of each parameter follows.
6377%
6378% o image: the image.
6379%
6380% o value: Specifies the value to write.
6381%
6382*/
6383MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
6384{
6385 unsigned char
6386 buffer[2];
6387
6388 assert(image != (Image *) NULL);
6389 assert(image->signature == MagickCoreSignature);
6390 if (image->endian == LSBEndian)
6391 {
6392 buffer[0]=(unsigned char) value;
6393 buffer[1]=(unsigned char) (value >> 8);
6394 return(WriteBlobStream(image,2,buffer));
6395 }
6396 buffer[0]=(unsigned char) (value >> 8);
6397 buffer[1]=(unsigned char) value;
6398 return(WriteBlobStream(image,2,buffer));
6399}
6400␌
6401/*
6402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6403% %
6404% %
6405% %
6406+ W r i t e B l o b S i g n e d L o n g %
6407% %
6408% %
6409% %
6410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6411%
6412% WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
6413% byte-order specified by the endian member of the image structure.
6414%
6415% The format of the WriteBlobSignedLong method is:
6416%
6417% ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6418%
6419% A description of each parameter follows.
6420%
6421% o image: the image.
6422%
6423% o value: Specifies the value to write.
6424%
6425*/
6426MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6427{
6428 union
6429 {
6430 unsigned int
6431 unsigned_value;
6432
6433 signed int
6434 signed_value;
6435 } quantum;
6436
6437 unsigned char
6438 buffer[4];
6439
6440 assert(image != (Image *) NULL);
6441 assert(image->signature == MagickCoreSignature);
6442 quantum.signed_value=value;
6443 if (image->endian == LSBEndian)
6444 {
6445 buffer[0]=(unsigned char) quantum.unsigned_value;
6446 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6447 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6448 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6449 return(WriteBlobStream(image,4,buffer));
6450 }
6451 buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
6452 buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
6453 buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
6454 buffer[3]=(unsigned char) quantum.unsigned_value;
6455 return(WriteBlobStream(image,4,buffer));
6456}
6457␌
6458/*
6459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6460% %
6461% %
6462% %
6463+ W r i t e B l o b L S B L o n g %
6464% %
6465% %
6466% %
6467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6468%
6469% WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
6470% least-significant byte first order.
6471%
6472% The format of the WriteBlobLSBLong method is:
6473%
6474% ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6475%
6476% A description of each parameter follows.
6477%
6478% o image: the image.
6479%
6480% o value: Specifies the value to write.
6481%
6482*/
6483MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6484{
6485 unsigned char
6486 buffer[4];
6487
6488 assert(image != (Image *) NULL);
6489 assert(image->signature == MagickCoreSignature);
6490 buffer[0]=(unsigned char) value;
6491 buffer[1]=(unsigned char) (value >> 8);
6492 buffer[2]=(unsigned char) (value >> 16);
6493 buffer[3]=(unsigned char) (value >> 24);
6494 return(WriteBlobStream(image,4,buffer));
6495}
6496␌
6497/*
6498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6499% %
6500% %
6501% %
6502+ W r i t e B l o b L S B S h o r t %
6503% %
6504% %
6505% %
6506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6507%
6508% WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
6509% least-significant byte first order.
6510%
6511% The format of the WriteBlobLSBShort method is:
6512%
6513% ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6514%
6515% A description of each parameter follows.
6516%
6517% o image: the image.
6518%
6519% o value: Specifies the value to write.
6520%
6521*/
6522MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6523{
6524 unsigned char
6525 buffer[2];
6526
6527 assert(image != (Image *) NULL);
6528 assert(image->signature == MagickCoreSignature);
6529 buffer[0]=(unsigned char) value;
6530 buffer[1]=(unsigned char) (value >> 8);
6531 return(WriteBlobStream(image,2,buffer));
6532}
6533␌
6534/*
6535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6536% %
6537% %
6538% %
6539+ W r i t e B l o b L S B S i g n e d L o n g %
6540% %
6541% %
6542% %
6543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6544%
6545% WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
6546% least-significant byte first order.
6547%
6548% The format of the WriteBlobLSBSignedLong method is:
6549%
6550% ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6551%
6552% A description of each parameter follows.
6553%
6554% o image: the image.
6555%
6556% o value: Specifies the value to write.
6557%
6558*/
6559MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6560{
6561 union
6562 {
6563 unsigned int
6564 unsigned_value;
6565
6566 signed int
6567 signed_value;
6568 } quantum;
6569
6570 unsigned char
6571 buffer[4];
6572
6573 assert(image != (Image *) NULL);
6574 assert(image->signature == MagickCoreSignature);
6575 quantum.signed_value=value;
6576 buffer[0]=(unsigned char) quantum.unsigned_value;
6577 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6578 buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6579 buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6580 return(WriteBlobStream(image,4,buffer));
6581}
6582␌
6583/*
6584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6585% %
6586% %
6587% %
6588+ W r i t e B l o b L S B S i g n e d S h o r t %
6589% %
6590% %
6591% %
6592%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6593%
6594% WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
6595% in least-significant byte first order.
6596%
6597% The format of the WriteBlobLSBSignedShort method is:
6598%
6599% ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
6600%
6601% A description of each parameter follows.
6602%
6603% o image: the image.
6604%
6605% o value: Specifies the value to write.
6606%
6607*/
6608MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
6609 const signed short value)
6610{
6611 union
6612 {
6613 unsigned short
6614 unsigned_value;
6615
6616 signed short
6617 signed_value;
6618 } quantum;
6619
6620 unsigned char
6621 buffer[2];
6622
6623 assert(image != (Image *) NULL);
6624 assert(image->signature == MagickCoreSignature);
6625 quantum.signed_value=value;
6626 buffer[0]=(unsigned char) quantum.unsigned_value;
6627 buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6628 return(WriteBlobStream(image,2,buffer));
6629}
6630␌
6631/*
6632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6633% %
6634% %
6635% %
6636+ W r i t e B l o b M S B L o n g %
6637% %
6638% %
6639% %
6640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6641%
6642% WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
6643% most-significant byte first order.
6644%
6645% The format of the WriteBlobMSBLong method is:
6646%
6647% ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6648%
6649% A description of each parameter follows.
6650%
6651% o value: Specifies the value to write.
6652%
6653% o image: the image.
6654%
6655*/
6656MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6657{
6658 unsigned char
6659 buffer[4];
6660
6661 assert(image != (Image *) NULL);
6662 assert(image->signature == MagickCoreSignature);
6663 buffer[0]=(unsigned char) (value >> 24);
6664 buffer[1]=(unsigned char) (value >> 16);
6665 buffer[2]=(unsigned char) (value >> 8);
6666 buffer[3]=(unsigned char) value;
6667 return(WriteBlobStream(image,4,buffer));
6668}
6669␌
6670/*
6671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6672% %
6673% %
6674% %
6675+ W r i t e B l o b M S B S i g n e d S h o r t %
6676% %
6677% %
6678% %
6679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6680%
6681% WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
6682% in most-significant byte first order.
6683%
6684% The format of the WriteBlobMSBSignedShort method is:
6685%
6686% ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
6687%
6688% A description of each parameter follows.
6689%
6690% o image: the image.
6691%
6692% o value: Specifies the value to write.
6693%
6694*/
6695MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
6696 const signed short value)
6697{
6698 union
6699 {
6700 unsigned short
6701 unsigned_value;
6702
6703 signed short
6704 signed_value;
6705 } quantum;
6706
6707 unsigned char
6708 buffer[2];
6709
6710 assert(image != (Image *) NULL);
6711 assert(image->signature == MagickCoreSignature);
6712 quantum.signed_value=value;
6713 buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
6714 buffer[1]=(unsigned char) quantum.unsigned_value;
6715 return(WriteBlobStream(image,2,buffer));
6716}
6717␌
6718/*
6719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6720% %
6721% %
6722% %
6723+ W r i t e B l o b M S B S h o r t %
6724% %
6725% %
6726% %
6727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6728%
6729% WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6730% most-significant byte first order.
6731%
6732% The format of the WriteBlobMSBShort method is:
6733%
6734% ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6735%
6736% A description of each parameter follows.
6737%
6738% o value: Specifies the value to write.
6739%
6740% o file: Specifies the file to write the data to.
6741%
6742*/
6743MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6744{
6745 unsigned char
6746 buffer[2];
6747
6748 assert(image != (Image *) NULL);
6749 assert(image->signature == MagickCoreSignature);
6750 buffer[0]=(unsigned char) (value >> 8);
6751 buffer[1]=(unsigned char) value;
6752 return(WriteBlobStream(image,2,buffer));
6753}
6754␌
6755/*
6756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6757% %
6758% %
6759% %
6760+ W r i t e B l o b S t r i n g %
6761% %
6762% %
6763% %
6764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6765%
6766% WriteBlobString() write a string to a blob. It returns the number of
6767% characters written.
6768%
6769% The format of the WriteBlobString method is:
6770%
6771% ssize_t WriteBlobString(Image *image,const char *string)
6772%
6773% A description of each parameter follows.
6774%
6775% o image: the image.
6776%
6777% o string: Specifies the string to write.
6778%
6779*/
6780MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6781{
6782 assert(image != (Image *) NULL);
6783 assert(image->signature == MagickCoreSignature);
6784 assert(string != (const char *) NULL);
6785 return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
6786}