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