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