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