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