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