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