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