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