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