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