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