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