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