]> granicus.if.org Git - imagemagick/blob - MagickCore/blob.c
M MagickCore/blob.c
[imagemagick] / MagickCore / 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 %                                John Cristy                                  %
17 %                                 July 1999                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2012 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 %    http://www.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 \f
40 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/nt-base-private.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/blob-private.h"
47 #include "MagickCore/cache.h"
48 #include "MagickCore/client.h"
49 #include "MagickCore/constitute.h"
50 #include "MagickCore/delegate.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/image-private.h"
54 #include "MagickCore/list.h"
55 #include "MagickCore/locale_.h"
56 #include "MagickCore/log.h"
57 #include "MagickCore/magick.h"
58 #include "MagickCore/memory_.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/resource_.h"
61 #include "MagickCore/semaphore.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/string-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
67 #if defined(MAGICKCORE_ZLIB_DELEGATE)
68 #include "zlib.h"
69 #endif
70 #if defined(MAGICKCORE_BZLIB_DELEGATE)
71 #include "bzlib.h"
72 #endif
73 \f
74 /*
75   Define declarations.
76 */
77 #define MagickMaxBlobExtent  65541
78 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
79 # define MAP_ANONYMOUS  MAP_ANON
80 #endif
81 #if !defined(MAP_FAILED)
82 #define MAP_FAILED  ((void *) -1)
83 #endif
84 #if !defined(MS_SYNC)
85 #define MS_SYNC  0x04
86 #endif
87 #if defined(__OS2__)
88 #include <io.h>
89 #define _O_BINARY O_BINARY
90 #endif
91 \f
92 /*
93   Typedef declarations.
94 */
95 typedef union FileInfo
96 {
97   FILE
98     *file;
99
100 #if defined(MAGICKCORE_ZLIB_DELEGATE)
101   gzFile
102     gzfile;
103 #endif
104
105 #if defined(MAGICKCORE_BZLIB_DELEGATE)
106   BZFILE
107     *bzfile;
108 #endif
109 } FileInfo;
110
111 struct _BlobInfo
112 {
113   size_t
114     length,
115     extent,
116     quantum;
117
118   MagickBooleanType
119     mapped,
120     eof;
121
122   MagickOffsetType
123     offset;
124
125   MagickSizeType
126     size;
127
128   MagickBooleanType
129     exempt,
130     synchronize,
131     status,
132     temporary;
133
134   StreamType
135     type;
136
137   FileInfo
138     file_info;
139
140   struct stat
141     properties;
142
143   StreamHandler
144     stream;
145
146   unsigned char
147     *data;
148
149   MagickBooleanType
150     debug;
151
152   SemaphoreInfo
153     *semaphore;
154
155   ssize_t
156     reference_count;
157
158   size_t
159     signature;
160 };
161 \f
162 /*
163   Forward declarations.
164 */
165 static int
166   SyncBlob(Image *);
167 \f
168 /*
169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 %                                                                             %
171 %                                                                             %
172 %                                                                             %
173 +   A t t a c h B l o b                                                       %
174 %                                                                             %
175 %                                                                             %
176 %                                                                             %
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 %
179 %  AttachBlob() attaches a blob to the BlobInfo structure.
180 %
181 %  The format of the AttachBlob method is:
182 %
183 %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
184 %
185 %  A description of each parameter follows:
186 %
187 %    o blob_info: Specifies a pointer to a BlobInfo structure.
188 %
189 %    o blob: the address of a character stream in one of the image formats
190 %      understood by ImageMagick.
191 %
192 %    o length: This size_t integer reflects the length in bytes of the blob.
193 %
194 */
195 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
196   const size_t length)
197 {
198   assert(blob_info != (BlobInfo *) NULL);
199   if (blob_info->debug != MagickFalse)
200     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
201   blob_info->length=length;
202   blob_info->extent=length;
203   blob_info->quantum=(size_t) MagickMaxBlobExtent;
204   blob_info->offset=0;
205   blob_info->type=BlobStream;
206   blob_info->file_info.file=(FILE *) NULL;
207   blob_info->data=(unsigned char *) blob;
208   blob_info->mapped=MagickFalse;
209 }
210 \f
211 /*
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213 %                                                                             %
214 %                                                                             %
215 %                                                                             %
216 +   B l o b T o F i l e                                                       %
217 %                                                                             %
218 %                                                                             %
219 %                                                                             %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 %
222 %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
223 %  occurs otherwise MagickTrue.
224 %
225 %  The format of the BlobToFile method is:
226 %
227 %       MagickBooleanType BlobToFile(char *filename,const void *blob,
228 %         const size_t length,ExceptionInfo *exception)
229 %
230 %  A description of each parameter follows:
231 %
232 %    o filename: Write the blob to this file.
233 %
234 %    o blob: the address of a blob.
235 %
236 %    o length: This length in bytes of the blob.
237 %
238 %    o exception: return any errors or warnings in this structure.
239 %
240 */
241
242 static inline MagickSizeType MagickMin(const MagickSizeType x,
243   const MagickSizeType y)
244 {
245   if (x < y)
246     return(x);
247   return(y);
248 }
249
250 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
251   const size_t length,ExceptionInfo *exception)
252 {
253   int
254     file;
255
256   register size_t
257     i;
258
259   ssize_t
260     count;
261
262   assert(filename != (const char *) NULL);
263   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
264   assert(blob != (const void *) NULL);
265   if (*filename == '\0')
266     file=AcquireUniqueFileResource(filename);
267   else
268     file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
269   if (file == -1)
270     {
271       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
272       return(MagickFalse);
273     }
274   for (i=0; i < length; i+=count)
275   {
276     count=(ssize_t) write(file,(const char *) blob+i,(size_t) MagickMin(length-
277       i,(MagickSizeType) SSIZE_MAX));
278     if (count <= 0)
279       {
280         count=0;
281         if (errno != EINTR)
282           break;
283       }
284   }
285   file=close(file);
286   if ((file == -1) || (i < length))
287     {
288       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
289       return(MagickFalse);
290     }
291   return(MagickTrue);
292 }
293 \f
294 /*
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 %                                                                             %
297 %                                                                             %
298 %                                                                             %
299 %   B l o b T o I m a g e                                                     %
300 %                                                                             %
301 %                                                                             %
302 %                                                                             %
303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304 %
305 %  BlobToImage() implements direct to memory image formats.  It returns the
306 %  blob as an image.
307 %
308 %  The format of the BlobToImage method is:
309 %
310 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
311 %        const size_t length,ExceptionInfo *exception)
312 %
313 %  A description of each parameter follows:
314 %
315 %    o image_info: the image info.
316 %
317 %    o blob: the address of a character stream in one of the image formats
318 %      understood by ImageMagick.
319 %
320 %    o length: This size_t integer reflects the length in bytes of the blob.
321 %
322 %    o exception: return any errors or warnings in this structure.
323 %
324 */
325 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
326   const size_t length,ExceptionInfo *exception)
327 {
328   const MagickInfo
329     *magick_info;
330
331   Image
332     *image;
333
334   ImageInfo
335     *blob_info,
336     *clone_info;
337
338   MagickBooleanType
339     status;
340
341   assert(image_info != (ImageInfo *) NULL);
342   assert(image_info->signature == MagickSignature);
343   if (image_info->debug != MagickFalse)
344     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
345       image_info->filename);
346   assert(exception != (ExceptionInfo *) NULL);
347   if ((blob == (const void *) NULL) || (length == 0))
348     {
349       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
350         "ZeroLengthBlobNotPermitted","'%s'",image_info->filename);
351       return((Image *) NULL);
352     }
353   blob_info=CloneImageInfo(image_info);
354   blob_info->blob=(void *) blob;
355   blob_info->length=length;
356   if (*blob_info->magick == '\0')
357     (void) SetImageInfo(blob_info,0,exception);
358   magick_info=GetMagickInfo(blob_info->magick,exception);
359   if (magick_info == (const MagickInfo *) NULL)
360     {
361       blob_info=DestroyImageInfo(blob_info);
362       (void) ThrowMagickException(exception,GetMagickModule(),
363         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
364         image_info->filename);
365       return((Image *) NULL);
366     }
367   if (GetMagickBlobSupport(magick_info) != MagickFalse)
368     {
369       /*
370         Native blob support for this image format.
371       */
372       (void) CopyMagickString(blob_info->filename,image_info->filename,
373         MaxTextExtent);
374       (void) CopyMagickString(blob_info->magick,image_info->magick,
375         MaxTextExtent);
376       image=ReadImage(blob_info,exception);
377       if (image != (Image *) NULL)
378         (void) DetachBlob(image->blob);
379       blob_info=DestroyImageInfo(blob_info);
380       return(image);
381     }
382   /*
383     Write blob to a temporary file on disk.
384   */
385   blob_info->blob=(void *) NULL;
386   blob_info->length=0;
387   *blob_info->filename='\0';
388   status=BlobToFile(blob_info->filename,blob,length,exception);
389   if (status == MagickFalse)
390     {
391       (void) RelinquishUniqueFileResource(blob_info->filename);
392       blob_info=DestroyImageInfo(blob_info);
393       return((Image *) NULL);
394     }
395   clone_info=CloneImageInfo(blob_info);
396   (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:%s",
397     blob_info->magick,blob_info->filename);
398   image=ReadImage(clone_info,exception);
399   if (image != (Image *) NULL)
400     {
401       Image
402         *images;
403
404       /*
405         Restore original filenames.
406       */
407       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
408       {
409         (void) CopyMagickMemory(images->filename,image_info->filename,
410           sizeof(images->filename));
411         (void) CopyMagickMemory(images->magick_filename,image_info->filename,
412           sizeof(images->magick_filename));
413         images=GetNextImageInList(images);
414       }
415     }
416   clone_info=DestroyImageInfo(clone_info);
417   (void) RelinquishUniqueFileResource(blob_info->filename);
418   blob_info=DestroyImageInfo(blob_info);
419   return(image);
420 }
421 \f
422 /*
423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424 %                                                                             %
425 %                                                                             %
426 %                                                                             %
427 +   C l o n e B l o b I n f o                                                 %
428 %                                                                             %
429 %                                                                             %
430 %                                                                             %
431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 %
433 %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
434 %  blob info is NULL, a new one.
435 %
436 %  The format of the CloneBlobInfo method is:
437 %
438 %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
439 %
440 %  A description of each parameter follows:
441 %
442 %    o blob_info: the blob info.
443 %
444 */
445 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
446 {
447   BlobInfo
448     *clone_info;
449
450   clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
451   if (clone_info == (BlobInfo *) NULL)
452     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
453   GetBlobInfo(clone_info);
454   if (blob_info == (BlobInfo *) NULL)
455     return(clone_info);
456   clone_info->length=blob_info->length;
457   clone_info->extent=blob_info->extent;
458   clone_info->synchronize=blob_info->synchronize;
459   clone_info->quantum=blob_info->quantum;
460   clone_info->mapped=blob_info->mapped;
461   clone_info->eof=blob_info->eof;
462   clone_info->offset=blob_info->offset;
463   clone_info->size=blob_info->size;
464   clone_info->exempt=blob_info->exempt;
465   clone_info->status=blob_info->status;
466   clone_info->temporary=blob_info->temporary;
467   clone_info->type=blob_info->type;
468   clone_info->file_info.file=blob_info->file_info.file;
469   clone_info->properties=blob_info->properties;
470   clone_info->stream=blob_info->stream;
471   clone_info->data=blob_info->data;
472   clone_info->debug=IsEventLogging();
473   clone_info->reference_count=1;
474   return(clone_info);
475 }
476 \f
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 MagickExport MagickBooleanType CloseBlob(Image *image)
500 {
501   int
502     status;
503
504   /*
505     Close image file.
506   */
507   assert(image != (Image *) NULL);
508   assert(image->signature == MagickSignature);
509   if (image->debug != MagickFalse)
510     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
511   assert(image->blob != (BlobInfo *) NULL);
512   if (image->blob->type == UndefinedStream)
513     return(MagickTrue);
514   if (image->blob->synchronize != MagickFalse)
515     SyncBlob(image);
516   image->blob->size=GetBlobSize(image);
517   image->extent=image->blob->size;
518   image->blob->eof=MagickFalse;
519   if (image->blob->exempt != MagickFalse)
520     {
521       image->blob->type=UndefinedStream;
522       return(MagickTrue);
523     }
524   status=0;
525   switch (image->blob->type)
526   {
527     case UndefinedStream:
528     case StandardStream:
529       break;
530     case FileStream:
531     case PipeStream:
532     {
533       status=ferror(image->blob->file_info.file);
534       break;
535     }
536     case ZipStream:
537     {
538 #if defined(MAGICKCORE_ZLIB_DELEGATE)
539       (void) gzerror(image->blob->file_info.gzfile,&status);
540 #endif
541       break;
542     }
543     case BZipStream:
544     {
545 #if defined(MAGICKCORE_BZLIB_DELEGATE)
546       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
547 #endif
548       break;
549     }
550     case FifoStream:
551     case BlobStream:
552       break;
553   }
554   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
555   switch (image->blob->type)
556   {
557     case UndefinedStream:
558     case StandardStream:
559       break;
560     case FileStream:
561     {
562       if (image->blob->synchronize != MagickFalse)
563         {
564           status=fflush(image->blob->file_info.file);
565           status=fsync(fileno(image->blob->file_info.file));
566         }
567       status=fclose(image->blob->file_info.file);
568       break;
569     }
570     case PipeStream:
571     {
572 #if defined(MAGICKCORE_HAVE_PCLOSE)
573       status=pclose(image->blob->file_info.file);
574 #endif
575       break;
576     }
577     case ZipStream:
578     {
579 #if defined(MAGICKCORE_ZLIB_DELEGATE)
580       status=gzclose(image->blob->file_info.gzfile);
581 #endif
582       break;
583     }
584     case BZipStream:
585     {
586 #if defined(MAGICKCORE_BZLIB_DELEGATE)
587       BZ2_bzclose(image->blob->file_info.bzfile);
588 #endif
589       break;
590     }
591     case FifoStream:
592       break;
593     case BlobStream:
594     {
595       if (image->blob->file_info.file != (FILE *) NULL)
596         {
597           if (image->blob->synchronize != MagickFalse)
598             (void) fsync(fileno(image->blob->file_info.file));
599           status=fclose(image->blob->file_info.file);
600         }
601       break;
602     }
603   }
604   (void) DetachBlob(image->blob);
605   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
606   return(image->blob->status);
607 }
608 \f
609 /*
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 %                                                                             %
612 %                                                                             %
613 %                                                                             %
614 +   D e s t r o y B l o b                                                     %
615 %                                                                             %
616 %                                                                             %
617 %                                                                             %
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %
620 %  DestroyBlob() deallocates memory associated with a blob.
621 %
622 %  The format of the DestroyBlob method is:
623 %
624 %      void DestroyBlob(Image *image)
625 %
626 %  A description of each parameter follows:
627 %
628 %    o image: the image.
629 %
630 */
631 MagickExport void DestroyBlob(Image *image)
632 {
633   MagickBooleanType
634     destroy;
635
636   assert(image != (Image *) NULL);
637   assert(image->signature == MagickSignature);
638   if (image->debug != MagickFalse)
639     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
640   assert(image->blob != (BlobInfo *) NULL);
641   assert(image->blob->signature == MagickSignature);
642   destroy=MagickFalse;
643   LockSemaphoreInfo(image->blob->semaphore);
644   image->blob->reference_count--;
645   assert(image->blob->reference_count >= 0);
646   if (image->blob->reference_count == 0)
647     destroy=MagickTrue;
648   UnlockSemaphoreInfo(image->blob->semaphore);
649   if (destroy == MagickFalse)
650     return;
651   (void) CloseBlob(image);
652   if (image->blob->mapped != MagickFalse)
653     (void) UnmapBlob(image->blob->data,image->blob->length);
654   if (image->blob->semaphore != (SemaphoreInfo *) NULL)
655     DestroySemaphoreInfo(&image->blob->semaphore);
656   image->blob->signature=(~MagickSignature);
657   image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
658 }
659 \f
660 /*
661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662 %                                                                             %
663 %                                                                             %
664 %                                                                             %
665 +   D e t a c h B l o b                                                       %
666 %                                                                             %
667 %                                                                             %
668 %                                                                             %
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 %
671 %  DetachBlob() detaches a blob from the BlobInfo structure.
672 %
673 %  The format of the DetachBlob method is:
674 %
675 %      unsigned char *DetachBlob(BlobInfo *blob_info)
676 %
677 %  A description of each parameter follows:
678 %
679 %    o blob_info: Specifies a pointer to a BlobInfo structure.
680 %
681 */
682 MagickExport unsigned char *DetachBlob(BlobInfo *blob_info)
683 {
684   unsigned char
685     *data;
686
687   assert(blob_info != (BlobInfo *) NULL);
688   if (blob_info->debug != MagickFalse)
689     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
690   if (blob_info->mapped != MagickFalse)
691     (void) UnmapBlob(blob_info->data,blob_info->length);
692   blob_info->mapped=MagickFalse;
693   blob_info->length=0;
694   blob_info->offset=0;
695   blob_info->eof=MagickFalse;
696   blob_info->exempt=MagickFalse;
697   blob_info->type=UndefinedStream;
698   blob_info->file_info.file=(FILE *) NULL;
699   data=blob_info->data;
700   blob_info->data=(unsigned char *) NULL;
701   blob_info->stream=(StreamHandler) NULL;
702   return(data);
703 }
704 \f
705 /*
706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 %                                                                             %
708 %                                                                             %
709 %                                                                             %
710 +  D i s c a r d B l o b B y t e s                                            %
711 %                                                                             %
712 %                                                                             %
713 %                                                                             %
714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715 %
716 %  DiscardBlobBytes() discards bytes in a blob.
717 %
718 %  The format of the DiscardBlobBytes method is:
719 %
720 %      MagickBooleanType DiscardBlobBytes(Image *image,const size_t length)
721 %
722 %  A description of each parameter follows.
723 %
724 %    o image: the image.
725 %
726 %    o length:  the number of bytes to skip.
727 %
728 */
729
730 static inline const unsigned char *ReadBlobStream(Image *image,
731   const size_t length,unsigned char *data,ssize_t *count)
732 {
733   assert(count != (ssize_t *) NULL);
734   assert(image->blob != (BlobInfo *) NULL);
735   if (image->blob->type != BlobStream)
736     {
737       *count=ReadBlob(image,length,data);
738       return(data);
739     }
740   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
741     {
742       *count=0;
743       image->blob->eof=MagickTrue;
744       return(data);
745     }
746   data=image->blob->data+image->blob->offset;
747   *count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
748     image->blob->offset));
749   image->blob->offset+=(*count);
750   if (*count != (ssize_t) length)
751     image->blob->eof=MagickTrue;
752   return(data);
753 }
754
755 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
756   const MagickSizeType length)
757 {
758   register MagickOffsetType
759     i;
760
761   size_t
762     quantum;
763
764   ssize_t
765     count;
766
767   unsigned char
768     buffer[16384];
769
770   assert(image != (Image *) NULL);
771   assert(image->signature == MagickSignature);
772   count=0;
773   for (i=0; i < (MagickOffsetType) length; i+=count)
774   {
775     quantum=(size_t) MagickMin(length-i,sizeof(buffer));
776     (void) ReadBlobStream(image,quantum,buffer,&count);
777     if (count <= 0)
778       {
779         count=0;
780         if (errno != EINTR)
781           break;
782       }
783   }
784   return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
785 }
786 \f
787 /*
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789 %                                                                             %
790 %                                                                             %
791 %                                                                             %
792 +   D u p l i c a t e s B l o b                                               %
793 %                                                                             %
794 %                                                                             %
795 %                                                                             %
796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797 %
798 %  DuplicateBlob() duplicates a blob descriptor.
799 %
800 %  The format of the DuplicateBlob method is:
801 %
802 %      void DuplicateBlob(Image *image,const Image *duplicate)
803 %
804 %  A description of each parameter follows:
805 %
806 %    o image: the image.
807 %
808 %    o duplicate: the duplicate image.
809 %
810 */
811 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
812 {
813   assert(image != (Image *) NULL);
814   assert(image->signature == MagickSignature);
815   if (image->debug != MagickFalse)
816     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
817   assert(duplicate != (Image *) NULL);
818   assert(duplicate->signature == MagickSignature);
819   DestroyBlob(image);
820   image->blob=ReferenceBlob(duplicate->blob);
821 }
822 \f
823 /*
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 +  E O F B l o b                                                              %
829 %                                                                             %
830 %                                                                             %
831 %                                                                             %
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 %
834 %  EOFBlob() returns a non-zero value when EOF has been detected reading from
835 %  a blob or file.
836 %
837 %  The format of the EOFBlob method is:
838 %
839 %      int EOFBlob(const Image *image)
840 %
841 %  A description of each parameter follows:
842 %
843 %    o image: the image.
844 %
845 */
846 MagickExport int EOFBlob(const Image *image)
847 {
848   assert(image != (Image *) NULL);
849   assert(image->signature == MagickSignature);
850   if (image->debug != MagickFalse)
851     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
852   assert(image->blob != (BlobInfo *) NULL);
853   assert(image->blob->type != UndefinedStream);
854   switch (image->blob->type)
855   {
856     case UndefinedStream:
857     case StandardStream:
858       break;
859     case FileStream:
860     case PipeStream:
861     {
862       image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
863         MagickFalse;
864       break;
865     }
866     case ZipStream:
867     {
868       image->blob->eof=MagickFalse;
869       break;
870     }
871     case BZipStream:
872     {
873 #if defined(MAGICKCORE_BZLIB_DELEGATE)
874       int
875         status;
876
877       status=0;
878       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
879       image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
880 #endif
881       break;
882     }
883     case FifoStream:
884     {
885       image->blob->eof=MagickFalse;
886       break;
887     }
888     case BlobStream:
889       break;
890   }
891   return((int) image->blob->eof);
892 }
893 \f
894 /*
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896 %                                                                             %
897 %                                                                             %
898 %                                                                             %
899 +   F i l e T o B l o b                                                       %
900 %                                                                             %
901 %                                                                             %
902 %                                                                             %
903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904 %
905 %  FileToBlob() returns the contents of a file as a buffer terminated with
906 %  the '\0' character.  The length of the buffer (not including the extra
907 %  terminating '\0' character) is returned via the 'length' parameter.  Free
908 %  the buffer with RelinquishMagickMemory().
909 %
910 %  The format of the FileToBlob method is:
911 %
912 %      unsigned char *FileToBlob(const char *filename,const size_t extent,
913 %        size_t *length,ExceptionInfo *exception)
914 %
915 %  A description of each parameter follows:
916 %
917 %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
918 %      an error occurs NULL is returned.
919 %
920 %    o filename: the filename.
921 %
922 %    o extent:  The maximum length of the blob.
923 %
924 %    o length: On return, this reflects the actual length of the blob.
925 %
926 %    o exception: return any errors or warnings in this structure.
927 %
928 */
929 MagickExport unsigned char *FileToBlob(const char *filename,const size_t extent,
930   size_t *length,ExceptionInfo *exception)
931 {
932   int
933     file;
934
935   MagickOffsetType
936     offset;
937
938   register size_t
939     i;
940
941   ssize_t
942     count;
943
944   unsigned char
945     *blob;
946
947   void
948     *map;
949
950   assert(filename != (const char *) NULL);
951   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
952   assert(exception != (ExceptionInfo *) NULL);
953   *length=0;
954   file=fileno(stdin);
955   if (LocaleCompare(filename,"-") != 0)
956     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
957   if (file == -1)
958     {
959       ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
960       return((unsigned char *) NULL);
961     }
962   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
963   count=0;
964   if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
965     {
966       size_t
967         quantum;
968
969       struct stat
970         file_stats;
971
972       /*
973         Stream is not seekable.
974       */
975       quantum=(size_t) MagickMaxBufferExtent;
976       if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
977         quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
978           MagickMaxBufferExtent);
979       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
980       for (i=0; blob != (unsigned char *) NULL; i+=count)
981       {
982         count=(ssize_t) read(file,blob+i,quantum);
983         if (count <= 0)
984           {
985             count=0;
986             if (errno != EINTR)
987               break;
988           }
989         if (~((size_t) i) < (quantum+1))
990           {
991             blob=(unsigned char *) RelinquishMagickMemory(blob);
992             break;
993           }
994         blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
995           sizeof(*blob));
996         if ((size_t) (i+count) >= extent)
997           break;
998       }
999       if (LocaleCompare(filename,"-") != 0)
1000         file=close(file);
1001       if (blob == (unsigned char *) NULL)
1002         {
1003           (void) ThrowMagickException(exception,GetMagickModule(),
1004             ResourceLimitError,"MemoryAllocationFailed","'%s'",filename);
1005           return((unsigned char *) NULL);
1006         }
1007       if (file == -1)
1008         {
1009           blob=(unsigned char *) RelinquishMagickMemory(blob);
1010           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1011           return((unsigned char *) NULL);
1012         }
1013       *length=(size_t) MagickMin(i+count,extent);
1014       blob[*length]='\0';
1015       return(blob);
1016     }
1017   *length=(size_t) MagickMin((MagickSizeType) offset,extent);
1018   blob=(unsigned char *) NULL;
1019   if (~(*length) >= (MaxTextExtent-1))
1020     blob=(unsigned char *) AcquireQuantumMemory(*length+MaxTextExtent,
1021       sizeof(*blob));
1022   if (blob == (unsigned char *) NULL)
1023     {
1024       file=close(file);
1025       (void) ThrowMagickException(exception,GetMagickModule(),
1026         ResourceLimitError,"MemoryAllocationFailed","'%s'",filename);
1027       return((unsigned char *) NULL);
1028     }
1029   map=MapBlob(file,ReadMode,0,*length);
1030   if (map != (unsigned char *) NULL)
1031     {
1032       (void) memcpy(blob,map,*length);
1033       (void) UnmapBlob(map,*length);
1034     }
1035   else
1036     {
1037       (void) lseek(file,0,SEEK_SET);
1038       for (i=0; i < *length; i+=count)
1039       {
1040         count=(ssize_t) read(file,blob+i,(size_t) MagickMin(*length-i,
1041           (MagickSizeType) SSIZE_MAX));
1042         if (count <= 0)
1043           {
1044             count=0;
1045             if (errno != EINTR)
1046               break;
1047           }
1048       }
1049       if (i < *length)
1050         {
1051           file=close(file)-1;
1052           blob=(unsigned char *) RelinquishMagickMemory(blob);
1053           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1054           return((unsigned char *) NULL);
1055         }
1056     }
1057   blob[*length]='\0';
1058   if (LocaleCompare(filename,"-") != 0)
1059     file=close(file);
1060   if (file == -1)
1061     {
1062       blob=(unsigned char *) RelinquishMagickMemory(blob);
1063       ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1064     }
1065   return(blob);
1066 }
1067 \f
1068 /*
1069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070 %                                                                             %
1071 %                                                                             %
1072 %                                                                             %
1073 %   F i l e T o I m a g e                                                     %
1074 %                                                                             %
1075 %                                                                             %
1076 %                                                                             %
1077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078 %
1079 %  FileToImage() write the contents of a file to an image.
1080 %
1081 %  The format of the FileToImage method is:
1082 %
1083 %      MagickBooleanType FileToImage(Image *,const char *filename)
1084 %
1085 %  A description of each parameter follows:
1086 %
1087 %    o image: the image.
1088 %
1089 %    o filename: the filename.
1090 %
1091 */
1092
1093 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1094   const unsigned char *data)
1095 {
1096   MagickSizeType
1097     extent;
1098
1099   register unsigned char
1100     *q;
1101
1102   assert(image->blob != (BlobInfo *) NULL);
1103   if (image->blob->type != BlobStream)
1104     return(WriteBlob(image,length,data));
1105   assert(image->blob->type != UndefinedStream);
1106   assert(data != (void *) NULL);
1107   extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1108   if (extent >= image->blob->extent)
1109     {
1110       image->blob->quantum<<=1;
1111       extent=image->blob->extent+image->blob->quantum+length;
1112       if (SetBlobExtent(image,extent) == MagickFalse)
1113         return(0);
1114     }
1115   q=image->blob->data+image->blob->offset;
1116   (void) memcpy(q,data,length);
1117   image->blob->offset+=length;
1118   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1119     image->blob->length=(size_t) image->blob->offset;
1120   return((ssize_t) length);
1121 }
1122
1123 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1124   ExceptionInfo *exception)
1125 {
1126   int
1127     file;
1128
1129   size_t
1130     length,
1131     quantum;
1132
1133   ssize_t
1134     count;
1135
1136   struct stat
1137     file_stats;
1138
1139   unsigned char
1140     *blob;
1141
1142   assert(image != (const Image *) NULL);
1143   assert(image->signature == MagickSignature);
1144   assert(filename != (const char *) NULL);
1145   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1146   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1147   if (file == -1)
1148     {
1149       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1150       return(MagickFalse);
1151     }
1152   quantum=(size_t) MagickMaxBufferExtent;
1153   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1154     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1155   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1156   if (blob == (unsigned char *) NULL)
1157     {
1158       ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1159         filename);
1160       return(MagickFalse);
1161     }
1162   for ( ; ; )
1163   {
1164     count=(ssize_t) read(file,blob,quantum);
1165     if (count <= 0)
1166       {
1167         count=0;
1168         if (errno != EINTR)
1169           break;
1170       }
1171     length=(size_t) count;
1172     count=WriteBlobStream(image,length,blob);
1173     if (count != (ssize_t) length)
1174       {
1175         ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1176         break;
1177       }
1178   }
1179   file=close(file);
1180   if (file == -1)
1181     ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1182   blob=(unsigned char *) RelinquishMagickMemory(blob);
1183   return(MagickTrue);
1184 }
1185 \f
1186 /*
1187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188 %                                                                             %
1189 %                                                                             %
1190 %                                                                             %
1191 +   G e t B l o b E r r o r                                                   %
1192 %                                                                             %
1193 %                                                                             %
1194 %                                                                             %
1195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196 %
1197 %  GetBlobError() returns MagickTrue if the blob associated with the specified
1198 %  image encountered an error.
1199 %
1200 %  The format of the GetBlobError method is:
1201 %
1202 %       MagickBooleanType GetBlobError(const Image *image)
1203 %
1204 %  A description of each parameter follows:
1205 %
1206 %    o image: the image.
1207 %
1208 */
1209 MagickPrivate MagickBooleanType GetBlobError(const Image *image)
1210 {
1211   assert(image != (const Image *) NULL);
1212   assert(image->signature == MagickSignature);
1213   if (image->debug != MagickFalse)
1214     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1215   return(image->blob->status);
1216 }
1217 \f
1218 /*
1219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 %                                                                             %
1221 %                                                                             %
1222 %                                                                             %
1223 +   G e t B l o b F i l e H a n d l e                                         %
1224 %                                                                             %
1225 %                                                                             %
1226 %                                                                             %
1227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1228 %
1229 %  GetBlobFileHandle() returns the file handle associated with the image blob.
1230 %
1231 %  The format of the GetBlobFile method is:
1232 %
1233 %      FILE *GetBlobFileHandle(const Image *image)
1234 %
1235 %  A description of each parameter follows:
1236 %
1237 %    o image: the image.
1238 %
1239 */
1240 MagickExport FILE *GetBlobFileHandle(const Image *image)
1241 {
1242   assert(image != (const Image *) NULL);
1243   assert(image->signature == MagickSignature);
1244   return(image->blob->file_info.file);
1245 }
1246 \f
1247 /*
1248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1249 %                                                                             %
1250 %                                                                             %
1251 %                                                                             %
1252 +   G e t B l o b I n f o                                                     %
1253 %                                                                             %
1254 %                                                                             %
1255 %                                                                             %
1256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1257 %
1258 %  GetBlobInfo() initializes the BlobInfo structure.
1259 %
1260 %  The format of the GetBlobInfo method is:
1261 %
1262 %      void GetBlobInfo(BlobInfo *blob_info)
1263 %
1264 %  A description of each parameter follows:
1265 %
1266 %    o blob_info: Specifies a pointer to a BlobInfo structure.
1267 %
1268 */
1269 MagickPrivate void GetBlobInfo(BlobInfo *blob_info)
1270 {
1271   assert(blob_info != (BlobInfo *) NULL);
1272   (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1273   blob_info->type=UndefinedStream;
1274   blob_info->quantum=(size_t) MagickMaxBlobExtent;
1275   blob_info->properties.st_mtime=time((time_t *) NULL);
1276   blob_info->properties.st_ctime=time((time_t *) NULL);
1277   blob_info->debug=IsEventLogging();
1278   blob_info->reference_count=1;
1279   blob_info->semaphore=AllocateSemaphoreInfo();
1280   blob_info->signature=MagickSignature;
1281 }
1282 \f
1283 /*
1284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1285 %                                                                             %
1286 %                                                                             %
1287 %                                                                             %
1288 %  G e t B l o b P r o p e r t i e s                                          %
1289 %                                                                             %
1290 %                                                                             %
1291 %                                                                             %
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 %
1294 %  GetBlobProperties() returns information about an image blob.
1295 %
1296 %  The format of the GetBlobProperties method is:
1297 %
1298 %      const struct stat *GetBlobProperties(const Image *image)
1299 %
1300 %  A description of each parameter follows:
1301 %
1302 %    o image: the image.
1303 %
1304 */
1305 MagickPrivate const struct stat *GetBlobProperties(const Image *image)
1306 {
1307   assert(image != (Image *) NULL);
1308   assert(image->signature == MagickSignature);
1309   if (image->debug != MagickFalse)
1310     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1311   return(&image->blob->properties);
1312 }
1313 \f
1314 /*
1315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1316 %                                                                             %
1317 %                                                                             %
1318 %                                                                             %
1319 +  G e t B l o b S i z e                                                      %
1320 %                                                                             %
1321 %                                                                             %
1322 %                                                                             %
1323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1324 %
1325 %  GetBlobSize() returns the current length of the image file or blob; zero is
1326 %  returned if the size cannot be determined.
1327 %
1328 %  The format of the GetBlobSize method is:
1329 %
1330 %      MagickSizeType GetBlobSize(const Image *image)
1331 %
1332 %  A description of each parameter follows:
1333 %
1334 %    o image: the image.
1335 %
1336 */
1337 MagickExport MagickSizeType GetBlobSize(const Image *image)
1338 {
1339   MagickSizeType
1340     extent;
1341
1342   assert(image != (Image *) NULL);
1343   assert(image->signature == MagickSignature);
1344   if (image->debug != MagickFalse)
1345     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1346   assert(image->blob != (BlobInfo *) NULL);
1347   extent=0;
1348   switch (image->blob->type)
1349   {
1350     case UndefinedStream:
1351     {
1352       extent=image->blob->size;
1353       break;
1354     }
1355     case StandardStream:
1356     {
1357       extent=image->blob->size;
1358       break;
1359     }
1360     case FileStream:
1361     {
1362       if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
1363         extent=(MagickSizeType) image->blob->properties.st_size;
1364       break;
1365     }
1366     case PipeStream:
1367     {
1368       extent=image->blob->size;
1369       break;
1370     }
1371     case ZipStream:
1372     case BZipStream:
1373     {
1374       MagickBooleanType
1375         status;
1376
1377       status=GetPathAttributes(image->filename,&image->blob->properties);
1378       if (status != MagickFalse)
1379         extent=(MagickSizeType) image->blob->properties.st_size;
1380       break;
1381     }
1382     case FifoStream:
1383       break;
1384     case BlobStream:
1385     {
1386       extent=(MagickSizeType) image->blob->length;
1387       break;
1388     }
1389   }
1390   return(extent);
1391 }
1392 \f
1393 /*
1394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395 %                                                                             %
1396 %                                                                             %
1397 %                                                                             %
1398 +   G e t B l o b S t r e a m D a t a                                         %
1399 %                                                                             %
1400 %                                                                             %
1401 %                                                                             %
1402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403 %
1404 %  GetBlobStreamData() returns the stream data for the image.
1405 %
1406 %  The format of the GetBlobStreamData method is:
1407 %
1408 %      unsigned char *GetBlobStreamData(const Image *image)
1409 %
1410 %  A description of each parameter follows:
1411 %
1412 %    o image: the image.
1413 %
1414 */
1415 MagickExport unsigned char *GetBlobStreamData(const Image *image)
1416 {
1417   assert(image != (const Image *) NULL);
1418   assert(image->signature == MagickSignature);
1419   return(image->blob->data);
1420 }
1421 \f
1422 /*
1423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424 %                                                                             %
1425 %                                                                             %
1426 %                                                                             %
1427 +   G e t B l o b S t r e a m H a n d l e r                                   %
1428 %                                                                             %
1429 %                                                                             %
1430 %                                                                             %
1431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432 %
1433 %  GetBlobStreamHandler() returns the stream handler for the image.
1434 %
1435 %  The format of the GetBlobStreamHandler method is:
1436 %
1437 %      StreamHandler GetBlobStreamHandler(const Image *image)
1438 %
1439 %  A description of each parameter follows:
1440 %
1441 %    o image: the image.
1442 %
1443 */
1444 MagickPrivate StreamHandler GetBlobStreamHandler(const Image *image)
1445 {
1446   assert(image != (const Image *) NULL);
1447   assert(image->signature == MagickSignature);
1448   if (image->debug != MagickFalse)
1449     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1450   return(image->blob->stream);
1451 }
1452 \f
1453 /*
1454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1455 %                                                                             %
1456 %                                                                             %
1457 %                                                                             %
1458 %   I m a g e T o B l o b                                                     %
1459 %                                                                             %
1460 %                                                                             %
1461 %                                                                             %
1462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1463 %
1464 %  ImageToBlob() implements direct to memory image formats.  It returns the
1465 %  image as a formatted blob and its length.  The magick member of the Image
1466 %  structure determines the format of the returned blob (GIF, JPEG, PNG,
1467 %  etc.).  This method is the equivalent of WriteImage(), but writes the
1468 %  formatted "file" to a memory buffer rather than to an actual file.
1469 %
1470 %  The format of the ImageToBlob method is:
1471 %
1472 %      unsigned char *ImageToBlob(const ImageInfo *image_info,Image *image,
1473 %        size_t *length,ExceptionInfo *exception)
1474 %
1475 %  A description of each parameter follows:
1476 %
1477 %    o image_info: the image info.
1478 %
1479 %    o image: the image.
1480 %
1481 %    o length: This pointer to a size_t integer sets the initial length of the
1482 %      blob.  On return, it reflects the actual length of the blob.
1483 %
1484 %    o exception: return any errors or warnings in this structure.
1485 %
1486 */
1487 MagickExport unsigned char *ImageToBlob(const ImageInfo *image_info,
1488   Image *image,size_t *length,ExceptionInfo *exception)
1489 {
1490   const MagickInfo
1491     *magick_info;
1492
1493   ImageInfo
1494     *blob_info;
1495
1496   MagickBooleanType
1497     status;
1498
1499   unsigned char
1500     *blob;
1501
1502   assert(image_info != (const ImageInfo *) NULL);
1503   assert(image_info->signature == MagickSignature);
1504   if (image_info->debug != MagickFalse)
1505     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1506       image_info->filename);
1507   assert(image != (Image *) NULL);
1508   assert(image->signature == MagickSignature);
1509   assert(exception != (ExceptionInfo *) NULL);
1510   *length=0;
1511   blob=(unsigned char *) NULL;
1512   blob_info=CloneImageInfo(image_info);
1513   blob_info->adjoin=MagickFalse;
1514   (void) SetImageInfo(blob_info,1,exception);
1515   if (*blob_info->magick != '\0')
1516     (void) CopyMagickString(image->magick,blob_info->magick,MaxTextExtent);
1517   magick_info=GetMagickInfo(image->magick,exception);
1518   if (magick_info == (const MagickInfo *) NULL)
1519     {
1520       (void) ThrowMagickException(exception,GetMagickModule(),
1521         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
1522         image->filename);
1523       return(blob);
1524     }
1525   (void) CopyMagickString(blob_info->magick,image->magick,MaxTextExtent);
1526   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1527     {
1528       /*
1529         Native blob support for this image format.
1530       */
1531       blob_info->length=0;
1532       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1533         sizeof(unsigned char));
1534       if (blob_info->blob == (void *) NULL)
1535         (void) ThrowMagickException(exception,GetMagickModule(),
1536           ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
1537       else
1538         {
1539           (void) CloseBlob(image);
1540           image->blob->exempt=MagickTrue;
1541           *image->filename='\0';
1542           status=WriteImage(blob_info,image,exception);
1543           *length=image->blob->length;
1544           blob=DetachBlob(image->blob);
1545           if (status == MagickFalse)
1546             blob=(unsigned char *) RelinquishMagickMemory(blob);
1547           else
1548             blob=(unsigned char *) ResizeQuantumMemory(blob,*length+1,
1549               sizeof(*blob));
1550         }
1551     }
1552   else
1553     {
1554       char
1555         unique[MaxTextExtent];
1556
1557       int
1558         file;
1559
1560       /*
1561         Write file to disk in blob image format.
1562       */
1563       file=AcquireUniqueFileResource(unique);
1564       if (file == -1)
1565         {
1566           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1567             image_info->filename);
1568         }
1569       else
1570         {
1571           blob_info->file=fdopen(file,"wb");
1572           if (blob_info->file != (FILE *) NULL)
1573             {
1574               (void) FormatLocaleString(image->filename,MaxTextExtent,"%s:%s",
1575                 image->magick,unique);
1576               status=WriteImage(blob_info,image,exception);
1577               (void) fclose(blob_info->file);
1578               if (status != MagickFalse)
1579                 blob=FileToBlob(image->filename,~0UL,length,exception);
1580             }
1581           (void) RelinquishUniqueFileResource(unique);
1582         }
1583     }
1584   blob_info=DestroyImageInfo(blob_info);
1585   return(blob);
1586 }
1587 \f
1588 /*
1589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590 %                                                                             %
1591 %                                                                             %
1592 %                                                                             %
1593 %   I m a g e T o F i l e                                                     %
1594 %                                                                             %
1595 %                                                                             %
1596 %                                                                             %
1597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1598 %
1599 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
1600 %  occurs otherwise MagickTrue.
1601 %
1602 %  The format of the ImageToFile method is:
1603 %
1604 %       MagickBooleanType ImageToFile(Image *image,char *filename,
1605 %         ExceptionInfo *exception)
1606 %
1607 %  A description of each parameter follows:
1608 %
1609 %    o image: the image.
1610 %
1611 %    o filename: Write the image to this file.
1612 %
1613 %    o exception: return any errors or warnings in this structure.
1614 %
1615 */
1616 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1617   ExceptionInfo *exception)
1618 {
1619   int
1620     file;
1621
1622   register const unsigned char
1623     *p;
1624
1625   register size_t
1626     i;
1627
1628   size_t
1629     length,
1630     quantum;
1631
1632   ssize_t
1633     count;
1634
1635   struct stat
1636     file_stats;
1637
1638   unsigned char
1639     *buffer;
1640
1641   assert(image != (Image *) NULL);
1642   assert(image->signature == MagickSignature);
1643   assert(image->blob != (BlobInfo *) NULL);
1644   assert(image->blob->type != UndefinedStream);
1645   if (image->debug != MagickFalse)
1646     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1647   assert(filename != (const char *) NULL);
1648   if (*filename == '\0')
1649     file=AcquireUniqueFileResource(filename);
1650   else
1651     if (LocaleCompare(filename,"-") == 0)
1652       file=fileno(stdout);
1653     else
1654       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1655   if (file == -1)
1656     {
1657       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1658       return(MagickFalse);
1659     }
1660   quantum=(size_t) MagickMaxBufferExtent;
1661   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1662     quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
1663       MagickMaxBufferExtent);
1664   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1665   if (buffer == (unsigned char *) NULL)
1666     {
1667       file=close(file)-1;
1668       (void) ThrowMagickException(exception,GetMagickModule(),
1669         ResourceLimitError,"MemoryAllocationError","'%s'",filename);
1670       return(MagickFalse);
1671     }
1672   length=0;
1673   p=ReadBlobStream(image,quantum,buffer,&count);
1674   for (i=0; count > 0; p=ReadBlobStream(image,quantum,buffer,&count))
1675   {
1676     length=(size_t) count;
1677     for (i=0; i < length; i+=count)
1678     {
1679       count=write(file,p+i,(size_t) (length-i));
1680       if (count <= 0)
1681         {
1682           count=0;
1683           if (errno != EINTR)
1684             break;
1685         }
1686     }
1687     if (i < length)
1688       break;
1689   }
1690   if (LocaleCompare(filename,"-") != 0)
1691     file=close(file);
1692   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1693   if ((file == -1) || (i < length))
1694     {
1695       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1696       return(MagickFalse);
1697     }
1698   return(MagickTrue);
1699 }
1700 \f
1701 /*
1702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1703 %                                                                             %
1704 %                                                                             %
1705 %                                                                             %
1706 %   I m a g e s T o B l o b                                                   %
1707 %                                                                             %
1708 %                                                                             %
1709 %                                                                             %
1710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1711 %
1712 %  ImagesToBlob() implements direct to memory image formats.  It returns the
1713 %  image sequence as a blob and its length.  The magick member of the ImageInfo
1714 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
1715 %
1716 %  Note, some image formats do not permit multiple images to the same image
1717 %  stream (e.g. JPEG).  in this instance, just the first image of the
1718 %  sequence is returned as a blob.
1719 %
1720 %  The format of the ImagesToBlob method is:
1721 %
1722 %      unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1723 %        size_t *length,ExceptionInfo *exception)
1724 %
1725 %  A description of each parameter follows:
1726 %
1727 %    o image_info: the image info.
1728 %
1729 %    o images: the image list.
1730 %
1731 %    o length: This pointer to a size_t integer sets the initial length of the
1732 %      blob.  On return, it reflects the actual length of the blob.
1733 %
1734 %    o exception: return any errors or warnings in this structure.
1735 %
1736 */
1737 MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1738   Image *images,size_t *length,ExceptionInfo *exception)
1739 {
1740   const MagickInfo
1741     *magick_info;
1742
1743   ImageInfo
1744     *blob_info;
1745
1746   MagickBooleanType
1747     status;
1748
1749   unsigned char
1750     *blob;
1751
1752   assert(image_info != (const ImageInfo *) NULL);
1753   assert(image_info->signature == MagickSignature);
1754   if (image_info->debug != MagickFalse)
1755     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1756       image_info->filename);
1757   assert(images != (Image *) NULL);
1758   assert(images->signature == MagickSignature);
1759   assert(exception != (ExceptionInfo *) NULL);
1760   *length=0;
1761   blob=(unsigned char *) NULL;
1762   blob_info=CloneImageInfo(image_info);
1763   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1764     exception);
1765   if (*blob_info->magick != '\0')
1766     (void) CopyMagickString(images->magick,blob_info->magick,MaxTextExtent);
1767   if (blob_info->adjoin == MagickFalse)
1768     {
1769       blob_info=DestroyImageInfo(blob_info);
1770       return(ImageToBlob(image_info,images,length,exception));
1771     }
1772   magick_info=GetMagickInfo(images->magick,exception);
1773   if (magick_info == (const MagickInfo *) NULL)
1774     {
1775       (void) ThrowMagickException(exception,GetMagickModule(),
1776         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","'%s'",
1777         images->filename);
1778       return(blob);
1779     }
1780   (void) CopyMagickString(blob_info->magick,images->magick,MaxTextExtent);
1781   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1782     {
1783       /*
1784         Native blob support for this images format.
1785       */
1786       blob_info->length=0;
1787       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1788         sizeof(unsigned char));
1789       if (blob_info->blob == (void *) NULL)
1790         (void) ThrowMagickException(exception,GetMagickModule(),
1791           ResourceLimitError,"MemoryAllocationFailed","'%s'",images->filename);
1792       else
1793         {
1794           images->blob->exempt=MagickTrue;
1795           *images->filename='\0';
1796           status=WriteImages(blob_info,images,images->filename,exception);
1797           if ((status != MagickFalse) && (images->blob->length != 0))
1798             {
1799               *length=images->blob->length;
1800               blob=DetachBlob(images->blob);
1801               blob=(unsigned char *) ResizeQuantumMemory(blob,*length,
1802                 sizeof(*blob));
1803             }
1804         }
1805     }
1806   else
1807     {
1808       char
1809         filename[MaxTextExtent],
1810         unique[MaxTextExtent];
1811
1812       int
1813         file;
1814
1815       /*
1816         Write file to disk in blob images format.
1817       */
1818       file=AcquireUniqueFileResource(unique);
1819       if (file == -1)
1820         {
1821           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
1822             image_info->filename);
1823         }
1824       else
1825         {
1826           blob_info->file=fdopen(file,"wb");
1827           if (blob_info->file != (FILE *) NULL)
1828             {
1829               (void) FormatLocaleString(filename,MaxTextExtent,"%s:%s",
1830                 images->magick,unique);
1831               status=WriteImages(blob_info,images,filename,exception);
1832               (void) fclose(blob_info->file);
1833               if (status != MagickFalse)
1834                 blob=FileToBlob(images->filename,~0UL,length,exception);
1835             }
1836           (void) RelinquishUniqueFileResource(unique);
1837         }
1838     }
1839   blob_info=DestroyImageInfo(blob_info);
1840   return(blob);
1841 }
1842 /*
1843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1844 %                                                                             %
1845 %                                                                             %
1846 %                                                                             %
1847 %   I n j e c t I m a g e B l o b                                             %
1848 %                                                                             %
1849 %                                                                             %
1850 %                                                                             %
1851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1852 %
1853 %  InjectImageBlob() injects the image with a copy of itself in the specified
1854 %  format (e.g. inject JPEG into a PDF image).
1855 %
1856 %  The format of the InjectImageBlob method is:
1857 %
1858 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1859 %        Image *image,Image *inject_image,const char *format,
1860 %        ExceptionInfo *exception)
1861 %
1862 %  A description of each parameter follows:
1863 %
1864 %    o image_info: the image info..
1865 %
1866 %    o image: the image.
1867 %
1868 %    o inject_image: inject into the image stream.
1869 %
1870 %    o format: the image format.
1871 %
1872 %    o exception: return any errors or warnings in this structure.
1873 %
1874 */
1875 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
1876   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
1877 {
1878   char
1879     filename[MaxTextExtent];
1880
1881   FILE
1882     *unique_file;
1883
1884   Image
1885     *byte_image;
1886
1887   ImageInfo
1888     *write_info;
1889
1890   int
1891     file;
1892
1893   MagickBooleanType
1894     status;
1895
1896   register ssize_t
1897     i;
1898
1899   size_t
1900     quantum;
1901
1902   ssize_t
1903     count;
1904
1905   struct stat
1906     file_stats;
1907
1908   unsigned char
1909     *buffer;
1910
1911   /*
1912     Write inject image to a temporary file.
1913   */
1914   assert(image_info != (ImageInfo *) NULL);
1915   assert(image_info->signature == MagickSignature);
1916   assert(image != (Image *) NULL);
1917   assert(image->signature == MagickSignature);
1918   if (image->debug != MagickFalse)
1919     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1920   assert(inject_image != (Image *) NULL);
1921   assert(inject_image->signature == MagickSignature);
1922   assert(exception != (ExceptionInfo *) NULL);
1923   unique_file=(FILE *) NULL;
1924   file=AcquireUniqueFileResource(filename);
1925   if (file != -1)
1926     unique_file=fdopen(file,"wb");
1927   if ((file == -1) || (unique_file == (FILE *) NULL))
1928     {
1929       (void) CopyMagickString(image->filename,filename,MaxTextExtent);
1930       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
1931         image->filename);
1932       return(MagickFalse);
1933     }
1934   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
1935   if (byte_image == (Image *) NULL)
1936     {
1937       (void) fclose(unique_file);
1938       (void) RelinquishUniqueFileResource(filename);
1939       return(MagickFalse);
1940     }
1941   (void) FormatLocaleString(byte_image->filename,MaxTextExtent,"%s:%s",format,
1942     filename);
1943   DestroyBlob(byte_image);
1944   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
1945   write_info=CloneImageInfo(image_info);
1946   SetImageInfoFile(write_info,unique_file);
1947   status=WriteImage(write_info,byte_image,exception);
1948   write_info=DestroyImageInfo(write_info);
1949   byte_image=DestroyImage(byte_image);
1950   (void) fclose(unique_file);
1951   if (status == MagickFalse)
1952     {
1953       (void) RelinquishUniqueFileResource(filename);
1954       return(MagickFalse);
1955     }
1956   /*
1957     Inject into image stream.
1958   */
1959   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1960   if (file == -1)
1961     {
1962       (void) RelinquishUniqueFileResource(filename);
1963       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
1964         image_info->filename);
1965       return(MagickFalse);
1966     }
1967   quantum=(size_t) MagickMaxBufferExtent;
1968   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1969     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1970   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1971   if (buffer == (unsigned char *) NULL)
1972     {
1973       (void) RelinquishUniqueFileResource(filename);
1974       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1975         image->filename);
1976     }
1977   for (i=0; ; i+=count)
1978   {
1979     count=(ssize_t) read(file,buffer,quantum);
1980     if (count <= 0)
1981       {
1982         count=0;
1983         if (errno != EINTR)
1984           break;
1985       }
1986     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
1987       MagickFalse;
1988   }
1989   file=close(file);
1990   if (file == -1)
1991     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
1992   (void) RelinquishUniqueFileResource(filename);
1993   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1994   return(status);
1995 }
1996 \f
1997 /*
1998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1999 %                                                                             %
2000 %                                                                             %
2001 %                                                                             %
2002 +   I s B l o b E x e m p t                                                   %
2003 %                                                                             %
2004 %                                                                             %
2005 %                                                                             %
2006 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2007 %
2008 %  IsBlobExempt() returns true if the blob is exempt.
2009 %
2010 %  The format of the IsBlobExempt method is:
2011 %
2012 %       MagickBooleanType IsBlobExempt(const Image *image)
2013 %
2014 %  A description of each parameter follows:
2015 %
2016 %    o image: the image.
2017 %
2018 */
2019 MagickPrivate MagickBooleanType IsBlobExempt(const Image *image)
2020 {
2021   assert(image != (const Image *) NULL);
2022   assert(image->signature == MagickSignature);
2023   if (image->debug != MagickFalse)
2024     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2025   return(image->blob->exempt);
2026 }
2027 \f
2028 /*
2029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2030 %                                                                             %
2031 %                                                                             %
2032 %                                                                             %
2033 +   I s B l o b S e e k a b l e                                               %
2034 %                                                                             %
2035 %                                                                             %
2036 %                                                                             %
2037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2038 %
2039 %  IsBlobSeekable() returns true if the blob is seekable.
2040 %
2041 %  The format of the IsBlobSeekable method is:
2042 %
2043 %       MagickBooleanType IsBlobSeekable(const Image *image)
2044 %
2045 %  A description of each parameter follows:
2046 %
2047 %    o image: the image.
2048 %
2049 */
2050 MagickPrivate MagickBooleanType IsBlobSeekable(const Image *image)
2051 {
2052   MagickBooleanType
2053     seekable;
2054
2055   assert(image != (const Image *) NULL);
2056   assert(image->signature == MagickSignature);
2057   if (image->debug != MagickFalse)
2058     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2059   switch (image->blob->type)
2060   {
2061     case FileStream:
2062     case BlobStream:
2063     case ZipStream:
2064     {
2065       seekable=MagickTrue;
2066       break;
2067     }
2068     default:
2069     {
2070       seekable=MagickFalse;
2071       break;
2072     }
2073   }
2074   return(seekable);
2075 }
2076 \f
2077 /*
2078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2079 %                                                                             %
2080 %                                                                             %
2081 %                                                                             %
2082 +   I s B l o b T e m p o r a r y                                             %
2083 %                                                                             %
2084 %                                                                             %
2085 %                                                                             %
2086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2087 %
2088 %  IsBlobTemporary() returns true if the blob is temporary.
2089 %
2090 %  The format of the IsBlobTemporary method is:
2091 %
2092 %       MagickBooleanType IsBlobTemporary(const Image *image)
2093 %
2094 %  A description of each parameter follows:
2095 %
2096 %    o image: the image.
2097 %
2098 */
2099 MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
2100 {
2101   assert(image != (const Image *) NULL);
2102   assert(image->signature == MagickSignature);
2103   if (image->debug != MagickFalse)
2104     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2105   return(image->blob->temporary);
2106 }
2107 \f
2108 /*
2109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2110 %                                                                             %
2111 %                                                                             %
2112 %                                                                             %
2113 +  M a p B l o b                                                              %
2114 %                                                                             %
2115 %                                                                             %
2116 %                                                                             %
2117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2118 %
2119 %  MapBlob() creates a mapping from a file to a binary large object.
2120 %
2121 %  The format of the MapBlob method is:
2122 %
2123 %      unsigned char *MapBlob(int file,const MapMode mode,
2124 %        const MagickOffsetType offset,const size_t length)
2125 %
2126 %  A description of each parameter follows:
2127 %
2128 %    o file: map this file descriptor.
2129 %
2130 %    o mode: ReadMode, WriteMode, or IOMode.
2131 %
2132 %    o offset: starting at this offset within the file.
2133 %
2134 %    o length: the length of the mapping is returned in this pointer.
2135 %
2136 */
2137 MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2138   const MagickOffsetType offset,const size_t length)
2139 {
2140 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2141   int
2142     flags,
2143     protection;
2144
2145   unsigned char
2146     *map;
2147
2148   /*
2149     Map file.
2150   */
2151   flags=0;
2152   if (file == -1)
2153 #if defined(MAP_ANONYMOUS)
2154     flags|=MAP_ANONYMOUS;
2155 #else
2156     return((unsigned char *) NULL);
2157 #endif
2158   switch (mode)
2159   {
2160     case ReadMode:
2161     default:
2162     {
2163       protection=PROT_READ;
2164       flags|=MAP_PRIVATE;
2165       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2166         (off_t) offset);
2167       break;
2168     }
2169     case WriteMode:
2170     {
2171       protection=PROT_WRITE;
2172       flags|=MAP_SHARED;
2173       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2174         (off_t) offset);
2175 #if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2176       (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2177         POSIX_MADV_WILLNEED);
2178 #endif
2179       break;
2180     }
2181     case IOMode:
2182     {
2183       protection=PROT_READ | PROT_WRITE;
2184       flags|=MAP_SHARED;
2185       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2186         (off_t) offset);
2187       break;
2188     }
2189   }
2190   if (map == (unsigned char *) MAP_FAILED)
2191     return((unsigned char *) NULL);
2192   return(map);
2193 #else
2194   (void) file;
2195   (void) mode;
2196   (void) offset;
2197   (void) length;
2198   return((unsigned char *) NULL);
2199 #endif
2200 }
2201 \f
2202 /*
2203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2204 %                                                                             %
2205 %                                                                             %
2206 %                                                                             %
2207 +  M S B O r d e r L o n g                                                    %
2208 %                                                                             %
2209 %                                                                             %
2210 %                                                                             %
2211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2212 %
2213 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
2214 %  most-significant byte first.
2215 %
2216 %  The format of the MSBOrderLong method is:
2217 %
2218 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
2219 %
2220 %  A description of each parameter follows.
2221 %
2222 %   o  buffer:  Specifies a pointer to a buffer of integers.
2223 %
2224 %   o  length:  Specifies the length of the buffer.
2225 %
2226 */
2227 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2228 {
2229   int
2230     c;
2231
2232   register unsigned char
2233     *p,
2234     *q;
2235
2236   assert(buffer != (unsigned char *) NULL);
2237   q=buffer+length;
2238   while (buffer < q)
2239   {
2240     p=buffer+3;
2241     c=(int) (*p);
2242     *p=(*buffer);
2243     *buffer++=(unsigned char) c;
2244     p=buffer+1;
2245     c=(int) (*p);
2246     *p=(*buffer);
2247     *buffer++=(unsigned char) c;
2248     buffer+=2;
2249   }
2250 }
2251 \f
2252 /*
2253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2254 %                                                                             %
2255 %                                                                             %
2256 %                                                                             %
2257 +  M S B O r d e r S h o r t                                                  %
2258 %                                                                             %
2259 %                                                                             %
2260 %                                                                             %
2261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2262 %
2263 %  MSBOrderShort() converts a least-significant byte first buffer of integers
2264 %  to most-significant byte first.
2265 %
2266 %  The format of the MSBOrderShort method is:
2267 %
2268 %      void MSBOrderShort(unsigned char *p,const size_t length)
2269 %
2270 %  A description of each parameter follows.
2271 %
2272 %   o  p:  Specifies a pointer to a buffer of integers.
2273 %
2274 %   o  length:  Specifies the length of the buffer.
2275 %
2276 */
2277 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2278 {
2279   int
2280     c;
2281
2282   register unsigned char
2283     *q;
2284
2285   assert(p != (unsigned char *) NULL);
2286   q=p+length;
2287   while (p < q)
2288   {
2289     c=(int) (*p);
2290     *p=(*(p+1));
2291     p++;
2292     *p++=(unsigned char) c;
2293   }
2294 }
2295 \f
2296 /*
2297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2298 %                                                                             %
2299 %                                                                             %
2300 %                                                                             %
2301 +   O p e n B l o b                                                           %
2302 %                                                                             %
2303 %                                                                             %
2304 %                                                                             %
2305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2306 %
2307 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
2308 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
2309 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2310 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
2311 %  from a system command.
2312 %
2313 %  The format of the OpenBlob method is:
2314 %
2315 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2316 %        const BlobMode mode,ExceptionInfo *exception)
2317 %
2318 %  A description of each parameter follows:
2319 %
2320 %    o image_info: the image info.
2321 %
2322 %    o image: the image.
2323 %
2324 %    o mode: the mode for opening the file.
2325 %
2326 */
2327 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2328   Image *image,const BlobMode mode,ExceptionInfo *exception)
2329 {
2330   char
2331     extension[MaxTextExtent],
2332     filename[MaxTextExtent];
2333
2334   const char
2335     *type;
2336
2337   MagickBooleanType
2338     status;
2339
2340   PolicyRights
2341     rights;
2342
2343   assert(image_info != (ImageInfo *) NULL);
2344   assert(image_info->signature == MagickSignature);
2345   if (image_info->debug != MagickFalse)
2346     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2347       image_info->filename);
2348   assert(image != (Image *) NULL);
2349   assert(image->signature == MagickSignature);
2350   if (image_info->blob != (void *) NULL)
2351     {
2352       if (image_info->stream != (StreamHandler) NULL)
2353         image->blob->stream=(StreamHandler) image_info->stream;
2354       AttachBlob(image->blob,image_info->blob,image_info->length);
2355       return(MagickTrue);
2356     }
2357   (void) DetachBlob(image->blob);
2358   switch (mode)
2359   {
2360     default: type="r"; break;
2361     case ReadBlobMode: type="r"; break;
2362     case ReadBinaryBlobMode: type="rb"; break;
2363     case WriteBlobMode: type="w"; break;
2364     case WriteBinaryBlobMode: type="w+b"; break;
2365     case AppendBlobMode: type="a"; break;
2366     case AppendBinaryBlobMode: type="a+b"; break;
2367   }
2368   if (*type != 'r')
2369     image->blob->synchronize=image_info->synchronize;
2370   if (image_info->stream != (StreamHandler) NULL)
2371     {
2372       image->blob->stream=(StreamHandler) image_info->stream;
2373       if (*type == 'w')
2374         {
2375           image->blob->type=FifoStream;
2376           return(MagickTrue);
2377         }
2378     }
2379   /*
2380     Open image file.
2381   */
2382   *filename='\0';
2383   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2384   rights=ReadPolicyRights;
2385   if (*type == 'w')
2386     rights=WritePolicyRights;
2387   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2388     {
2389       errno=EPERM;
2390       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2391         "NotAuthorized","'%s'",filename);
2392       return(MagickFalse);
2393     }
2394   if ((LocaleCompare(filename,"-") == 0) ||
2395       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2396     {
2397       image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2398 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2399       if (strchr(type,'b') != (char *) NULL)
2400         setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2401 #endif
2402       image->blob->type=StandardStream;
2403       image->blob->exempt=MagickTrue;
2404       return(MagickTrue);
2405     }
2406   if (LocaleNCompare(filename,"fd:",3) == 0)
2407     {
2408       char
2409         mode[MaxTextExtent];
2410
2411       *mode=(*type);
2412       mode[1]='\0';
2413       image->blob->file_info.file=fdopen(StringToLong(filename+3),mode);
2414 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2415       if (strchr(type,'b') != (char *) NULL)
2416         setmode(_fileno(image->blob->file_info.file),_O_BINARY);
2417 #endif
2418       image->blob->type=StandardStream;
2419       image->blob->exempt=MagickTrue;
2420       return(MagickTrue);
2421     }
2422 #if defined(MAGICKCORE_HAVE_POPEN)
2423   if (*filename == '|')
2424     {
2425       char
2426         mode[MaxTextExtent];
2427
2428       /*
2429         Pipe image to or from a system command.
2430       */
2431 #if defined(SIGPIPE)
2432       if (*type == 'w')
2433         (void) signal(SIGPIPE,SIG_IGN);
2434 #endif
2435       *mode=(*type);
2436       mode[1]='\0';
2437       image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);
2438       if (image->blob->file_info.file == (FILE *) NULL)
2439         {
2440           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2441           return(MagickFalse);
2442         }
2443       image->blob->type=PipeStream;
2444       image->blob->exempt=MagickTrue;
2445       return(MagickTrue);
2446     }
2447 #endif
2448   status=GetPathAttributes(filename,&image->blob->properties);
2449 #if defined(S_ISFIFO)
2450   if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2451     {
2452       image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2453       if (image->blob->file_info.file == (FILE *) NULL)
2454         {
2455           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2456           return(MagickFalse);
2457         }
2458       image->blob->type=FileStream;
2459       image->blob->exempt=MagickTrue;
2460       return(MagickTrue);
2461     }
2462 #endif
2463   GetPathComponent(image->filename,ExtensionPath,extension);
2464   if (*type == 'w')
2465     {
2466       (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2467       if ((image_info->adjoin == MagickFalse) ||
2468           (strchr(filename,'%') != (char *) NULL))
2469         {
2470           /*
2471             Form filename for multi-part images.
2472           */
2473           (void) InterpretImageFilename(image_info,image,image->filename,(int)
2474             image->scene,filename,exception);
2475           if ((LocaleCompare(filename,image->filename) == 0) &&
2476               ((GetPreviousImageInList(image) != (Image *) NULL) ||
2477                (GetNextImageInList(image) != (Image *) NULL)))
2478             {
2479               char
2480                 path[MaxTextExtent];
2481
2482               GetPathComponent(image->filename,RootPath,path);
2483               if (*extension == '\0')
2484                 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
2485                   path,(double) image->scene);
2486               else
2487                 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
2488                   path,(double) image->scene,extension);
2489             }
2490           (void) CopyMagickString(image->filename,filename,MaxTextExtent);
2491 #if defined(macintosh)
2492           SetApplicationType(filename,image_info->magick,'8BIM');
2493 #endif
2494         }
2495     }
2496   if (image_info->file != (FILE *) NULL)
2497     {
2498       image->blob->file_info.file=image_info->file;
2499       image->blob->type=FileStream;
2500       image->blob->exempt=MagickTrue;
2501     }
2502   else
2503     if (*type == 'r')
2504       {
2505         image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2506         if (image->blob->file_info.file != (FILE *) NULL)
2507           {
2508             size_t
2509               count;
2510
2511             unsigned char
2512               magick[3];
2513
2514             image->blob->type=FileStream;
2515 #if defined(MAGICKCORE_HAVE_SETVBUF)
2516             (void) setvbuf(image->blob->file_info.file,(char *) NULL,
2517               (int) _IOFBF,16384);
2518 #endif
2519             (void) ResetMagickMemory(magick,0,sizeof(magick));
2520             count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2521             (void) rewind(image->blob->file_info.file);
2522             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2523                "  read %.20g magic header bytes",(double) count);
2524 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2525             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2526                 ((int) magick[2] == 0x08))
2527               {
2528                 (void) fclose(image->blob->file_info.file);
2529                 image->blob->file_info.gzfile=gzopen(filename,type);
2530                 if (image->blob->file_info.gzfile != (gzFile) NULL)
2531                   image->blob->type=ZipStream;
2532                }
2533 #endif
2534 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2535             if (strncmp((char *) magick,"BZh",3) == 0)
2536               {
2537                 (void) fclose(image->blob->file_info.file);
2538                 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2539                 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2540                   image->blob->type=BZipStream;
2541               }
2542 #endif
2543             if (image->blob->type == FileStream)
2544               {
2545                 const MagickInfo
2546                   *magick_info;
2547
2548                 ExceptionInfo
2549                   *sans_exception;
2550
2551                 struct stat
2552                   *properties;
2553
2554                 sans_exception=AcquireExceptionInfo();
2555                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2556                 sans_exception=DestroyExceptionInfo(sans_exception);
2557                 properties=(&image->blob->properties);
2558                 if ((magick_info != (const MagickInfo *) NULL) &&
2559                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2560                     (properties->st_size <= MagickMaxBufferExtent))
2561                   {
2562                     size_t
2563                       length;
2564
2565                     void
2566                       *blob;
2567
2568                     length=(size_t) properties->st_size;
2569                     blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,
2570                       0,length);
2571                     if (blob != (void *) NULL)
2572                       {
2573                         /*
2574                           Format supports blobs-- use memory-mapped I/O.
2575                         */
2576                         if (image_info->file != (FILE *) NULL)
2577                           image->blob->exempt=MagickFalse;
2578                         else
2579                           {
2580                             (void) fclose(image->blob->file_info.file);
2581                             image->blob->file_info.file=(FILE *) NULL;
2582                           }
2583                         AttachBlob(image->blob,blob,length);
2584                         image->blob->mapped=MagickTrue;
2585                       }
2586                   }
2587               }
2588           }
2589         }
2590       else
2591 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2592         if ((LocaleCompare(extension,"Z") == 0) ||
2593             (LocaleCompare(extension,"gz") == 0) ||
2594             (LocaleCompare(extension,"wmz") == 0) ||
2595             (LocaleCompare(extension,"svgz") == 0))
2596           {
2597             if (mode == WriteBinaryBlobMode)
2598               type="wb";
2599             image->blob->file_info.gzfile=gzopen(filename,type);
2600             if (image->blob->file_info.gzfile != (gzFile) NULL)
2601               image->blob->type=ZipStream;
2602           }
2603         else
2604 #endif
2605 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2606           if (LocaleCompare(extension,"bz2") == 0)
2607             {
2608               image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2609               if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2610                 image->blob->type=BZipStream;
2611             }
2612           else
2613 #endif
2614             {
2615               image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2616               if (image->blob->file_info.file != (FILE *) NULL)
2617                 {
2618                   image->blob->type=FileStream;
2619 #if defined(MAGICKCORE_HAVE_SETVBUF)
2620                   (void) setvbuf(image->blob->file_info.file,(char *) NULL,(int) _IOFBF,
2621                     16384);
2622 #endif
2623                 }
2624        }
2625   image->blob->status=MagickFalse;
2626   if (image->blob->type != UndefinedStream)
2627     image->blob->size=GetBlobSize(image);
2628   else
2629     {
2630       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2631       return(MagickFalse);
2632     }
2633   return(MagickTrue);
2634 }
2635 \f
2636 /*
2637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2638 %                                                                             %
2639 %                                                                             %
2640 %                                                                             %
2641 +   P i n g B l o b                                                           %
2642 %                                                                             %
2643 %                                                                             %
2644 %                                                                             %
2645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2646 %
2647 %  PingBlob() returns all the attributes of an image or image sequence except
2648 %  for the pixels.  It is much faster and consumes far less memory than
2649 %  BlobToImage().  On failure, a NULL image is returned and exception
2650 %  describes the reason for the failure.
2651 %
2652 %  The format of the PingBlob method is:
2653 %
2654 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
2655 %        const size_t length,ExceptionInfo *exception)
2656 %
2657 %  A description of each parameter follows:
2658 %
2659 %    o image_info: the image info.
2660 %
2661 %    o blob: the address of a character stream in one of the image formats
2662 %      understood by ImageMagick.
2663 %
2664 %    o length: This size_t integer reflects the length in bytes of the blob.
2665 %
2666 %    o exception: return any errors or warnings in this structure.
2667 %
2668 */
2669
2670 #if defined(__cplusplus) || defined(c_plusplus)
2671 extern "C" {
2672 #endif
2673
2674 static size_t PingStream(const Image *magick_unused(image),
2675   const void *magick_unused(pixels),const size_t columns)
2676 {
2677   return(columns);
2678 }
2679
2680 #if defined(__cplusplus) || defined(c_plusplus)
2681 }
2682 #endif
2683
2684 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2685   const size_t length,ExceptionInfo *exception)
2686 {
2687   Image
2688     *image;
2689
2690   ImageInfo
2691     *ping_info;
2692
2693   assert(image_info != (ImageInfo *) NULL);
2694   assert(image_info->signature == MagickSignature);
2695   if (image_info->debug != MagickFalse)
2696     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2697       image_info->filename);
2698   assert(exception != (ExceptionInfo *) NULL);
2699   if ((blob == (const void *) NULL) || (length == 0))
2700     {
2701       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2702         "UnrecognizedImageFormat","'%s'",image_info->magick);
2703       return((Image *) NULL);
2704     }
2705   ping_info=CloneImageInfo(image_info);
2706   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2707   if (ping_info->blob == (const void *) NULL)
2708     {
2709       (void) ThrowMagickException(exception,GetMagickModule(),
2710         ResourceLimitFatalError,"MemoryAllocationFailed","'%s'","");
2711       return((Image *) NULL);
2712     }
2713   (void) memcpy(ping_info->blob,blob,length);
2714   ping_info->length=length;
2715   ping_info->ping=MagickTrue;
2716   image=ReadStream(ping_info,&PingStream,exception);
2717   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2718   ping_info=DestroyImageInfo(ping_info);
2719   return(image);
2720 }
2721 \f
2722 /*
2723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2724 %                                                                             %
2725 %                                                                             %
2726 %                                                                             %
2727 +  R e a d B l o b                                                            %
2728 %                                                                             %
2729 %                                                                             %
2730 %                                                                             %
2731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2732 %
2733 %  ReadBlob() reads data from the blob or image file and returns it.  It
2734 %  returns the number of bytes read.
2735 %
2736 %  The format of the ReadBlob method is:
2737 %
2738 %      ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2739 %
2740 %  A description of each parameter follows:
2741 %
2742 %    o image: the image.
2743 %
2744 %    o length:  Specifies an integer representing the number of bytes to read
2745 %      from the file.
2746 %
2747 %    o data:  Specifies an area to place the information requested from the
2748 %      file.
2749 %
2750 */
2751 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2752   unsigned char *data)
2753 {
2754   int
2755     c;
2756
2757   register unsigned char
2758     *q;
2759
2760   ssize_t
2761     count;
2762
2763   assert(image != (Image *) NULL);
2764   assert(image->signature == MagickSignature);
2765   assert(image->blob != (BlobInfo *) NULL);
2766   assert(image->blob->type != UndefinedStream);
2767   if (length == 0)
2768     return(0);
2769   assert(data != (void *) NULL);
2770   count=0;
2771   q=data;
2772   switch (image->blob->type)
2773   {
2774     case UndefinedStream:
2775       break;
2776     case StandardStream:
2777     {
2778       count=(ssize_t) read(fileno(image->blob->file_info.file),q,length);
2779       break;
2780     }
2781     case FileStream:
2782     case PipeStream:
2783     {
2784       switch (length)
2785       {
2786         default:
2787         {
2788           count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
2789           break;
2790         }
2791         case 2:
2792         {
2793           c=getc(image->blob->file_info.file);
2794           if (c == EOF)
2795             break;
2796           *q++=(unsigned char) c;
2797           count++;
2798         }
2799         case 1:
2800         {
2801           c=getc(image->blob->file_info.file);
2802           if (c == EOF)
2803             break;
2804           *q++=(unsigned char) c;
2805           count++;
2806         }
2807         case 0:
2808           break;
2809       }
2810       break;
2811     }
2812     case ZipStream:
2813     {
2814 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2815       switch (length)
2816       {
2817         default:
2818         {
2819           count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
2820             (unsigned int) length);
2821           break;
2822         }
2823         case 2:
2824         {
2825           c=gzgetc(image->blob->file_info.gzfile);
2826           if (c == EOF)
2827             break;
2828           *q++=(unsigned char) c;
2829           count++;
2830         }
2831         case 1:
2832         {
2833           c=gzgetc(image->blob->file_info.gzfile);
2834           if (c == EOF)
2835             break;
2836           *q++=(unsigned char) c;
2837           count++;
2838         }
2839         case 0:
2840           break;
2841       }
2842 #endif
2843       break;
2844     }
2845     case BZipStream:
2846     {
2847 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2848       count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,
2849         (int) length);
2850 #endif
2851       break;
2852     }
2853     case FifoStream:
2854       break;
2855     case BlobStream:
2856     {
2857       register const unsigned char
2858         *p;
2859
2860       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2861         {
2862           image->blob->eof=MagickTrue;
2863           break;
2864         }
2865       p=image->blob->data+image->blob->offset;
2866       count=(ssize_t) MagickMin(length,(MagickSizeType) (image->blob->length-
2867         image->blob->offset));
2868       image->blob->offset+=count;
2869       if (count != (ssize_t) length)
2870         image->blob->eof=MagickTrue;
2871       (void) memcpy(q,p,(size_t) count);
2872       break;
2873     }
2874   }
2875   return(count);
2876 }
2877 \f
2878 /*
2879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2880 %                                                                             %
2881 %                                                                             %
2882 %                                                                             %
2883 +  R e a d B l o b B y t e                                                    %
2884 %                                                                             %
2885 %                                                                             %
2886 %                                                                             %
2887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2888 %
2889 %  ReadBlobByte() reads a single byte from the image file and returns it.
2890 %
2891 %  The format of the ReadBlobByte method is:
2892 %
2893 %      int ReadBlobByte(Image *image)
2894 %
2895 %  A description of each parameter follows.
2896 %
2897 %    o image: the image.
2898 %
2899 */
2900 MagickExport int ReadBlobByte(Image *image)
2901 {
2902   register const unsigned char
2903     *p;
2904
2905   ssize_t
2906     count;
2907
2908   unsigned char
2909     buffer[1];
2910
2911   assert(image != (Image *) NULL);
2912   assert(image->signature == MagickSignature);
2913   p=ReadBlobStream(image,1,buffer,&count);
2914   if (count != 1)
2915     return(EOF);
2916   return((int) (*p));
2917 }
2918 \f
2919 /*
2920 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2921 %                                                                             %
2922 %                                                                             %
2923 %                                                                             %
2924 +  R e a d B l o b D o u b l e                                                %
2925 %                                                                             %
2926 %                                                                             %
2927 %                                                                             %
2928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2929 %
2930 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2931 %  specified by the endian member of the image structure.
2932 %
2933 %  The format of the ReadBlobDouble method is:
2934 %
2935 %      double ReadBlobDouble(Image *image)
2936 %
2937 %  A description of each parameter follows.
2938 %
2939 %    o image: the image.
2940 %
2941 */
2942 MagickExport double ReadBlobDouble(Image *image)
2943 {
2944   union
2945   {
2946     MagickSizeType
2947       unsigned_value;
2948
2949     double
2950       double_value;
2951   } quantum;
2952
2953   quantum.double_value=0.0;
2954   quantum.unsigned_value=ReadBlobLongLong(image);
2955   return(quantum.double_value);
2956 }
2957 \f
2958 /*
2959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2960 %                                                                             %
2961 %                                                                             %
2962 %                                                                             %
2963 +  R e a d B l o b F l o a t                                                  %
2964 %                                                                             %
2965 %                                                                             %
2966 %                                                                             %
2967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2968 %
2969 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2970 %  specified by the endian member of the image structure.
2971 %
2972 %  The format of the ReadBlobFloat method is:
2973 %
2974 %      float ReadBlobFloat(Image *image)
2975 %
2976 %  A description of each parameter follows.
2977 %
2978 %    o image: the image.
2979 %
2980 */
2981 MagickExport float ReadBlobFloat(Image *image)
2982 {
2983   union
2984   {
2985     unsigned int
2986       unsigned_value;
2987
2988     float
2989       float_value;
2990   } quantum;
2991
2992   quantum.float_value=0.0;
2993   quantum.unsigned_value=ReadBlobLong(image);
2994   return(quantum.float_value);
2995 }
2996 \f
2997 /*
2998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2999 %                                                                             %
3000 %                                                                             %
3001 %                                                                             %
3002 +  R e a d B l o b L o n g                                                    %
3003 %                                                                             %
3004 %                                                                             %
3005 %                                                                             %
3006 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3007 %
3008 %  ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
3009 %  specified by the endian member of the image structure.
3010 %
3011 %  The format of the ReadBlobLong method is:
3012 %
3013 %      unsigned int ReadBlobLong(Image *image)
3014 %
3015 %  A description of each parameter follows.
3016 %
3017 %    o image: the image.
3018 %
3019 */
3020 MagickExport unsigned int ReadBlobLong(Image *image)
3021 {
3022   register const unsigned char
3023     *p;
3024
3025   ssize_t
3026     count;
3027
3028   unsigned char
3029     buffer[4];
3030
3031   unsigned int
3032     value;
3033
3034   assert(image != (Image *) NULL);
3035   assert(image->signature == MagickSignature);
3036   *buffer='\0';
3037   p=ReadBlobStream(image,4,buffer,&count);
3038   if (count != 4)
3039     return(0UL);
3040   if (image->endian == LSBEndian)
3041     {
3042       value=(unsigned int) (*p++);
3043       value|=((unsigned int) (*p++)) << 8;
3044       value|=((unsigned int) (*p++)) << 16;
3045       value|=((unsigned int) (*p++)) << 24;
3046       return(value);
3047     }
3048   value=((unsigned int) (*p++)) << 24;
3049   value|=((unsigned int) (*p++)) << 16;
3050   value|=((unsigned int) (*p++)) << 8;
3051   value|=((unsigned int) (*p++));
3052   return(value);
3053 }
3054 \f
3055 /*
3056 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3057 %                                                                             %
3058 %                                                                             %
3059 %                                                                             %
3060 +  R e a d B l o b L o n g L o n g                                            %
3061 %                                                                             %
3062 %                                                                             %
3063 %                                                                             %
3064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3065 %
3066 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3067 %  byte-order specified by the endian member of the image structure.
3068 %
3069 %  The format of the ReadBlobLongLong method is:
3070 %
3071 %      MagickSizeType ReadBlobLongLong(Image *image)
3072 %
3073 %  A description of each parameter follows.
3074 %
3075 %    o image: the image.
3076 %
3077 */
3078 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3079 {
3080   MagickSizeType
3081     value;
3082
3083   register const unsigned char
3084     *p;
3085
3086   ssize_t
3087     count;
3088
3089   unsigned char
3090     buffer[8];
3091
3092   assert(image != (Image *) NULL);
3093   assert(image->signature == MagickSignature);
3094   *buffer='\0';
3095   p=ReadBlobStream(image,8,buffer,&count);
3096   if (count != 8)
3097     return(MagickULLConstant(0));
3098   if (image->endian == LSBEndian)
3099     {
3100       value=(MagickSizeType) (*p++);
3101       value|=((MagickSizeType) (*p++)) << 8;
3102       value|=((MagickSizeType) (*p++)) << 16;
3103       value|=((MagickSizeType) (*p++)) << 24;
3104       value|=((MagickSizeType) (*p++)) << 32;
3105       value|=((MagickSizeType) (*p++)) << 40;
3106       value|=((MagickSizeType) (*p++)) << 48;
3107       value|=((MagickSizeType) (*p++)) << 56;
3108       return(value & MagickULLConstant(0xffffffffffffffff));
3109     }
3110   value=((MagickSizeType) (*p++)) << 56;
3111   value|=((MagickSizeType) (*p++)) << 48;
3112   value|=((MagickSizeType) (*p++)) << 40;
3113   value|=((MagickSizeType) (*p++)) << 32;
3114   value|=((MagickSizeType) (*p++)) << 24;
3115   value|=((MagickSizeType) (*p++)) << 16;
3116   value|=((MagickSizeType) (*p++)) << 8;
3117   value|=((MagickSizeType) (*p++));
3118   return(value & MagickULLConstant(0xffffffffffffffff));
3119 }
3120 \f
3121 /*
3122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3123 %                                                                             %
3124 %                                                                             %
3125 %                                                                             %
3126 +  R e a d B l o b S h o r t                                                  %
3127 %                                                                             %
3128 %                                                                             %
3129 %                                                                             %
3130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3131 %
3132 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3133 %  specified by the endian member of the image structure.
3134 %
3135 %  The format of the ReadBlobShort method is:
3136 %
3137 %      unsigned short ReadBlobShort(Image *image)
3138 %
3139 %  A description of each parameter follows.
3140 %
3141 %    o image: the image.
3142 %
3143 */
3144 MagickExport unsigned short ReadBlobShort(Image *image)
3145 {
3146   register const unsigned char
3147     *p;
3148
3149   register unsigned int
3150     value;
3151
3152   ssize_t
3153     count;
3154
3155   unsigned char
3156     buffer[2];
3157
3158   assert(image != (Image *) NULL);
3159   assert(image->signature == MagickSignature);
3160   *buffer='\0';
3161   p=ReadBlobStream(image,2,buffer,&count);
3162   if (count != 2)
3163     return((unsigned short) 0U);
3164   if (image->endian == LSBEndian)
3165     {
3166       value=(unsigned int) (*p++);
3167       value|=((unsigned int) (*p++)) << 8;
3168       return((unsigned short) (value & 0xffff));
3169     }
3170   value=(unsigned int) ((*p++) << 8);
3171   value|=(unsigned int) (*p++);
3172   return((unsigned short) (value & 0xffff));
3173 }
3174 \f
3175 /*
3176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3177 %                                                                             %
3178 %                                                                             %
3179 %                                                                             %
3180 +  R e a d B l o b L S B L o n g                                              %
3181 %                                                                             %
3182 %                                                                             %
3183 %                                                                             %
3184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3185 %
3186 %  ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
3187 %  least-significant byte first order.
3188 %
3189 %  The format of the ReadBlobLSBLong method is:
3190 %
3191 %      unsigned int ReadBlobLSBLong(Image *image)
3192 %
3193 %  A description of each parameter follows.
3194 %
3195 %    o image: the image.
3196 %
3197 */
3198 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3199 {
3200   register const unsigned char
3201     *p;
3202
3203   register unsigned int
3204     value;
3205
3206   ssize_t
3207     count;
3208
3209   unsigned char
3210     buffer[4];
3211
3212   assert(image != (Image *) NULL);
3213   assert(image->signature == MagickSignature);
3214   *buffer='\0';
3215   p=ReadBlobStream(image,4,buffer,&count);
3216   if (count != 4)
3217     return(0U);
3218   value=(unsigned int) (*p++);
3219   value|=((unsigned int) (*p++)) << 8;
3220   value|=((unsigned int) (*p++)) << 16;
3221   value|=((unsigned int) (*p++)) << 24;
3222   return(value);
3223 }
3224 \f
3225 /*
3226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3227 %                                                                             %
3228 %                                                                             %
3229 %                                                                             %
3230 +  R e a d B l o b L S B S h o r t                                            %
3231 %                                                                             %
3232 %                                                                             %
3233 %                                                                             %
3234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3235 %
3236 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3237 %  least-significant byte first order.
3238 %
3239 %  The format of the ReadBlobLSBShort method is:
3240 %
3241 %      unsigned short ReadBlobLSBShort(Image *image)
3242 %
3243 %  A description of each parameter follows.
3244 %
3245 %    o image: the image.
3246 %
3247 */
3248 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3249 {
3250   register const unsigned char
3251     *p;
3252
3253   register unsigned int
3254     value;
3255
3256   ssize_t
3257     count;
3258
3259   unsigned char
3260     buffer[2];
3261
3262   assert(image != (Image *) NULL);
3263   assert(image->signature == MagickSignature);
3264   *buffer='\0';
3265   p=ReadBlobStream(image,2,buffer,&count);
3266   if (count != 2)
3267     return((unsigned short) 0U);
3268   value=(unsigned int) (*p++);
3269   value|=((unsigned int) ((*p++)) << 8);
3270   return((unsigned short) (value & 0xffff));
3271 }
3272 \f
3273 /*
3274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3275 %                                                                             %
3276 %                                                                             %
3277 %                                                                             %
3278 +  R e a d B l o b M S B L o n g                                              %
3279 %                                                                             %
3280 %                                                                             %
3281 %                                                                             %
3282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3283 %
3284 %  ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
3285 %  most-significant byte first order.
3286 %
3287 %  The format of the ReadBlobMSBLong method is:
3288 %
3289 %      unsigned int ReadBlobMSBLong(Image *image)
3290 %
3291 %  A description of each parameter follows.
3292 %
3293 %    o image: the image.
3294 %
3295 */
3296 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3297 {
3298   register const unsigned char
3299     *p;
3300
3301   register unsigned int
3302     value;
3303
3304   ssize_t
3305     count;
3306
3307   unsigned char
3308     buffer[4];
3309
3310   assert(image != (Image *) NULL);
3311   assert(image->signature == MagickSignature);
3312   *buffer='\0';
3313   p=ReadBlobStream(image,4,buffer,&count);
3314   if (count != 4)
3315     return(0UL);
3316   value=((unsigned int) (*p++) << 24);
3317   value|=((unsigned int) (*p++) << 16);
3318   value|=((unsigned int) (*p++) << 8);
3319   value|=(unsigned int) (*p++);
3320   return(value);
3321 }
3322 \f
3323 /*
3324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3325 %                                                                             %
3326 %                                                                             %
3327 %                                                                             %
3328 +  R e a d B l o b M S B L o n g L o n g                                      %
3329 %                                                                             %
3330 %                                                                             %
3331 %                                                                             %
3332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3333 %
3334 %  ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
3335 %  most-significant byte first order.
3336 %
3337 %  The format of the ReadBlobMSBLongLong method is:
3338 %
3339 %      unsigned int ReadBlobMSBLongLong(Image *image)
3340 %
3341 %  A description of each parameter follows.
3342 %
3343 %    o image: the image.
3344 %
3345 */
3346 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3347 {
3348   register const unsigned char
3349     *p;
3350
3351   register MagickSizeType
3352     value;
3353
3354   ssize_t
3355     count;
3356
3357   unsigned char
3358     buffer[8];
3359
3360   assert(image != (Image *) NULL);
3361   assert(image->signature == MagickSignature);
3362   *buffer='\0';
3363   p=ReadBlobStream(image,8,buffer,&count);
3364   if (count != 8)
3365     return(MagickULLConstant(0));
3366   value=((MagickSizeType) (*p++)) << 56;
3367   value|=((MagickSizeType) (*p++)) << 48;
3368   value|=((MagickSizeType) (*p++)) << 40;
3369   value|=((MagickSizeType) (*p++)) << 32;
3370   value|=((MagickSizeType) (*p++)) << 24;
3371   value|=((MagickSizeType) (*p++)) << 16;
3372   value|=((MagickSizeType) (*p++)) << 8;
3373   value|=((MagickSizeType) (*p++));
3374   return(value & MagickULLConstant(0xffffffffffffffff));
3375 }
3376 \f
3377 /*
3378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3379 %                                                                             %
3380 %                                                                             %
3381 %                                                                             %
3382 +  R e a d B l o b M S B S h o r t                                            %
3383 %                                                                             %
3384 %                                                                             %
3385 %                                                                             %
3386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3387 %
3388 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3389 %  most-significant byte first order.
3390 %
3391 %  The format of the ReadBlobMSBShort method is:
3392 %
3393 %      unsigned short ReadBlobMSBShort(Image *image)
3394 %
3395 %  A description of each parameter follows.
3396 %
3397 %    o image: the image.
3398 %
3399 */
3400 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3401 {
3402   register const unsigned char
3403     *p;
3404
3405   register unsigned int
3406     value;
3407
3408   ssize_t
3409     count;
3410
3411   unsigned char
3412     buffer[2];
3413
3414   assert(image != (Image *) NULL);
3415   assert(image->signature == MagickSignature);
3416   *buffer='\0';
3417   p=ReadBlobStream(image,2,buffer,&count);
3418   if (count != 2)
3419     return((unsigned short) 0U);
3420   value=(unsigned int) ((*p++) << 8);
3421   value|=(unsigned int) (*p++);
3422   return((unsigned short) (value & 0xffff));
3423 }
3424 \f
3425 /*
3426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3427 %                                                                             %
3428 %                                                                             %
3429 %                                                                             %
3430 +   R e a d B l o b S t r i n g                                               %
3431 %                                                                             %
3432 %                                                                             %
3433 %                                                                             %
3434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3435 %
3436 %  ReadBlobString() reads characters from a blob or file until a newline
3437 %  character is read or an end-of-file condition is encountered.
3438 %
3439 %  The format of the ReadBlobString method is:
3440 %
3441 %      char *ReadBlobString(Image *image,char *string)
3442 %
3443 %  A description of each parameter follows:
3444 %
3445 %    o image: the image.
3446 %
3447 %    o string: the address of a character buffer.
3448 %
3449 */
3450 MagickExport char *ReadBlobString(Image *image,char *string)
3451 {
3452   register const unsigned char
3453     *p;
3454
3455   register ssize_t
3456     i;
3457
3458   ssize_t
3459     count;
3460
3461   unsigned char
3462     buffer[1];
3463
3464   assert(image != (Image *) NULL);
3465   assert(image->signature == MagickSignature);
3466   for (i=0; i < (MaxTextExtent-1L); i++)
3467   {
3468     p=ReadBlobStream(image,1,buffer,&count);
3469     if (count != 1)
3470       {
3471         if (i == 0)
3472           return((char *) NULL);
3473         break;
3474       }
3475     string[i]=(char) (*p);
3476     if ((string[i] == '\r') || (string[i] == '\n'))
3477       break;
3478   }
3479   if (string[i] == '\r')
3480     (void) ReadBlobStream(image,1,buffer,&count);
3481   string[i]='\0';
3482   return(string);
3483 }
3484 \f
3485 /*
3486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3487 %                                                                             %
3488 %                                                                             %
3489 %                                                                             %
3490 +   R e f e r e n c e B l o b                                                 %
3491 %                                                                             %
3492 %                                                                             %
3493 %                                                                             %
3494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3495 %
3496 %  ReferenceBlob() increments the reference count associated with the pixel
3497 %  blob returning a pointer to the blob.
3498 %
3499 %  The format of the ReferenceBlob method is:
3500 %
3501 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
3502 %
3503 %  A description of each parameter follows:
3504 %
3505 %    o blob_info: the blob_info.
3506 %
3507 */
3508 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3509 {
3510   assert(blob != (BlobInfo *) NULL);
3511   assert(blob->signature == MagickSignature);
3512   if (blob->debug != MagickFalse)
3513     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3514   LockSemaphoreInfo(blob->semaphore);
3515   blob->reference_count++;
3516   UnlockSemaphoreInfo(blob->semaphore);
3517   return(blob);
3518 }
3519 \f
3520 /*
3521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3522 %                                                                             %
3523 %                                                                             %
3524 %                                                                             %
3525 +  S e e k B l o b                                                            %
3526 %                                                                             %
3527 %                                                                             %
3528 %                                                                             %
3529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3530 %
3531 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
3532 %  and returns the resulting offset.
3533 %
3534 %  The format of the SeekBlob method is:
3535 %
3536 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3537 %        const int whence)
3538 %
3539 %  A description of each parameter follows:
3540 %
3541 %    o image: the image.
3542 %
3543 %    o offset:  Specifies an integer representing the offset in bytes.
3544 %
3545 %    o whence:  Specifies an integer representing how the offset is
3546 %      treated relative to the beginning of the blob as follows:
3547 %
3548 %        SEEK_SET  Set position equal to offset bytes.
3549 %        SEEK_CUR  Set position to current location plus offset.
3550 %        SEEK_END  Set position to EOF plus offset.
3551 %
3552 */
3553 MagickExport MagickOffsetType SeekBlob(Image *image,
3554   const MagickOffsetType offset,const int whence)
3555 {
3556   assert(image != (Image *) NULL);
3557   assert(image->signature == MagickSignature);
3558   if (image->debug != MagickFalse)
3559     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3560   assert(image->blob != (BlobInfo *) NULL);
3561   assert(image->blob->type != UndefinedStream);
3562   switch (image->blob->type)
3563   {
3564     case UndefinedStream:
3565       break;
3566     case StandardStream:
3567       return(-1);
3568     case FileStream:
3569     {
3570       if (fseek(image->blob->file_info.file,offset,whence) < 0)
3571         return(-1);
3572       image->blob->offset=TellBlob(image);
3573       break;
3574     }
3575     case PipeStream:
3576     case ZipStream:
3577     {
3578 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3579       if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
3580         return(-1);
3581 #endif
3582       image->blob->offset=TellBlob(image);
3583       break;
3584     }
3585     case BZipStream:
3586       return(-1);
3587     case FifoStream:
3588       return(-1);
3589     case BlobStream:
3590     {
3591       switch (whence)
3592       {
3593         case SEEK_SET:
3594         default:
3595         {
3596           if (offset < 0)
3597             return(-1);
3598           image->blob->offset=offset;
3599           break;
3600         }
3601         case SEEK_CUR:
3602         {
3603           if ((image->blob->offset+offset) < 0)
3604             return(-1);
3605           image->blob->offset+=offset;
3606           break;
3607         }
3608         case SEEK_END:
3609         {
3610           if (((MagickOffsetType) image->blob->length+offset) < 0)
3611             return(-1);
3612           image->blob->offset=image->blob->length+offset;
3613           break;
3614         }
3615       }
3616       if (image->blob->offset <= (MagickOffsetType)
3617           ((off_t) image->blob->length))
3618         image->blob->eof=MagickFalse;
3619       else
3620         if (image->blob->mapped != MagickFalse)
3621           return(-1);
3622         else
3623           {
3624             image->blob->extent=(size_t) (image->blob->offset+
3625               image->blob->quantum);
3626             image->blob->data=(unsigned char *) ResizeQuantumMemory(
3627               image->blob->data,image->blob->extent+1,
3628               sizeof(*image->blob->data));
3629             (void) SyncBlob(image);
3630             if (image->blob->data == (unsigned char *) NULL)
3631               {
3632                 (void) DetachBlob(image->blob);
3633                 return(-1);
3634               }
3635           }
3636       break;
3637     }
3638   }
3639   return(image->blob->offset);
3640 }
3641 \f
3642 /*
3643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3644 %                                                                             %
3645 %                                                                             %
3646 %                                                                             %
3647 +   S e t B l o b E x e m p t                                                 %
3648 %                                                                             %
3649 %                                                                             %
3650 %                                                                             %
3651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652 %
3653 %  SetBlobExempt() sets the blob exempt status.
3654 %
3655 %  The format of the SetBlobExempt method is:
3656 %
3657 %      MagickBooleanType SetBlobExempt(const Image *image,
3658 %        const MagickBooleanType exempt)
3659 %
3660 %  A description of each parameter follows:
3661 %
3662 %    o image: the image.
3663 %
3664 %    o exempt: Set to true if this blob is exempt from being closed.
3665 %
3666 */
3667 MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3668 {
3669   assert(image != (const Image *) NULL);
3670   assert(image->signature == MagickSignature);
3671   if (image->debug != MagickFalse)
3672     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3673   image->blob->exempt=exempt;
3674 }
3675 \f
3676 /*
3677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3678 %                                                                             %
3679 %                                                                             %
3680 %                                                                             %
3681 +  S e t B l o b E x t e n t                                                  %
3682 %                                                                             %
3683 %                                                                             %
3684 %                                                                             %
3685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3686 %
3687 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
3688 %  method is successful, subsequent writes to bytes in the specified range are
3689 %  guaranteed not to fail.
3690 %
3691 %  The format of the SetBlobExtent method is:
3692 %
3693 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3694 %
3695 %  A description of each parameter follows:
3696 %
3697 %    o image: the image.
3698 %
3699 %    o extent:  the blob maximum extent.
3700 %
3701 */
3702 MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
3703   const MagickSizeType extent)
3704 {
3705   assert(image != (Image *) NULL);
3706   assert(image->signature == MagickSignature);
3707   if (image->debug != MagickFalse)
3708     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3709   assert(image->blob != (BlobInfo *) NULL);
3710   assert(image->blob->type != UndefinedStream);
3711   switch (image->blob->type)
3712   {
3713     case UndefinedStream:
3714       break;
3715     case StandardStream:
3716       return(MagickFalse);
3717     case FileStream:
3718     {
3719       if (extent != (MagickSizeType) ((off_t) extent))
3720         return(MagickFalse);
3721 #if !defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3722         return(MagickFalse);
3723 #else
3724       {
3725         int
3726           status;
3727
3728         MagickOffsetType
3729           offset;
3730
3731         offset=TellBlob(image);
3732         status=posix_fallocate(fileno(image->blob->file_info.file),
3733           (off_t) offset,(off_t) (extent-offset));
3734         if (status != 0)
3735           return(MagickFalse);
3736       }
3737 #endif
3738       break;
3739     }
3740     case PipeStream:
3741     case ZipStream:
3742       return(MagickFalse);
3743     case BZipStream:
3744       return(MagickFalse);
3745     case FifoStream:
3746       return(MagickFalse);
3747     case BlobStream:
3748     {
3749       if (image->blob->mapped != MagickFalse)
3750         {
3751           if (image->blob->file_info.file == (FILE *) NULL)
3752             return(MagickFalse);
3753           (void) UnmapBlob(image->blob->data,image->blob->length);
3754 #if !defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3755           return(MagickFalse);
3756 #else
3757           {
3758             int
3759               status;
3760
3761             MagickOffsetType
3762               offset;
3763
3764             offset=TellBlob(image);
3765             status=posix_fallocate(fileno(image->blob->file_info.file),
3766               (off_t) offset,(off_t) (extent-offset));
3767             if (status != 0)
3768               return(MagickFalse);
3769           }
3770           image->blob->data=(unsigned char*) MapBlob(fileno(
3771             image->blob->file_info.file),WriteMode,0,(size_t) extent);
3772           image->blob->extent=(size_t) extent;
3773           image->blob->length=(size_t) extent;
3774           (void) SyncBlob(image);
3775           break;
3776 #endif
3777         }
3778       if (extent != (MagickSizeType) ((size_t) extent))
3779         return(MagickFalse);
3780       image->blob->extent=(size_t) extent;
3781       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3782         image->blob->extent+1,sizeof(*image->blob->data));
3783       (void) SyncBlob(image);
3784       if (image->blob->data == (unsigned char *) NULL)
3785         {
3786           (void) DetachBlob(image->blob);
3787           return(MagickFalse);
3788         }
3789       break;
3790     }
3791   }
3792   return(MagickTrue);
3793 }
3794 \f
3795 /*
3796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3797 %                                                                             %
3798 %                                                                             %
3799 %                                                                             %
3800 +  S y n c B l o b                                                            %
3801 %                                                                             %
3802 %                                                                             %
3803 %                                                                             %
3804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3805 %
3806 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
3807 %  attributes if it is an blob.
3808 %
3809 %  The format of the SyncBlob method is:
3810 %
3811 %      int SyncBlob(Image *image)
3812 %
3813 %  A description of each parameter follows:
3814 %
3815 %    o image: the image.
3816 %
3817 */
3818 static int SyncBlob(Image *image)
3819 {
3820   int
3821     status;
3822
3823   assert(image != (Image *) NULL);
3824   assert(image->signature == MagickSignature);
3825   if (image->debug != MagickFalse)
3826     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3827   assert(image->blob != (BlobInfo *) NULL);
3828   assert(image->blob->type != UndefinedStream);
3829   status=0;
3830   switch (image->blob->type)
3831   {
3832     case UndefinedStream:
3833     case StandardStream:
3834       break;
3835     case FileStream:
3836     case PipeStream:
3837     {
3838       status=fflush(image->blob->file_info.file);
3839       break;
3840     }
3841     case ZipStream:
3842     {
3843 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3844       status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
3845 #endif
3846       break;
3847     }
3848     case BZipStream:
3849     {
3850 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3851       status=BZ2_bzflush(image->blob->file_info.bzfile);
3852 #endif
3853       break;
3854     }
3855     case FifoStream:
3856       break;
3857     case BlobStream:
3858     {
3859 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3860       if (image->blob->mapped != MagickFalse)
3861         status=msync(image->blob->data,image->blob->length,MS_SYNC);
3862 #endif
3863       break;
3864     }
3865   }
3866   return(status);
3867 }
3868 \f
3869 /*
3870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3871 %                                                                             %
3872 %                                                                             %
3873 %                                                                             %
3874 +  T e l l B l o b                                                            %
3875 %                                                                             %
3876 %                                                                             %
3877 %                                                                             %
3878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3879 %
3880 %  TellBlob() obtains the current value of the blob or file position.
3881 %
3882 %  The format of the TellBlob method is:
3883 %
3884 %      MagickOffsetType TellBlob(const Image *image)
3885 %
3886 %  A description of each parameter follows:
3887 %
3888 %    o image: the image.
3889 %
3890 */
3891 MagickExport MagickOffsetType TellBlob(const Image *image)
3892 {
3893   MagickOffsetType
3894     offset;
3895
3896   assert(image != (Image *) NULL);
3897   assert(image->signature == MagickSignature);
3898   if (image->debug != MagickFalse)
3899     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3900   assert(image->blob != (BlobInfo *) NULL);
3901   assert(image->blob->type != UndefinedStream);
3902   offset=(-1);
3903   switch (image->blob->type)
3904   {
3905     case UndefinedStream:
3906     case StandardStream:
3907       break;
3908     case FileStream:
3909     {
3910       offset=ftell(image->blob->file_info.file);
3911       break;
3912     }
3913     case PipeStream:
3914       break;
3915     case ZipStream:
3916     {
3917 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3918       offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
3919 #endif
3920       break;
3921     }
3922     case BZipStream:
3923       break;
3924     case FifoStream:
3925       break;
3926     case BlobStream:
3927     {
3928       offset=image->blob->offset;
3929       break;
3930     }
3931   }
3932   return(offset);
3933 }
3934 \f
3935 /*
3936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3937 %                                                                             %
3938 %                                                                             %
3939 %                                                                             %
3940 +  U n m a p B l o b                                                          %
3941 %                                                                             %
3942 %                                                                             %
3943 %                                                                             %
3944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3945 %
3946 %  UnmapBlob() deallocates the binary large object previously allocated with
3947 %  the MapBlob method.
3948 %
3949 %  The format of the UnmapBlob method is:
3950 %
3951 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
3952 %
3953 %  A description of each parameter follows:
3954 %
3955 %    o map: the address  of the binary large object.
3956 %
3957 %    o length: the length of the binary large object.
3958 %
3959 */
3960 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3961 {
3962 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3963   int
3964     status;
3965
3966   status=munmap(map,length);
3967   return(status == -1 ? MagickFalse : MagickTrue);
3968 #else
3969   (void) map;
3970   (void) length;
3971   return(MagickFalse);
3972 #endif
3973 }
3974 \f
3975 /*
3976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3977 %                                                                             %
3978 %                                                                             %
3979 %                                                                             %
3980 +  W r i t e B l o b                                                          %
3981 %                                                                             %
3982 %                                                                             %
3983 %                                                                             %
3984 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3985 %
3986 %  WriteBlob() writes data to a blob or image file.  It returns the number of
3987 %  bytes written.
3988 %
3989 %  The format of the WriteBlob method is:
3990 %
3991 %      ssize_t WriteBlob(Image *image,const size_t length,
3992 %        const unsigned char *data)
3993 %
3994 %  A description of each parameter follows:
3995 %
3996 %    o image: the image.
3997 %
3998 %    o length:  Specifies an integer representing the number of bytes to
3999 %      write to the file.
4000 %
4001 %    o data:  The address of the data to write to the blob or file.
4002 %
4003 */
4004 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4005   const unsigned char *data)
4006 {
4007   int
4008     c;
4009
4010   register const unsigned char
4011     *p;
4012
4013   ssize_t
4014     count;
4015
4016   assert(image != (Image *) NULL);
4017   assert(image->signature == MagickSignature);
4018   assert(data != (const unsigned char *) NULL);
4019   assert(image->blob != (BlobInfo *) NULL);
4020   assert(image->blob->type != UndefinedStream);
4021   if (length == 0)
4022     return(0);
4023   count=0;
4024   p=data;
4025   switch (image->blob->type)
4026   {
4027     case UndefinedStream:
4028       break;
4029     case StandardStream:
4030     {
4031       count=(ssize_t) write(fileno(image->blob->file_info.file),data,length);
4032       break;
4033     }
4034     case FileStream:
4035     case PipeStream:
4036     {
4037       switch (length)
4038       {
4039         default:
4040         {
4041           count=(ssize_t) fwrite((const char *) data,1,length,
4042             image->blob->file_info.file);
4043           break;
4044         }
4045         case 2:
4046         {
4047           c=putc((int) *p++,image->blob->file_info.file);
4048           if (c == EOF)
4049             break;
4050           count++;
4051         }
4052         case 1:
4053         {
4054           c=putc((int) *p++,image->blob->file_info.file);
4055           if (c == EOF)
4056             break;
4057           count++;
4058         }
4059         case 0:
4060           break;
4061       }
4062       break;
4063     }
4064     case ZipStream:
4065     {
4066 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4067       switch (length)
4068       {
4069         default:
4070         {
4071           count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
4072             (unsigned int) length);
4073           break;
4074         }
4075         case 2:
4076         {
4077           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4078           if (c == EOF)
4079             break;
4080           count++;
4081         }
4082         case 1:
4083         {
4084           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4085           if (c == EOF)
4086             break;
4087           count++;
4088         }
4089         case 0:
4090           break;
4091       }
4092 #endif
4093       break;
4094     }
4095     case BZipStream:
4096     {
4097 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4098       count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
4099         (int) length);
4100 #endif
4101       break;
4102     }
4103     case FifoStream:
4104     {
4105       count=(ssize_t) image->blob->stream(image,data,length);
4106       break;
4107     }
4108     case BlobStream:
4109     {
4110       register unsigned char
4111         *q;
4112
4113       if ((image->blob->offset+(MagickOffsetType) length) >=
4114           (MagickOffsetType) image->blob->extent)
4115         {
4116           if (image->blob->mapped != MagickFalse)
4117             return(0);
4118           image->blob->quantum<<=1;
4119           image->blob->extent+=length+image->blob->quantum;
4120           image->blob->data=(unsigned char *) ResizeQuantumMemory(
4121             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4122           (void) SyncBlob(image);
4123           if (image->blob->data == (unsigned char *) NULL)
4124             {
4125               (void) DetachBlob(image->blob);
4126               return(0);
4127             }
4128         }
4129       q=image->blob->data+image->blob->offset;
4130       (void) memcpy(q,p,length);
4131       image->blob->offset+=length;
4132       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4133         image->blob->length=(size_t) image->blob->offset;
4134       count=(ssize_t) length;
4135     }
4136   }
4137   return(count);
4138 }
4139 \f
4140 /*
4141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4142 %                                                                             %
4143 %                                                                             %
4144 %                                                                             %
4145 +  W r i t e B l o b B y t e                                                  %
4146 %                                                                             %
4147 %                                                                             %
4148 %                                                                             %
4149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4150 %
4151 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
4152 %  written (either 0 or 1);
4153 %
4154 %  The format of the WriteBlobByte method is:
4155 %
4156 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
4157 %
4158 %  A description of each parameter follows.
4159 %
4160 %    o image: the image.
4161 %
4162 %    o value: Specifies the value to write.
4163 %
4164 */
4165 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4166 {
4167   assert(image != (Image *) NULL);
4168   assert(image->signature == MagickSignature);
4169   return(WriteBlobStream(image,1,&value));
4170 }
4171 \f
4172 /*
4173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4174 %                                                                             %
4175 %                                                                             %
4176 %                                                                             %
4177 +  W r i t e B l o b F l o a t                                                %
4178 %                                                                             %
4179 %                                                                             %
4180 %                                                                             %
4181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4182 %
4183 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4184 %  specified by the endian member of the image structure.
4185 %
4186 %  The format of the WriteBlobFloat method is:
4187 %
4188 %      ssize_t WriteBlobFloat(Image *image,const float value)
4189 %
4190 %  A description of each parameter follows.
4191 %
4192 %    o image: the image.
4193 %
4194 %    o value: Specifies the value to write.
4195 %
4196 */
4197 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4198 {
4199   union
4200   {
4201     unsigned int
4202       unsigned_value;
4203
4204     float
4205       float_value;
4206   } quantum;
4207
4208   quantum.unsigned_value=0U;
4209   quantum.float_value=value;
4210   return(WriteBlobLong(image,quantum.unsigned_value));
4211 }
4212 \f
4213 /*
4214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4215 %                                                                             %
4216 %                                                                             %
4217 %                                                                             %
4218 +  W r i t e B l o b L o n g                                                  %
4219 %                                                                             %
4220 %                                                                             %
4221 %                                                                             %
4222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4223 %
4224 %  WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
4225 %  specified by the endian member of the image structure.
4226 %
4227 %  The format of the WriteBlobLong method is:
4228 %
4229 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
4230 %
4231 %  A description of each parameter follows.
4232 %
4233 %    o image: the image.
4234 %
4235 %    o value: Specifies the value to write.
4236 %
4237 */
4238 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4239 {
4240   unsigned char
4241     buffer[4];
4242
4243   assert(image != (Image *) NULL);
4244   assert(image->signature == MagickSignature);
4245   if (image->endian == LSBEndian)
4246     {
4247       buffer[0]=(unsigned char) value;
4248       buffer[1]=(unsigned char) (value >> 8);
4249       buffer[2]=(unsigned char) (value >> 16);
4250       buffer[3]=(unsigned char) (value >> 24);
4251       return(WriteBlobStream(image,4,buffer));
4252     }
4253   buffer[0]=(unsigned char) (value >> 24);
4254   buffer[1]=(unsigned char) (value >> 16);
4255   buffer[2]=(unsigned char) (value >> 8);
4256   buffer[3]=(unsigned char) value;
4257   return(WriteBlobStream(image,4,buffer));
4258 }
4259 \f
4260 /*
4261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4262 %                                                                             %
4263 %                                                                             %
4264 %                                                                             %
4265 +   W r i t e B l o b S h o r t                                               %
4266 %                                                                             %
4267 %                                                                             %
4268 %                                                                             %
4269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4270 %
4271 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
4272 %  byte-order specified by the endian member of the image structure.
4273 %
4274 %  The format of the WriteBlobShort method is:
4275 %
4276 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
4277 %
4278 %  A description of each parameter follows.
4279 %
4280 %    o image: the image.
4281 %
4282 %    o value:  Specifies the value to write.
4283 %
4284 */
4285 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4286 {
4287   unsigned char
4288     buffer[2];
4289
4290   assert(image != (Image *) NULL);
4291   assert(image->signature == MagickSignature);
4292   if (image->endian == LSBEndian)
4293     {
4294       buffer[0]=(unsigned char) value;
4295       buffer[1]=(unsigned char) (value >> 8);
4296       return(WriteBlobStream(image,2,buffer));
4297     }
4298   buffer[0]=(unsigned char) (value >> 8);
4299   buffer[1]=(unsigned char) value;
4300   return(WriteBlobStream(image,2,buffer));
4301 }
4302 \f
4303 /*
4304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4305 %                                                                             %
4306 %                                                                             %
4307 %                                                                             %
4308 +  W r i t e B l o b L S B L o n g                                            %
4309 %                                                                             %
4310 %                                                                             %
4311 %                                                                             %
4312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4313 %
4314 %  WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
4315 %  least-significant byte first order.
4316 %
4317 %  The format of the WriteBlobLSBLong method is:
4318 %
4319 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4320 %
4321 %  A description of each parameter follows.
4322 %
4323 %    o image: the image.
4324 %
4325 %    o value: Specifies the value to write.
4326 %
4327 */
4328 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4329 {
4330   unsigned char
4331     buffer[4];
4332
4333   assert(image != (Image *) NULL);
4334   assert(image->signature == MagickSignature);
4335   buffer[0]=(unsigned char) value;
4336   buffer[1]=(unsigned char) (value >> 8);
4337   buffer[2]=(unsigned char) (value >> 16);
4338   buffer[3]=(unsigned char) (value >> 24);
4339   return(WriteBlobStream(image,4,buffer));
4340 }
4341 \f
4342 /*
4343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4344 %                                                                             %
4345 %                                                                             %
4346 %                                                                             %
4347 +   W r i t e B l o b L S B S h o r t                                         %
4348 %                                                                             %
4349 %                                                                             %
4350 %                                                                             %
4351 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4352 %
4353 %  WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
4354 %  least-significant byte first order.
4355 %
4356 %  The format of the WriteBlobLSBShort method is:
4357 %
4358 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4359 %
4360 %  A description of each parameter follows.
4361 %
4362 %    o image: the image.
4363 %
4364 %    o value:  Specifies the value to write.
4365 %
4366 */
4367 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4368 {
4369   unsigned char
4370     buffer[2];
4371
4372   assert(image != (Image *) NULL);
4373   assert(image->signature == MagickSignature);
4374   buffer[0]=(unsigned char) value;
4375   buffer[1]=(unsigned char) (value >> 8);
4376   return(WriteBlobStream(image,2,buffer));
4377 }
4378 \f
4379 /*
4380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4381 %                                                                             %
4382 %                                                                             %
4383 %                                                                             %
4384 +  W r i t e B l o b M S B L o n g                                            %
4385 %                                                                             %
4386 %                                                                             %
4387 %                                                                             %
4388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4389 %
4390 %  WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
4391 %  most-significant byte first order.
4392 %
4393 %  The format of the WriteBlobMSBLong method is:
4394 %
4395 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4396 %
4397 %  A description of each parameter follows.
4398 %
4399 %    o value:  Specifies the value to write.
4400 %
4401 %    o image: the image.
4402 %
4403 */
4404 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4405 {
4406   unsigned char
4407     buffer[4];
4408
4409   assert(image != (Image *) NULL);
4410   assert(image->signature == MagickSignature);
4411   buffer[0]=(unsigned char) (value >> 24);
4412   buffer[1]=(unsigned char) (value >> 16);
4413   buffer[2]=(unsigned char) (value >> 8);
4414   buffer[3]=(unsigned char) value;
4415   return(WriteBlobStream(image,4,buffer));
4416 }
4417 \f
4418 /*
4419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4420 %                                                                             %
4421 %                                                                             %
4422 %                                                                             %
4423 +  W r i t e B l o b M S B L o n g L o n g                                    %
4424 %                                                                             %
4425 %                                                                             %
4426 %                                                                             %
4427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4428 %
4429 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4430 %  most-significant byte first order.
4431 %
4432 %  The format of the WriteBlobMSBLongLong method is:
4433 %
4434 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4435 %
4436 %  A description of each parameter follows.
4437 %
4438 %    o value:  Specifies the value to write.
4439 %
4440 %    o image: the image.
4441 %
4442 */
4443 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4444   const MagickSizeType value)
4445 {
4446   unsigned char
4447     buffer[8];
4448
4449   assert(image != (Image *) NULL);
4450   assert(image->signature == MagickSignature);
4451   buffer[0]=(unsigned char) (value >> 56);
4452   buffer[1]=(unsigned char) (value >> 48);
4453   buffer[2]=(unsigned char) (value >> 40);
4454   buffer[3]=(unsigned char) (value >> 32);
4455   buffer[4]=(unsigned char) (value >> 24);
4456   buffer[5]=(unsigned char) (value >> 16);
4457   buffer[6]=(unsigned char) (value >> 8);
4458   buffer[7]=(unsigned char) value;
4459   return(WriteBlobStream(image,8,buffer));
4460 }
4461 \f
4462 /*
4463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4464 %                                                                             %
4465 %                                                                             %
4466 %                                                                             %
4467 +  W r i t e B l o b M S B S h o r t                                          %
4468 %                                                                             %
4469 %                                                                             %
4470 %                                                                             %
4471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4472 %
4473 %  WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
4474 %  most-significant byte first order.
4475 %
4476 %  The format of the WriteBlobMSBShort method is:
4477 %
4478 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4479 %
4480 %  A description of each parameter follows.
4481 %
4482 %   o  value:  Specifies the value to write.
4483 %
4484 %   o  file:  Specifies the file to write the data to.
4485 %
4486 */
4487 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4488 {
4489   unsigned char
4490     buffer[2];
4491
4492   assert(image != (Image *) NULL);
4493   assert(image->signature == MagickSignature);
4494   buffer[0]=(unsigned char) (value >> 8);
4495   buffer[1]=(unsigned char) value;
4496   return(WriteBlobStream(image,2,buffer));
4497 }
4498 \f
4499 /*
4500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4501 %                                                                             %
4502 %                                                                             %
4503 %                                                                             %
4504 +  W r i t e B l o b S t r i n g                                              %
4505 %                                                                             %
4506 %                                                                             %
4507 %                                                                             %
4508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4509 %
4510 %  WriteBlobString() write a string to a blob.  It returns the number of
4511 %  characters written.
4512 %
4513 %  The format of the WriteBlobString method is:
4514 %
4515 %      ssize_t WriteBlobString(Image *image,const char *string)
4516 %
4517 %  A description of each parameter follows.
4518 %
4519 %    o image: the image.
4520 %
4521 %    o string: Specifies the string to write.
4522 %
4523 */
4524 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4525 {
4526   assert(image != (Image *) NULL);
4527   assert(image->signature == MagickSignature);
4528   assert(string != (const char *) NULL);
4529   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4530 }