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