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