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