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