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