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