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