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