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