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