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