]> 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 *) AcquireAlignedMemory(1,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[8192];
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,
2461               16384);
2462 #endif
2463             (void) ResetMagickMemory(magick,0,sizeof(magick));
2464             count=fread(magick,1,sizeof(magick),image->blob->file);
2465             (void) rewind(image->blob->file);
2466             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2467                "  read %.20g magic header bytes",(double) count);
2468 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2469             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2470                 ((int) magick[2] == 0x08))
2471               {
2472                 (void) fclose(image->blob->file);
2473                 image->blob->file=(FILE *) gzopen(filename,type);
2474                 if (image->blob->file != (FILE *) NULL)
2475                   image->blob->type=ZipStream;
2476                }
2477 #endif
2478 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2479             if (strncmp((char *) magick,"BZh",3) == 0)
2480               {
2481                 (void) fclose(image->blob->file);
2482                 image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2483                 if (image->blob->file != (FILE *) NULL)
2484                   image->blob->type=BZipStream;
2485               }
2486 #endif
2487             if (image->blob->type == FileStream)
2488               {
2489                 const MagickInfo
2490                   *magick_info;
2491
2492                 ExceptionInfo
2493                   *sans_exception;
2494
2495                 struct stat
2496                   *properties;
2497
2498                 sans_exception=AcquireExceptionInfo();
2499                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2500                 sans_exception=DestroyExceptionInfo(sans_exception);
2501                 properties=(&image->blob->properties);
2502                 if ((magick_info != (const MagickInfo *) NULL) &&
2503                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2504                     (properties->st_size <= MagickMaxBufferExtent))
2505                   {
2506                     size_t
2507                       length;
2508
2509                     void
2510                       *blob;
2511
2512                     length=(size_t) properties->st_size;
2513                     blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
2514                     if (blob != (void *) NULL)
2515                       {
2516                         /*
2517                           Format supports blobs-- use memory-mapped I/O.
2518                         */
2519                         if (image_info->file != (FILE *) NULL)
2520                           image->blob->exempt=MagickFalse;
2521                         else
2522                           {
2523                             (void) fclose(image->blob->file);
2524                             image->blob->file=(FILE *) NULL;
2525                           }
2526                         AttachBlob(image->blob,blob,length);
2527                         image->blob->mapped=MagickTrue;
2528                       }
2529                   }
2530               }
2531           }
2532         }
2533       else
2534 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2535         if ((LocaleCompare(extension,"Z") == 0) ||
2536             (LocaleCompare(extension,"gz") == 0) ||
2537             (LocaleCompare(extension,"wmz") == 0) ||
2538             (LocaleCompare(extension,"svgz") == 0))
2539           {
2540             if (mode == WriteBinaryBlobMode)
2541               type="wb";
2542             image->blob->file=(FILE *) gzopen(filename,type);
2543             if (image->blob->file != (FILE *) NULL)
2544               image->blob->type=ZipStream;
2545           }
2546         else
2547 #endif
2548 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2549           if (LocaleCompare(extension,".bz2") == 0)
2550             {
2551               image->blob->file=(FILE *) BZ2_bzopen(filename,type);
2552               if (image->blob->file != (FILE *) NULL)
2553                 image->blob->type=BZipStream;
2554             }
2555           else
2556 #endif
2557             {
2558               image->blob->file=(FILE *) OpenMagickStream(filename,type);
2559               if (image->blob->file != (FILE *) NULL)
2560                 {
2561                   image->blob->type=FileStream;
2562 #if defined(MAGICKCORE_HAVE_SETVBUF)
2563                   (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,
2564                     16384);
2565 #endif
2566                 }
2567        }
2568   image->blob->status=MagickFalse;
2569   if (image->blob->type != UndefinedStream)
2570     image->blob->size=GetBlobSize(image);
2571   else
2572     {
2573       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2574       return(MagickFalse);
2575     }
2576   return(MagickTrue);
2577 }
2578 \f
2579 /*
2580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2581 %                                                                             %
2582 %                                                                             %
2583 %                                                                             %
2584 +   P i n g B l o b                                                           %
2585 %                                                                             %
2586 %                                                                             %
2587 %                                                                             %
2588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2589 %
2590 %  PingBlob() returns all the attributes of an image or image sequence except
2591 %  for the pixels.  It is much faster and consumes far less memory than
2592 %  BlobToImage().  On failure, a NULL image is returned and exception
2593 %  describes the reason for the failure.
2594 %
2595 %  The format of the PingBlob method is:
2596 %
2597 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
2598 %        const size_t length,ExceptionInfo *exception)
2599 %
2600 %  A description of each parameter follows:
2601 %
2602 %    o image_info: the image info.
2603 %
2604 %    o blob: the address of a character stream in one of the image formats
2605 %      understood by ImageMagick.
2606 %
2607 %    o length: This size_t integer reflects the length in bytes of the blob.
2608 %
2609 %    o exception: return any errors or warnings in this structure.
2610 %
2611 */
2612
2613 #if defined(__cplusplus) || defined(c_plusplus)
2614 extern "C" {
2615 #endif
2616
2617 static size_t PingStream(const Image *magick_unused(image),
2618   const void *magick_unused(pixels),const size_t columns)
2619 {
2620   return(columns);
2621 }
2622
2623 #if defined(__cplusplus) || defined(c_plusplus)
2624 }
2625 #endif
2626
2627 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2628   const size_t length,ExceptionInfo *exception)
2629 {
2630   Image
2631     *image;
2632
2633   ImageInfo
2634     *ping_info;
2635
2636   assert(image_info != (ImageInfo *) NULL);
2637   assert(image_info->signature == MagickSignature);
2638   if (image_info->debug != MagickFalse)
2639     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2640       image_info->filename);
2641   assert(exception != (ExceptionInfo *) NULL);
2642   if ((blob == (const void *) NULL) || (length == 0))
2643     {
2644       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2645         "UnrecognizedImageFormat","`%s'",image_info->magick);
2646       return((Image *) NULL);
2647     }
2648   ping_info=CloneImageInfo(image_info);
2649   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2650   if (ping_info->blob == (const void *) NULL)
2651     {
2652       (void) ThrowMagickException(exception,GetMagickModule(),
2653         ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2654       return((Image *) NULL);
2655     }
2656   (void) memcpy(ping_info->blob,blob,length);
2657   ping_info->length=length;
2658   ping_info->ping=MagickTrue;
2659   image=ReadStream(ping_info,&PingStream,exception);
2660   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2661   ping_info=DestroyImageInfo(ping_info);
2662   return(image);
2663 }
2664 \f
2665 /*
2666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2667 %                                                                             %
2668 %                                                                             %
2669 %                                                                             %
2670 +  R e a d B l o b                                                            %
2671 %                                                                             %
2672 %                                                                             %
2673 %                                                                             %
2674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2675 %
2676 %  ReadBlob() reads data from the blob or image file and returns it.  It
2677 %  returns the number of bytes read.
2678 %
2679 %  The format of the ReadBlob method is:
2680 %
2681 %      ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2682 %
2683 %  A description of each parameter follows:
2684 %
2685 %    o image: the image.
2686 %
2687 %    o length:  Specifies an integer representing the number of bytes to read
2688 %      from the file.
2689 %
2690 %    o data:  Specifies an area to place the information requested from the
2691 %      file.
2692 %
2693 */
2694 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2695   unsigned char *data)
2696 {
2697   int
2698     c;
2699
2700   register unsigned char
2701     *q;
2702
2703   ssize_t
2704     count;
2705
2706   assert(image != (Image *) NULL);
2707   assert(image->signature == MagickSignature);
2708   assert(image->blob != (BlobInfo *) NULL);
2709   assert(image->blob->type != UndefinedStream);
2710   if (length == 0)
2711     return(0);
2712   assert(data != (void *) NULL);
2713   count=0;
2714   q=data;
2715   switch (image->blob->type)
2716   {
2717     case UndefinedStream:
2718       break;
2719     case FileStream:
2720     case StandardStream:
2721     case PipeStream:
2722     {
2723       switch (length)
2724       {
2725         default:
2726         {
2727           count=(ssize_t) fread(q,1,length,image->blob->file);
2728           break;
2729         }
2730         case 2:
2731         {
2732           c=getc(image->blob->file);
2733           if (c == EOF)
2734             break;
2735           *q++=(unsigned char) c;
2736           count++;
2737         }
2738         case 1:
2739         {
2740           c=getc(image->blob->file);
2741           if (c == EOF)
2742             break;
2743           *q++=(unsigned char) c;
2744           count++;
2745         }
2746         case 0:
2747           break;
2748       }
2749       break;
2750     }
2751     case ZipStream:
2752     {
2753 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2754       switch (length)
2755       {
2756         default:
2757         {
2758           count=(ssize_t) gzread(image->blob->file,q,(unsigned int) length);
2759           break;
2760         }
2761         case 2:
2762         {
2763           c=gzgetc(image->blob->file);
2764           if (c == EOF)
2765             break;
2766           *q++=(unsigned char) c;
2767           count++;
2768         }
2769         case 1:
2770         {
2771           c=gzgetc(image->blob->file);
2772           if (c == EOF)
2773             break;
2774           *q++=(unsigned char) c;
2775           count++;
2776         }
2777         case 0:
2778           break;
2779       }
2780 #endif
2781       break;
2782     }
2783     case BZipStream:
2784     {
2785 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2786       count=(ssize_t) BZ2_bzread((BZFILE *) image->blob->file,q,(int) length);
2787 #endif
2788       break;
2789     }
2790     case FifoStream:
2791       break;
2792     case BlobStream:
2793     {
2794       register const unsigned char
2795         *p;
2796
2797       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2798         {
2799           image->blob->eof=MagickTrue;
2800           break;
2801         }
2802       p=image->blob->data+image->blob->offset;
2803       count=(ssize_t) MagickMin(length,(size_t) (image->blob->length-
2804         image->blob->offset));
2805       image->blob->offset+=count;
2806       if (count != (ssize_t) length)
2807         image->blob->eof=MagickTrue;
2808       (void) memcpy(q,p,(size_t) count);
2809       break;
2810     }
2811   }
2812   return(count);
2813 }
2814 \f
2815 /*
2816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2817 %                                                                             %
2818 %                                                                             %
2819 %                                                                             %
2820 +  R e a d B l o b B y t e                                                    %
2821 %                                                                             %
2822 %                                                                             %
2823 %                                                                             %
2824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2825 %
2826 %  ReadBlobByte() reads a single byte from the image file and returns it.
2827 %
2828 %  The format of the ReadBlobByte method is:
2829 %
2830 %      int ReadBlobByte(Image *image)
2831 %
2832 %  A description of each parameter follows.
2833 %
2834 %    o image: the image.
2835 %
2836 */
2837 MagickExport int ReadBlobByte(Image *image)
2838 {
2839   register const unsigned char
2840     *p;
2841
2842   ssize_t
2843     count;
2844
2845   unsigned char
2846     buffer[1];
2847
2848   assert(image != (Image *) NULL);
2849   assert(image->signature == MagickSignature);
2850   p=ReadBlobStream(image,1,buffer,&count);
2851   if (count != 1)
2852     return(EOF);
2853   return((int) (*p));
2854 }
2855 \f
2856 /*
2857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2858 %                                                                             %
2859 %                                                                             %
2860 %                                                                             %
2861 +  R e a d B l o b D o u b l e                                                %
2862 %                                                                             %
2863 %                                                                             %
2864 %                                                                             %
2865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2866 %
2867 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2868 %  specified by the endian member of the image structure.
2869 %
2870 %  The format of the ReadBlobDouble method is:
2871 %
2872 %      double ReadBlobDouble(Image *image)
2873 %
2874 %  A description of each parameter follows.
2875 %
2876 %    o image: the image.
2877 %
2878 */
2879 MagickExport double ReadBlobDouble(Image *image)
2880 {
2881   union
2882   {
2883     MagickSizeType
2884       unsigned_value;
2885
2886     double
2887       double_value;
2888   } quantum;
2889
2890   quantum.double_value=0.0;
2891   quantum.unsigned_value=ReadBlobLongLong(image);
2892   return(quantum.double_value);
2893 }
2894 \f
2895 /*
2896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2897 %                                                                             %
2898 %                                                                             %
2899 %                                                                             %
2900 +  R e a d B l o b F l o a t                                                  %
2901 %                                                                             %
2902 %                                                                             %
2903 %                                                                             %
2904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2905 %
2906 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2907 %  specified by the endian member of the image structure.
2908 %
2909 %  The format of the ReadBlobFloat method is:
2910 %
2911 %      float ReadBlobFloat(Image *image)
2912 %
2913 %  A description of each parameter follows.
2914 %
2915 %    o image: the image.
2916 %
2917 */
2918 MagickExport float ReadBlobFloat(Image *image)
2919 {
2920   union
2921   {
2922     unsigned int
2923       unsigned_value;
2924
2925     float
2926       float_value;
2927   } quantum;
2928
2929   quantum.float_value=0.0;
2930   quantum.unsigned_value=ReadBlobLong(image);
2931   return(quantum.float_value);
2932 }
2933 \f
2934 /*
2935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2936 %                                                                             %
2937 %                                                                             %
2938 %                                                                             %
2939 +  R e a d B l o b L o n g                                                    %
2940 %                                                                             %
2941 %                                                                             %
2942 %                                                                             %
2943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2944 %
2945 %  ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
2946 %  specified by the endian member of the image structure.
2947 %
2948 %  The format of the ReadBlobLong method is:
2949 %
2950 %      unsigned int ReadBlobLong(Image *image)
2951 %
2952 %  A description of each parameter follows.
2953 %
2954 %    o image: the image.
2955 %
2956 */
2957 MagickExport unsigned int ReadBlobLong(Image *image)
2958 {
2959   register const unsigned char
2960     *p;
2961
2962   ssize_t
2963     count;
2964
2965   unsigned char
2966     buffer[4];
2967
2968   unsigned int
2969     value;
2970
2971   assert(image != (Image *) NULL);
2972   assert(image->signature == MagickSignature);
2973   *buffer='\0';
2974   p=ReadBlobStream(image,4,buffer,&count);
2975   if (count != 4)
2976     return(0UL);
2977   if (image->endian == LSBEndian)
2978     {
2979       value=(unsigned int) (*p++);
2980       value|=((unsigned int) (*p++)) << 8;
2981       value|=((unsigned int) (*p++)) << 16;
2982       value|=((unsigned int) (*p++)) << 24;
2983       return(value);
2984     }
2985   value=((unsigned int) (*p++)) << 24;
2986   value|=((unsigned int) (*p++)) << 16;
2987   value|=((unsigned int) (*p++)) << 8;
2988   value|=((unsigned int) (*p++));
2989   return(value);
2990 }
2991 \f
2992 /*
2993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2994 %                                                                             %
2995 %                                                                             %
2996 %                                                                             %
2997 +  R e a d B l o b L o n g L o n g                                            %
2998 %                                                                             %
2999 %                                                                             %
3000 %                                                                             %
3001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3002 %
3003 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3004 %  byte-order specified by the endian member of the image structure.
3005 %
3006 %  The format of the ReadBlobLongLong method is:
3007 %
3008 %      MagickSizeType ReadBlobLongLong(Image *image)
3009 %
3010 %  A description of each parameter follows.
3011 %
3012 %    o image: the image.
3013 %
3014 */
3015 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3016 {
3017   register const unsigned char
3018     *p;
3019
3020   ssize_t
3021     count;
3022
3023   unsigned char
3024     buffer[8];
3025
3026   MagickSizeType
3027     value;
3028
3029   assert(image != (Image *) NULL);
3030   assert(image->signature == MagickSignature);
3031   *buffer='\0';
3032   p=ReadBlobStream(image,8,buffer,&count);
3033   if (count != 8)
3034     return(MagickULLConstant(0));
3035   if (image->endian == LSBEndian)
3036     {
3037       value=(MagickSizeType) (*p++);
3038       value|=((MagickSizeType) (*p++)) << 8;
3039       value|=((MagickSizeType) (*p++)) << 16;
3040       value|=((MagickSizeType) (*p++)) << 24;
3041       value|=((MagickSizeType) (*p++)) << 32;
3042       value|=((MagickSizeType) (*p++)) << 40;
3043       value|=((MagickSizeType) (*p++)) << 48;
3044       value|=((MagickSizeType) (*p++)) << 56;
3045       return(value & MagickULLConstant(0xffffffffffffffff));
3046     }
3047   value=((MagickSizeType) (*p++)) << 56;
3048   value|=((MagickSizeType) (*p++)) << 48;
3049   value|=((MagickSizeType) (*p++)) << 40;
3050   value|=((MagickSizeType) (*p++)) << 32;
3051   value|=((MagickSizeType) (*p++)) << 24;
3052   value|=((MagickSizeType) (*p++)) << 16;
3053   value|=((MagickSizeType) (*p++)) << 8;
3054   value|=((MagickSizeType) (*p++));
3055   return(value & MagickULLConstant(0xffffffffffffffff));
3056 }
3057 \f
3058 /*
3059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3060 %                                                                             %
3061 %                                                                             %
3062 %                                                                             %
3063 +  R e a d B l o b S h o r t                                                  %
3064 %                                                                             %
3065 %                                                                             %
3066 %                                                                             %
3067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3068 %
3069 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3070 %  specified by the endian member of the image structure.
3071 %
3072 %  The format of the ReadBlobShort method is:
3073 %
3074 %      unsigned short ReadBlobShort(Image *image)
3075 %
3076 %  A description of each parameter follows.
3077 %
3078 %    o image: the image.
3079 %
3080 */
3081 MagickExport unsigned short ReadBlobShort(Image *image)
3082 {
3083   register const unsigned char
3084     *p;
3085
3086   register unsigned int
3087     value;
3088
3089   ssize_t
3090     count;
3091
3092   unsigned char
3093     buffer[2];
3094
3095   assert(image != (Image *) NULL);
3096   assert(image->signature == MagickSignature);
3097   *buffer='\0';
3098   p=ReadBlobStream(image,2,buffer,&count);
3099   if (count != 2)
3100     return((unsigned short) 0U);
3101   if (image->endian == LSBEndian)
3102     {
3103       value=(unsigned int) (*p++);
3104       value|=((unsigned int) (*p++)) << 8;
3105       return((unsigned short) (value & 0xffff));
3106     }
3107   value=(unsigned int) ((*p++) << 8);
3108   value|=(unsigned int) (*p++);
3109   return((unsigned short) (value & 0xffff));
3110 }
3111 \f
3112 /*
3113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3114 %                                                                             %
3115 %                                                                             %
3116 %                                                                             %
3117 +  R e a d B l o b L S B L o n g                                              %
3118 %                                                                             %
3119 %                                                                             %
3120 %                                                                             %
3121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3122 %
3123 %  ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
3124 %  least-significant byte first order.
3125 %
3126 %  The format of the ReadBlobLSBLong method is:
3127 %
3128 %      unsigned int ReadBlobLSBLong(Image *image)
3129 %
3130 %  A description of each parameter follows.
3131 %
3132 %    o image: the image.
3133 %
3134 */
3135 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3136 {
3137   register const unsigned char
3138     *p;
3139
3140   register unsigned int
3141     value;
3142
3143   ssize_t
3144     count;
3145
3146   unsigned char
3147     buffer[4];
3148
3149   assert(image != (Image *) NULL);
3150   assert(image->signature == MagickSignature);
3151   *buffer='\0';
3152   p=ReadBlobStream(image,4,buffer,&count);
3153   if (count != 4)
3154     return(0U);
3155   value=(unsigned int) (*p++);
3156   value|=((unsigned int) (*p++)) << 8;
3157   value|=((unsigned int) (*p++)) << 16;
3158   value|=((unsigned int) (*p++)) << 24;
3159   return(value);
3160 }
3161 \f
3162 /*
3163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3164 %                                                                             %
3165 %                                                                             %
3166 %                                                                             %
3167 +  R e a d B l o b L S B S h o r t                                            %
3168 %                                                                             %
3169 %                                                                             %
3170 %                                                                             %
3171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3172 %
3173 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3174 %  least-significant byte first order.
3175 %
3176 %  The format of the ReadBlobLSBShort method is:
3177 %
3178 %      unsigned short ReadBlobLSBShort(Image *image)
3179 %
3180 %  A description of each parameter follows.
3181 %
3182 %    o image: the image.
3183 %
3184 */
3185 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3186 {
3187   register const unsigned char
3188     *p;
3189
3190   register unsigned int
3191     value;
3192
3193   ssize_t
3194     count;
3195
3196   unsigned char
3197     buffer[2];
3198
3199   assert(image != (Image *) NULL);
3200   assert(image->signature == MagickSignature);
3201   *buffer='\0';
3202   p=ReadBlobStream(image,2,buffer,&count);
3203   if (count != 2)
3204     return((unsigned short) 0U);
3205   value=(unsigned int) (*p++);
3206   value|=((unsigned int) ((*p++)) << 8);
3207   return((unsigned short) (value & 0xffff));
3208 }
3209 \f
3210 /*
3211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3212 %                                                                             %
3213 %                                                                             %
3214 %                                                                             %
3215 +  R e a d B l o b M S B L o n g                                              %
3216 %                                                                             %
3217 %                                                                             %
3218 %                                                                             %
3219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3220 %
3221 %  ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
3222 %  most-significant byte first order.
3223 %
3224 %  The format of the ReadBlobMSBLong method is:
3225 %
3226 %      unsigned int ReadBlobMSBLong(Image *image)
3227 %
3228 %  A description of each parameter follows.
3229 %
3230 %    o image: the image.
3231 %
3232 */
3233 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3234 {
3235   register const unsigned char
3236     *p;
3237
3238   register unsigned int
3239     value;
3240
3241   ssize_t
3242     count;
3243
3244   unsigned char
3245     buffer[4];
3246
3247   assert(image != (Image *) NULL);
3248   assert(image->signature == MagickSignature);
3249   *buffer='\0';
3250   p=ReadBlobStream(image,4,buffer,&count);
3251   if (count != 4)
3252     return(0UL);
3253   value=((unsigned int) (*p++) << 24);
3254   value|=((unsigned int) (*p++) << 16);
3255   value|=((unsigned int) (*p++) << 8);
3256   value|=(unsigned int) (*p++);
3257   return(value);
3258 }
3259 \f
3260 /*
3261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3262 %                                                                             %
3263 %                                                                             %
3264 %                                                                             %
3265 +  R e a d B l o b M S B L o n g L o n g                                      %
3266 %                                                                             %
3267 %                                                                             %
3268 %                                                                             %
3269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3270 %
3271 %  ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
3272 %  most-significant byte first order.
3273 %
3274 %  The format of the ReadBlobMSBLongLong method is:
3275 %
3276 %      unsigned int ReadBlobMSBLongLong(Image *image)
3277 %
3278 %  A description of each parameter follows.
3279 %
3280 %    o image: the image.
3281 %
3282 */
3283 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3284 {
3285   register const unsigned char
3286     *p;
3287
3288   register MagickSizeType
3289     value;
3290
3291   ssize_t
3292     count;
3293
3294   unsigned char
3295     buffer[4];
3296
3297   assert(image != (Image *) NULL);
3298   assert(image->signature == MagickSignature);
3299   *buffer='\0';
3300   p=ReadBlobStream(image,8,buffer,&count);
3301   if (count != 8)
3302     return(MagickULLConstant(0));
3303   value=((MagickSizeType) (*p++)) << 56;
3304   value|=((MagickSizeType) (*p++)) << 48;
3305   value|=((MagickSizeType) (*p++)) << 40;
3306   value|=((MagickSizeType) (*p++)) << 32;
3307   value|=((MagickSizeType) (*p++)) << 24;
3308   value|=((MagickSizeType) (*p++)) << 16;
3309   value|=((MagickSizeType) (*p++)) << 8;
3310   value|=((MagickSizeType) (*p++));
3311   return(value & MagickULLConstant(0xffffffffffffffff));
3312 }
3313 \f
3314 /*
3315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3316 %                                                                             %
3317 %                                                                             %
3318 %                                                                             %
3319 +  R e a d B l o b M S B S h o r t                                            %
3320 %                                                                             %
3321 %                                                                             %
3322 %                                                                             %
3323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3324 %
3325 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3326 %  most-significant byte first order.
3327 %
3328 %  The format of the ReadBlobMSBShort method is:
3329 %
3330 %      unsigned short ReadBlobMSBShort(Image *image)
3331 %
3332 %  A description of each parameter follows.
3333 %
3334 %    o image: the image.
3335 %
3336 */
3337 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3338 {
3339   register const unsigned char
3340     *p;
3341
3342   register unsigned int
3343     value;
3344
3345   ssize_t
3346     count;
3347
3348   unsigned char
3349     buffer[2];
3350
3351   assert(image != (Image *) NULL);
3352   assert(image->signature == MagickSignature);
3353   *buffer='\0';
3354   p=ReadBlobStream(image,2,buffer,&count);
3355   if (count != 2)
3356     return((unsigned short) 0U);
3357   value=(unsigned int) ((*p++) << 8);
3358   value|=(unsigned int) (*p++);
3359   return((unsigned short) (value & 0xffff));
3360 }
3361 \f
3362 /*
3363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3364 %                                                                             %
3365 %                                                                             %
3366 %                                                                             %
3367 +   R e a d B l o b S t r i n g                                               %
3368 %                                                                             %
3369 %                                                                             %
3370 %                                                                             %
3371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3372 %
3373 %  ReadBlobString() reads characters from a blob or file until a newline
3374 %  character is read or an end-of-file condition is encountered.
3375 %
3376 %  The format of the ReadBlobString method is:
3377 %
3378 %      char *ReadBlobString(Image *image,char *string)
3379 %
3380 %  A description of each parameter follows:
3381 %
3382 %    o image: the image.
3383 %
3384 %    o string: the address of a character buffer.
3385 %
3386 */
3387 MagickExport char *ReadBlobString(Image *image,char *string)
3388 {
3389   register const unsigned char
3390     *p;
3391
3392   register ssize_t
3393     i;
3394
3395   ssize_t
3396     count;
3397
3398   unsigned char
3399     buffer[1];
3400
3401   assert(image != (Image *) NULL);
3402   assert(image->signature == MagickSignature);
3403   for (i=0; i < (MaxTextExtent-1L); i++)
3404   {
3405     p=ReadBlobStream(image,1,buffer,&count);
3406     if (count != 1)
3407       {
3408         if (i == 0)
3409           return((char *) NULL);
3410         break;
3411       }
3412     string[i]=(char) (*p);
3413     if ((string[i] == '\r') || (string[i] == '\n'))
3414       break;
3415   }
3416   if (string[i] == '\r')
3417     (void) ReadBlobStream(image,1,buffer,&count);
3418   string[i]='\0';
3419   return(string);
3420 }
3421 \f
3422 /*
3423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3424 %                                                                             %
3425 %                                                                             %
3426 %                                                                             %
3427 +   R e f e r e n c e B l o b                                                 %
3428 %                                                                             %
3429 %                                                                             %
3430 %                                                                             %
3431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3432 %
3433 %  ReferenceBlob() increments the reference count associated with the pixel
3434 %  blob returning a pointer to the blob.
3435 %
3436 %  The format of the ReferenceBlob method is:
3437 %
3438 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
3439 %
3440 %  A description of each parameter follows:
3441 %
3442 %    o blob_info: the blob_info.
3443 %
3444 */
3445 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3446 {
3447   assert(blob != (BlobInfo *) NULL);
3448   assert(blob->signature == MagickSignature);
3449   if (blob->debug != MagickFalse)
3450     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3451   LockSemaphoreInfo(blob->semaphore);
3452   blob->reference_count++;
3453   UnlockSemaphoreInfo(blob->semaphore);
3454   return(blob);
3455 }
3456 \f
3457 /*
3458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3459 %                                                                             %
3460 %                                                                             %
3461 %                                                                             %
3462 +  S e e k B l o b                                                            %
3463 %                                                                             %
3464 %                                                                             %
3465 %                                                                             %
3466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3467 %
3468 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
3469 %  and returns the resulting offset.
3470 %
3471 %  The format of the SeekBlob method is:
3472 %
3473 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3474 %        const int whence)
3475 %
3476 %  A description of each parameter follows:
3477 %
3478 %    o image: the image.
3479 %
3480 %    o offset:  Specifies an integer representing the offset in bytes.
3481 %
3482 %    o whence:  Specifies an integer representing how the offset is
3483 %      treated relative to the beginning of the blob as follows:
3484 %
3485 %        SEEK_SET  Set position equal to offset bytes.
3486 %        SEEK_CUR  Set position to current location plus offset.
3487 %        SEEK_END  Set position to EOF plus offset.
3488 %
3489 */
3490 MagickExport MagickOffsetType SeekBlob(Image *image,
3491   const MagickOffsetType offset,const int whence)
3492 {
3493   assert(image != (Image *) NULL);
3494   assert(image->signature == MagickSignature);
3495   if (image->debug != MagickFalse)
3496     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3497   assert(image->blob != (BlobInfo *) NULL);
3498   assert(image->blob->type != UndefinedStream);
3499   switch (image->blob->type)
3500   {
3501     case UndefinedStream:
3502       break;
3503     case FileStream:
3504     {
3505       if (fseek(image->blob->file,(long) offset,whence) < 0)
3506         return(-1);
3507       image->blob->offset=TellBlob(image);
3508       break;
3509     }
3510     case StandardStream:
3511     case PipeStream:
3512     case ZipStream:
3513     {
3514 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3515       if (gzseek(image->blob->file,(off_t) offset,whence) < 0)
3516         return(-1);
3517 #endif
3518       image->blob->offset=TellBlob(image);
3519       break;
3520     }
3521     case BZipStream:
3522       return(-1);
3523     case FifoStream:
3524       return(-1);
3525     case BlobStream:
3526     {
3527       switch (whence)
3528       {
3529         case SEEK_SET:
3530         default:
3531         {
3532           if (offset < 0)
3533             return(-1);
3534           image->blob->offset=offset;
3535           break;
3536         }
3537         case SEEK_CUR:
3538         {
3539           if ((image->blob->offset+offset) < 0)
3540             return(-1);
3541           image->blob->offset+=offset;
3542           break;
3543         }
3544         case SEEK_END:
3545         {
3546           if (((MagickOffsetType) image->blob->length+offset) < 0)
3547             return(-1);
3548           image->blob->offset=image->blob->length+offset;
3549           break;
3550         }
3551       }
3552       if (image->blob->offset <= (MagickOffsetType)
3553           ((off_t) image->blob->length))
3554         image->blob->eof=MagickFalse;
3555       else
3556         if (image->blob->mapped != MagickFalse)
3557           return(-1);
3558         else
3559           {
3560             image->blob->extent=(size_t) (image->blob->offset+
3561               image->blob->quantum);
3562             image->blob->data=(unsigned char *) ResizeQuantumMemory(
3563               image->blob->data,image->blob->extent+1,
3564               sizeof(*image->blob->data));
3565             (void) SyncBlob(image);
3566             if (image->blob->data == (unsigned char *) NULL)
3567               {
3568                 (void) DetachBlob(image->blob);
3569                 return(-1);
3570               }
3571           }
3572       break;
3573     }
3574   }
3575   return(image->blob->offset);
3576 }
3577 \f
3578 /*
3579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3580 %                                                                             %
3581 %                                                                             %
3582 %                                                                             %
3583 +   S e t B l o b E x e m p t                                                 %
3584 %                                                                             %
3585 %                                                                             %
3586 %                                                                             %
3587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3588 %
3589 %  SetBlobExempt() sets the blob exempt status.
3590 %
3591 %  The format of the SetBlobExempt method is:
3592 %
3593 %      MagickBooleanType SetBlobExempt(const Image *image,
3594 %        const MagickBooleanType exempt)
3595 %
3596 %  A description of each parameter follows:
3597 %
3598 %    o image: the image.
3599 %
3600 %    o exempt: Set to true if this blob is exempt from being closed.
3601 %
3602 */
3603 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3604 {
3605   assert(image != (const Image *) NULL);
3606   assert(image->signature == MagickSignature);
3607   if (image->debug != MagickFalse)
3608     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3609   image->blob->exempt=exempt;
3610 }
3611 \f
3612 /*
3613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3614 %                                                                             %
3615 %                                                                             %
3616 %                                                                             %
3617 +  S e t B l o b E x t e n t                                                  %
3618 %                                                                             %
3619 %                                                                             %
3620 %                                                                             %
3621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3622 %
3623 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
3624 %  method is successful, subsequent writes to bytes in the specified range are
3625 %  guaranteed not to fail.
3626 %
3627 %  The format of the SetBlobExtent method is:
3628 %
3629 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3630 %
3631 %  A description of each parameter follows:
3632 %
3633 %    o image: the image.
3634 %
3635 %    o extent:  the blob maximum extent.
3636 %
3637 */
3638 MagickExport MagickBooleanType SetBlobExtent(Image *image,
3639   const MagickSizeType extent)
3640 {
3641   assert(image != (Image *) NULL);
3642   assert(image->signature == MagickSignature);
3643   if (image->debug != MagickFalse)
3644     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3645   assert(image->blob != (BlobInfo *) NULL);
3646   assert(image->blob->type != UndefinedStream);
3647   switch (image->blob->type)
3648   {
3649     case UndefinedStream:
3650       break;
3651     case FileStream:
3652     {
3653       if (extent != (MagickSizeType) ((off_t) extent))
3654         return(MagickFalse);
3655 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
3656         return(MagickFalse);
3657 #else
3658       {
3659         int
3660           status;
3661
3662         MagickOffsetType
3663           offset;
3664
3665         offset=TellBlob(image);
3666         status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3667           (off_t) (extent-offset));
3668         if (status != 0)
3669           return(MagickFalse);
3670       }
3671 #endif
3672       break;
3673     }
3674     case StandardStream:
3675     case PipeStream:
3676     case ZipStream:
3677       return(MagickFalse);
3678     case BZipStream:
3679       return(MagickFalse);
3680     case FifoStream:
3681       return(MagickFalse);
3682     case BlobStream:
3683     {
3684       if (image->blob->mapped != MagickFalse)
3685         {
3686           if (image->blob->file == (FILE *) NULL)
3687             return(MagickFalse);
3688           (void) UnmapBlob(image->blob->data,image->blob->length);
3689 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
3690           return(MagickFalse);
3691 #else
3692           {
3693             int
3694               status;
3695
3696             MagickOffsetType
3697               offset;
3698
3699             offset=TellBlob(image);
3700             status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3701               (off_t) (extent-offset));
3702             if (status != 0)
3703               return(MagickFalse);
3704           }
3705           image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
3706             WriteMode,0,(size_t) extent);
3707           image->blob->extent=(size_t) extent;
3708           image->blob->length=(size_t) extent;
3709           (void) SyncBlob(image);
3710           break;
3711 #endif
3712         }
3713       if (extent != (MagickSizeType) ((size_t) extent))
3714         return(MagickFalse);
3715       image->blob->extent=(size_t) extent;
3716       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3717         image->blob->extent+1,sizeof(*image->blob->data));
3718       (void) SyncBlob(image);
3719       if (image->blob->data == (unsigned char *) NULL)
3720         {
3721           (void) DetachBlob(image->blob);
3722           return(MagickFalse);
3723         }
3724       break;
3725     }
3726   }
3727   return(MagickTrue);
3728 }
3729 \f
3730 /*
3731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3732 %                                                                             %
3733 %                                                                             %
3734 %                                                                             %
3735 +  S y n c B l o b                                                            %
3736 %                                                                             %
3737 %                                                                             %
3738 %                                                                             %
3739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3740 %
3741 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
3742 %  attributes if it is an blob.
3743 %
3744 %  The format of the SyncBlob method is:
3745 %
3746 %      int SyncBlob(Image *image)
3747 %
3748 %  A description of each parameter follows:
3749 %
3750 %    o image: the image.
3751 %
3752 */
3753 static int SyncBlob(Image *image)
3754 {
3755   int
3756     status;
3757
3758   assert(image != (Image *) NULL);
3759   assert(image->signature == MagickSignature);
3760   if (image->debug != MagickFalse)
3761     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3762   assert(image->blob != (BlobInfo *) NULL);
3763   assert(image->blob->type != UndefinedStream);
3764   status=0;
3765   switch (image->blob->type)
3766   {
3767     case UndefinedStream:
3768       break;
3769     case FileStream:
3770     case StandardStream:
3771     case PipeStream:
3772     {
3773       status=fflush(image->blob->file);
3774       break;
3775     }
3776     case ZipStream:
3777     {
3778 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3779       status=gzflush(image->blob->file,Z_SYNC_FLUSH);
3780 #endif
3781       break;
3782     }
3783     case BZipStream:
3784     {
3785 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3786       status=BZ2_bzflush((BZFILE *) image->blob->file);
3787 #endif
3788       break;
3789     }
3790     case FifoStream:
3791       break;
3792     case BlobStream:
3793     {
3794 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3795       if (image->blob->mapped != MagickFalse)
3796         status=msync(image->blob->data,image->blob->length,MS_SYNC);
3797 #endif
3798       break;
3799     }
3800   }
3801   return(status);
3802 }
3803 \f
3804 /*
3805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3806 %                                                                             %
3807 %                                                                             %
3808 %                                                                             %
3809 +  T e l l B l o b                                                            %
3810 %                                                                             %
3811 %                                                                             %
3812 %                                                                             %
3813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3814 %
3815 %  TellBlob() obtains the current value of the blob or file position.
3816 %
3817 %  The format of the TellBlob method is:
3818 %
3819 %      MagickOffsetType TellBlob(const Image *image)
3820 %
3821 %  A description of each parameter follows:
3822 %
3823 %    o image: the image.
3824 %
3825 */
3826 MagickExport MagickOffsetType TellBlob(const Image *image)
3827 {
3828   MagickOffsetType
3829     offset;
3830
3831   assert(image != (Image *) NULL);
3832   assert(image->signature == MagickSignature);
3833   if (image->debug != MagickFalse)
3834     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3835   assert(image->blob != (BlobInfo *) NULL);
3836   assert(image->blob->type != UndefinedStream);
3837   offset=(-1);
3838   switch (image->blob->type)
3839   {
3840     case UndefinedStream:
3841       break;
3842     case FileStream:
3843     {
3844       offset=ftell(image->blob->file);
3845       break;
3846     }
3847     case StandardStream:
3848     case PipeStream:
3849       break;
3850     case ZipStream:
3851     {
3852 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3853       offset=(MagickOffsetType) gztell(image->blob->file);
3854 #endif
3855       break;
3856     }
3857     case BZipStream:
3858       break;
3859     case FifoStream:
3860       break;
3861     case BlobStream:
3862     {
3863       offset=image->blob->offset;
3864       break;
3865     }
3866   }
3867   return(offset);
3868 }
3869 \f
3870 /*
3871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3872 %                                                                             %
3873 %                                                                             %
3874 %                                                                             %
3875 +  U n m a p B l o b                                                          %
3876 %                                                                             %
3877 %                                                                             %
3878 %                                                                             %
3879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3880 %
3881 %  UnmapBlob() deallocates the binary large object previously allocated with
3882 %  the MapBlob method.
3883 %
3884 %  The format of the UnmapBlob method is:
3885 %
3886 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
3887 %
3888 %  A description of each parameter follows:
3889 %
3890 %    o map: the address  of the binary large object.
3891 %
3892 %    o length: the length of the binary large object.
3893 %
3894 */
3895 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3896 {
3897 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3898   int
3899     status;
3900
3901   status=munmap(map,length);
3902   return(status == -1 ? MagickFalse : MagickTrue);
3903 #else
3904   (void) map;
3905   (void) length;
3906   return(MagickFalse);
3907 #endif
3908 }
3909 \f
3910 /*
3911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3912 %                                                                             %
3913 %                                                                             %
3914 %                                                                             %
3915 +  W r i t e B l o b                                                          %
3916 %                                                                             %
3917 %                                                                             %
3918 %                                                                             %
3919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3920 %
3921 %  WriteBlob() writes data to a blob or image file.  It returns the number of
3922 %  bytes written.
3923 %
3924 %  The format of the WriteBlob method is:
3925 %
3926 %      ssize_t WriteBlob(Image *image,const size_t length,
3927 %        const unsigned char *data)
3928 %
3929 %  A description of each parameter follows:
3930 %
3931 %    o image: the image.
3932 %
3933 %    o length:  Specifies an integer representing the number of bytes to
3934 %      write to the file.
3935 %
3936 %    o data:  The address of the data to write to the blob or file.
3937 %
3938 */
3939 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
3940   const unsigned char *data)
3941 {
3942   int
3943     c;
3944
3945   register const unsigned char
3946     *p;
3947
3948   ssize_t
3949     count;
3950
3951   assert(image != (Image *) NULL);
3952   assert(image->signature == MagickSignature);
3953   assert(data != (const unsigned char *) NULL);
3954   assert(image->blob != (BlobInfo *) NULL);
3955   assert(image->blob->type != UndefinedStream);
3956   if (length == 0)
3957     return(0);
3958   count=0;
3959   p=data;
3960   switch (image->blob->type)
3961   {
3962     case UndefinedStream:
3963       break;
3964     case FileStream:
3965     case StandardStream:
3966     case PipeStream:
3967     {
3968       switch (length)
3969       {
3970         default:
3971         {
3972           count=(ssize_t) fwrite((const char *) data,1,length,
3973             image->blob->file);
3974           break;
3975         }
3976         case 2:
3977         {
3978           c=putc((int) *p++,image->blob->file);
3979           if (c == EOF)
3980             break;
3981           count++;
3982         }
3983         case 1:
3984         {
3985           c=putc((int) *p++,image->blob->file);
3986           if (c == EOF)
3987             break;
3988           count++;
3989         }
3990         case 0:
3991           break;
3992       }
3993       break;
3994     }
3995     case ZipStream:
3996     {
3997 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3998       switch (length)
3999       {
4000         default:
4001         {
4002           count=(ssize_t) gzwrite(image->blob->file,(void *) data,
4003             (unsigned int) length);
4004           break;
4005         }
4006         case 2:
4007         {
4008           c=gzputc(image->blob->file,(int) *p++);
4009           if (c == EOF)
4010             break;
4011           count++;
4012         }
4013         case 1:
4014         {
4015           c=gzputc(image->blob->file,(int) *p++);
4016           if (c == EOF)
4017             break;
4018           count++;
4019         }
4020         case 0:
4021           break;
4022       }
4023 #endif
4024       break;
4025     }
4026     case BZipStream:
4027     {
4028 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4029       count=(ssize_t) BZ2_bzwrite((BZFILE *) image->blob->file,(void *) data,
4030         (int) length);
4031 #endif
4032       break;
4033     }
4034     case FifoStream:
4035     {
4036       count=(ssize_t) image->blob->stream(image,data,length);
4037       break;
4038     }
4039     case BlobStream:
4040     {
4041       register unsigned char
4042         *q;
4043
4044       if ((image->blob->offset+(MagickOffsetType) length) >=
4045           (MagickOffsetType) image->blob->extent)
4046         {
4047           if (image->blob->mapped != MagickFalse)
4048             return(0);
4049           image->blob->quantum<<=1;
4050           image->blob->extent+=length+image->blob->quantum;
4051           image->blob->data=(unsigned char *) ResizeQuantumMemory(
4052             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4053           (void) SyncBlob(image);
4054           if (image->blob->data == (unsigned char *) NULL)
4055             {
4056               (void) DetachBlob(image->blob);
4057               return(0);
4058             }
4059         }
4060       q=image->blob->data+image->blob->offset;
4061       (void) memcpy(q,p,length);
4062       image->blob->offset+=length;
4063       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4064         image->blob->length=(size_t) image->blob->offset;
4065       count=(ssize_t) length;
4066     }
4067   }
4068   return(count);
4069 }
4070 \f
4071 /*
4072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4073 %                                                                             %
4074 %                                                                             %
4075 %                                                                             %
4076 +  W r i t e B l o b B y t e                                                  %
4077 %                                                                             %
4078 %                                                                             %
4079 %                                                                             %
4080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4081 %
4082 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
4083 %  written (either 0 or 1);
4084 %
4085 %  The format of the WriteBlobByte method is:
4086 %
4087 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
4088 %
4089 %  A description of each parameter follows.
4090 %
4091 %    o image: the image.
4092 %
4093 %    o value: Specifies the value to write.
4094 %
4095 */
4096 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4097 {
4098   assert(image != (Image *) NULL);
4099   assert(image->signature == MagickSignature);
4100   return(WriteBlobStream(image,1,&value));
4101 }
4102 \f
4103 /*
4104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4105 %                                                                             %
4106 %                                                                             %
4107 %                                                                             %
4108 +  W r i t e B l o b F l o a t                                                %
4109 %                                                                             %
4110 %                                                                             %
4111 %                                                                             %
4112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4113 %
4114 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4115 %  specified by the endian member of the image structure.
4116 %
4117 %  The format of the WriteBlobFloat method is:
4118 %
4119 %      ssize_t WriteBlobFloat(Image *image,const float value)
4120 %
4121 %  A description of each parameter follows.
4122 %
4123 %    o image: the image.
4124 %
4125 %    o value: Specifies the value to write.
4126 %
4127 */
4128 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4129 {
4130   union
4131   {
4132     unsigned int
4133       unsigned_value;
4134
4135     float
4136       float_value;
4137   } quantum;
4138
4139   quantum.unsigned_value=0U;
4140   quantum.float_value=value;
4141   return(WriteBlobLong(image,quantum.unsigned_value));
4142 }
4143 \f
4144 /*
4145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4146 %                                                                             %
4147 %                                                                             %
4148 %                                                                             %
4149 +  W r i t e B l o b L o n g                                                  %
4150 %                                                                             %
4151 %                                                                             %
4152 %                                                                             %
4153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4154 %
4155 %  WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
4156 %  specified by the endian member of the image structure.
4157 %
4158 %  The format of the WriteBlobLong method is:
4159 %
4160 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
4161 %
4162 %  A description of each parameter follows.
4163 %
4164 %    o image: the image.
4165 %
4166 %    o value: Specifies the value to write.
4167 %
4168 */
4169 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4170 {
4171   unsigned char
4172     buffer[4];
4173
4174   assert(image != (Image *) NULL);
4175   assert(image->signature == MagickSignature);
4176   if (image->endian == LSBEndian)
4177     {
4178       buffer[0]=(unsigned char) value;
4179       buffer[1]=(unsigned char) (value >> 8);
4180       buffer[2]=(unsigned char) (value >> 16);
4181       buffer[3]=(unsigned char) (value >> 24);
4182       return(WriteBlobStream(image,4,buffer));
4183     }
4184   buffer[0]=(unsigned char) (value >> 24);
4185   buffer[1]=(unsigned char) (value >> 16);
4186   buffer[2]=(unsigned char) (value >> 8);
4187   buffer[3]=(unsigned char) value;
4188   return(WriteBlobStream(image,4,buffer));
4189 }
4190 \f
4191 /*
4192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4193 %                                                                             %
4194 %                                                                             %
4195 %                                                                             %
4196 +   W r i t e B l o b S h o r t                                               %
4197 %                                                                             %
4198 %                                                                             %
4199 %                                                                             %
4200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4201 %
4202 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
4203 %  byte-order specified by the endian member of the image structure.
4204 %
4205 %  The format of the WriteBlobShort method is:
4206 %
4207 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
4208 %
4209 %  A description of each parameter follows.
4210 %
4211 %    o image: the image.
4212 %
4213 %    o value:  Specifies the value to write.
4214 %
4215 */
4216 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4217 {
4218   unsigned char
4219     buffer[2];
4220
4221   assert(image != (Image *) NULL);
4222   assert(image->signature == MagickSignature);
4223   if (image->endian == LSBEndian)
4224     {
4225       buffer[0]=(unsigned char) value;
4226       buffer[1]=(unsigned char) (value >> 8);
4227       return(WriteBlobStream(image,2,buffer));
4228     }
4229   buffer[0]=(unsigned char) (value >> 8);
4230   buffer[1]=(unsigned char) value;
4231   return(WriteBlobStream(image,2,buffer));
4232 }
4233 \f
4234 /*
4235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4236 %                                                                             %
4237 %                                                                             %
4238 %                                                                             %
4239 +  W r i t e B l o b L S B L o n g                                            %
4240 %                                                                             %
4241 %                                                                             %
4242 %                                                                             %
4243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4244 %
4245 %  WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
4246 %  least-significant byte first order.
4247 %
4248 %  The format of the WriteBlobLSBLong method is:
4249 %
4250 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4251 %
4252 %  A description of each parameter follows.
4253 %
4254 %    o image: the image.
4255 %
4256 %    o value: Specifies the value to write.
4257 %
4258 */
4259 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4260 {
4261   unsigned char
4262     buffer[4];
4263
4264   assert(image != (Image *) NULL);
4265   assert(image->signature == MagickSignature);
4266   buffer[0]=(unsigned char) value;
4267   buffer[1]=(unsigned char) (value >> 8);
4268   buffer[2]=(unsigned char) (value >> 16);
4269   buffer[3]=(unsigned char) (value >> 24);
4270   return(WriteBlobStream(image,4,buffer));
4271 }
4272 \f
4273 /*
4274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4275 %                                                                             %
4276 %                                                                             %
4277 %                                                                             %
4278 +   W r i t e B l o b L S B S h o r t                                         %
4279 %                                                                             %
4280 %                                                                             %
4281 %                                                                             %
4282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4283 %
4284 %  WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
4285 %  least-significant byte first order.
4286 %
4287 %  The format of the WriteBlobLSBShort method is:
4288 %
4289 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4290 %
4291 %  A description of each parameter follows.
4292 %
4293 %    o image: the image.
4294 %
4295 %    o value:  Specifies the value to write.
4296 %
4297 */
4298 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4299 {
4300   unsigned char
4301     buffer[2];
4302
4303   assert(image != (Image *) NULL);
4304   assert(image->signature == MagickSignature);
4305   buffer[0]=(unsigned char) value;
4306   buffer[1]=(unsigned char) (value >> 8);
4307   return(WriteBlobStream(image,2,buffer));
4308 }
4309 \f
4310 /*
4311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4312 %                                                                             %
4313 %                                                                             %
4314 %                                                                             %
4315 +  W r i t e B l o b M S B L o n g                                            %
4316 %                                                                             %
4317 %                                                                             %
4318 %                                                                             %
4319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4320 %
4321 %  WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
4322 %  most-significant byte first order.
4323 %
4324 %  The format of the WriteBlobMSBLong method is:
4325 %
4326 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4327 %
4328 %  A description of each parameter follows.
4329 %
4330 %    o value:  Specifies the value to write.
4331 %
4332 %    o image: the image.
4333 %
4334 */
4335 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4336 {
4337   unsigned char
4338     buffer[4];
4339
4340   assert(image != (Image *) NULL);
4341   assert(image->signature == MagickSignature);
4342   buffer[0]=(unsigned char) (value >> 24);
4343   buffer[1]=(unsigned char) (value >> 16);
4344   buffer[2]=(unsigned char) (value >> 8);
4345   buffer[3]=(unsigned char) value;
4346   return(WriteBlobStream(image,4,buffer));
4347 }
4348 \f
4349 /*
4350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4351 %                                                                             %
4352 %                                                                             %
4353 %                                                                             %
4354 +  W r i t e B l o b M S B L o n g L o n g                                    %
4355 %                                                                             %
4356 %                                                                             %
4357 %                                                                             %
4358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4359 %
4360 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4361 %  most-significant byte first order.
4362 %
4363 %  The format of the WriteBlobMSBLongLong method is:
4364 %
4365 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4366 %
4367 %  A description of each parameter follows.
4368 %
4369 %    o value:  Specifies the value to write.
4370 %
4371 %    o image: the image.
4372 %
4373 */
4374 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4375   const MagickSizeType value)
4376 {
4377   unsigned char
4378     buffer[8];
4379
4380   assert(image != (Image *) NULL);
4381   assert(image->signature == MagickSignature);
4382   buffer[0]=(unsigned char) (value >> 56);
4383   buffer[1]=(unsigned char) (value >> 48);
4384   buffer[2]=(unsigned char) (value >> 40);
4385   buffer[3]=(unsigned char) (value >> 32);
4386   buffer[4]=(unsigned char) (value >> 24);
4387   buffer[5]=(unsigned char) (value >> 16);
4388   buffer[6]=(unsigned char) (value >> 8);
4389   buffer[7]=(unsigned char) value;
4390   return(WriteBlobStream(image,8,buffer));
4391 }
4392 \f
4393 /*
4394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4395 %                                                                             %
4396 %                                                                             %
4397 %                                                                             %
4398 +  W r i t e B l o b M S B S h o r t                                          %
4399 %                                                                             %
4400 %                                                                             %
4401 %                                                                             %
4402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4403 %
4404 %  WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
4405 %  most-significant byte first order.
4406 %
4407 %  The format of the WriteBlobMSBShort method is:
4408 %
4409 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4410 %
4411 %  A description of each parameter follows.
4412 %
4413 %   o  value:  Specifies the value to write.
4414 %
4415 %   o  file:  Specifies the file to write the data to.
4416 %
4417 */
4418 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4419 {
4420   unsigned char
4421     buffer[2];
4422
4423   assert(image != (Image *) NULL);
4424   assert(image->signature == MagickSignature);
4425   buffer[0]=(unsigned char) (value >> 8);
4426   buffer[1]=(unsigned char) value;
4427   return(WriteBlobStream(image,2,buffer));
4428 }
4429 \f
4430 /*
4431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4432 %                                                                             %
4433 %                                                                             %
4434 %                                                                             %
4435 +  W r i t e B l o b S t r i n g                                              %
4436 %                                                                             %
4437 %                                                                             %
4438 %                                                                             %
4439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4440 %
4441 %  WriteBlobString() write a string to a blob.  It returns the number of
4442 %  characters written.
4443 %
4444 %  The format of the WriteBlobString method is:
4445 %
4446 %      ssize_t WriteBlobString(Image *image,const char *string)
4447 %
4448 %  A description of each parameter follows.
4449 %
4450 %    o image: the image.
4451 %
4452 %    o string: Specifies the string to write.
4453 %
4454 */
4455 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4456 {
4457   assert(image != (Image *) NULL);
4458   assert(image->signature == MagickSignature);
4459   assert(string != (const char *) NULL);
4460   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4461 }