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