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