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