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