]> 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] == '\n') || (string[i] == '\r'))
3332       break;
3333   }
3334   string[i]='\0';
3335   return(string);
3336 }
3337 \f
3338 /*
3339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3340 %                                                                             %
3341 %                                                                             %
3342 %                                                                             %
3343 +   R e f e r e n c e B l o b                                                 %
3344 %                                                                             %
3345 %                                                                             %
3346 %                                                                             %
3347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3348 %
3349 %  ReferenceBlob() increments the reference count associated with the pixel
3350 %  blob returning a pointer to the blob.
3351 %
3352 %  The format of the ReferenceBlob method is:
3353 %
3354 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
3355 %
3356 %  A description of each parameter follows:
3357 %
3358 %    o blob_info: the blob_info.
3359 %
3360 */
3361 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3362 {
3363   assert(blob != (BlobInfo *) NULL);
3364   assert(blob->signature == MagickSignature);
3365   if (blob->debug != MagickFalse)
3366     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3367   LockSemaphoreInfo(blob->semaphore);
3368   blob->reference_count++;
3369   UnlockSemaphoreInfo(blob->semaphore);
3370   return(blob);
3371 }
3372 \f
3373 /*
3374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3375 %                                                                             %
3376 %                                                                             %
3377 %                                                                             %
3378 +  S e e k B l o b                                                            %
3379 %                                                                             %
3380 %                                                                             %
3381 %                                                                             %
3382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3383 %
3384 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
3385 %  and returns the resulting offset.
3386 %
3387 %  The format of the SeekBlob method is:
3388 %
3389 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3390 %        const int whence)
3391 %
3392 %  A description of each parameter follows:
3393 %
3394 %    o image: the image.
3395 %
3396 %    o offset:  Specifies an integer representing the offset in bytes.
3397 %
3398 %    o whence:  Specifies an integer representing how the offset is
3399 %      treated relative to the beginning of the blob as follows:
3400 %
3401 %        SEEK_SET  Set position equal to offset bytes.
3402 %        SEEK_CUR  Set position to current location plus offset.
3403 %        SEEK_END  Set position to EOF plus offset.
3404 %
3405 */
3406 MagickExport MagickOffsetType SeekBlob(Image *image,
3407   const MagickOffsetType offset,const int whence)
3408 {
3409   assert(image != (Image *) NULL);
3410   assert(image->signature == MagickSignature);
3411   if (image->debug != MagickFalse)
3412     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3413   assert(image->blob != (BlobInfo *) NULL);
3414   assert(image->blob->type != UndefinedStream);
3415   switch (image->blob->type)
3416   {
3417     case UndefinedStream:
3418       break;
3419     case FileStream:
3420     {
3421       if (fseek(image->blob->file,(long) offset,whence) < 0)
3422         return(-1);
3423       image->blob->offset=TellBlob(image);
3424       break;
3425     }
3426     case StandardStream:
3427     case PipeStream:
3428     case ZipStream:
3429     {
3430 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3431       if (gzseek(image->blob->file,(off_t) offset,whence) < 0)
3432         return(-1);
3433 #endif
3434       image->blob->offset=TellBlob(image);
3435       break;
3436     }
3437     case BZipStream:
3438       return(-1);
3439     case FifoStream:
3440       return(-1);
3441     case BlobStream:
3442     {
3443       switch (whence)
3444       {
3445         case SEEK_SET:
3446         default:
3447         {
3448           if (offset < 0)
3449             return(-1);
3450           image->blob->offset=offset;
3451           break;
3452         }
3453         case SEEK_CUR:
3454         {
3455           if ((image->blob->offset+offset) < 0)
3456             return(-1);
3457           image->blob->offset+=offset;
3458           break;
3459         }
3460         case SEEK_END:
3461         {
3462           if (((MagickOffsetType) image->blob->length+offset) < 0)
3463             return(-1);
3464           image->blob->offset=image->blob->length+offset;
3465           break;
3466         }
3467       }
3468       if (image->blob->offset <= (MagickOffsetType)
3469           ((off_t) image->blob->length))
3470         image->blob->eof=MagickFalse;
3471       else
3472         if (image->blob->mapped != MagickFalse)
3473           return(-1);
3474         else
3475           {
3476             image->blob->extent=(size_t) (image->blob->offset+
3477               image->blob->quantum);
3478             image->blob->data=(unsigned char *) ResizeQuantumMemory(
3479               image->blob->data,image->blob->extent+1,
3480               sizeof(*image->blob->data));
3481             (void) SyncBlob(image);
3482             if (image->blob->data == (unsigned char *) NULL)
3483               {
3484                 (void) DetachBlob(image->blob);
3485                 return(-1);
3486               }
3487           }
3488       break;
3489     }
3490   }
3491   return(image->blob->offset);
3492 }
3493 \f
3494 /*
3495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3496 %                                                                             %
3497 %                                                                             %
3498 %                                                                             %
3499 +   S e t B l o b E x e m p t                                                 %
3500 %                                                                             %
3501 %                                                                             %
3502 %                                                                             %
3503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3504 %
3505 %  SetBlobExempt() sets the blob exempt status.
3506 %
3507 %  The format of the SetBlobExempt method is:
3508 %
3509 %      MagickBooleanType SetBlobExempt(const Image *image,
3510 %        const MagickBooleanType exempt)
3511 %
3512 %  A description of each parameter follows:
3513 %
3514 %    o image: the image.
3515 %
3516 %    o exempt: Set to true if this blob is exempt from being closed.
3517 %
3518 */
3519 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3520 {
3521   assert(image != (const Image *) NULL);
3522   assert(image->signature == MagickSignature);
3523   if (image->debug != MagickFalse)
3524     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3525   image->blob->exempt=exempt;
3526 }
3527 \f
3528 /*
3529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3530 %                                                                             %
3531 %                                                                             %
3532 %                                                                             %
3533 +  S e t B l o b E x t e n t                                                  %
3534 %                                                                             %
3535 %                                                                             %
3536 %                                                                             %
3537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3538 %
3539 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
3540 %  method is successful, subsequent writes to bytes in the specified range are
3541 %  guaranteed not to fail.
3542 %
3543 %  The format of the SetBlobExtent method is:
3544 %
3545 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3546 %
3547 %  A description of each parameter follows:
3548 %
3549 %    o image: the image.
3550 %
3551 %    o extent:  the blob maximum extent.
3552 %
3553 */
3554 MagickExport MagickBooleanType SetBlobExtent(Image *image,
3555   const MagickSizeType extent)
3556 {
3557   assert(image != (Image *) NULL);
3558   assert(image->signature == MagickSignature);
3559   if (image->debug != MagickFalse)
3560     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3561   assert(image->blob != (BlobInfo *) NULL);
3562   assert(image->blob->type != UndefinedStream);
3563   switch (image->blob->type)
3564   {
3565     case UndefinedStream:
3566       break;
3567     case FileStream:
3568     {
3569       if (extent != (MagickSizeType) ((off_t) extent))
3570         return(MagickFalse);
3571 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
3572         return(MagickFalse);
3573 #else
3574       {
3575         int
3576           status;
3577
3578         MagickOffsetType
3579           offset;
3580
3581         offset=TellBlob(image);
3582         status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3583           (off_t) (extent-offset));
3584         if (status != 0)
3585           return(MagickFalse);
3586       }
3587 #endif
3588       break;
3589     }
3590     case StandardStream:
3591     case PipeStream:
3592     case ZipStream:
3593       return(MagickFalse);
3594     case BZipStream:
3595       return(MagickFalse);
3596     case FifoStream:
3597       return(MagickFalse);
3598     case BlobStream:
3599     {
3600       if (image->blob->mapped != MagickFalse)
3601         {
3602           if (image->blob->file == (FILE *) NULL)
3603             return(MagickFalse);
3604           (void) UnmapBlob(image->blob->data,image->blob->length);
3605 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
3606           return(MagickFalse);
3607 #else
3608           {
3609             int
3610               status;
3611
3612             MagickOffsetType
3613               offset;
3614
3615             offset=TellBlob(image);
3616             status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3617               (off_t) (extent-offset));
3618             if (status != 0)
3619               return(MagickFalse);
3620           }
3621           image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
3622             WriteMode,0,(size_t) extent);
3623           image->blob->extent=(size_t) extent;
3624           image->blob->length=(size_t) extent;
3625           (void) SyncBlob(image);
3626           break;
3627 #endif
3628         }
3629       if (extent != (MagickSizeType) ((size_t) extent))
3630         return(MagickFalse);
3631       image->blob->extent=(size_t) extent;
3632       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3633         image->blob->extent+1,sizeof(*image->blob->data));
3634       (void) SyncBlob(image);
3635       if (image->blob->data == (unsigned char *) NULL)
3636         {
3637           (void) DetachBlob(image->blob);
3638           return(MagickFalse);
3639         }
3640       break;
3641     }
3642   }
3643   return(MagickTrue);
3644 }
3645 \f
3646 /*
3647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3648 %                                                                             %
3649 %                                                                             %
3650 %                                                                             %
3651 +  S y n c B l o b                                                            %
3652 %                                                                             %
3653 %                                                                             %
3654 %                                                                             %
3655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3656 %
3657 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
3658 %  attributes if it is an blob.
3659 %
3660 %  The format of the SyncBlob method is:
3661 %
3662 %      int SyncBlob(Image *image)
3663 %
3664 %  A description of each parameter follows:
3665 %
3666 %    o image: the image.
3667 %
3668 */
3669 static int SyncBlob(Image *image)
3670 {
3671   int
3672     status;
3673
3674   assert(image != (Image *) NULL);
3675   assert(image->signature == MagickSignature);
3676   if (image->debug != MagickFalse)
3677     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3678   assert(image->blob != (BlobInfo *) NULL);
3679   assert(image->blob->type != UndefinedStream);
3680   status=0;
3681   switch (image->blob->type)
3682   {
3683     case UndefinedStream:
3684       break;
3685     case FileStream:
3686     case StandardStream:
3687     case PipeStream:
3688     {
3689       status=fflush(image->blob->file);
3690       break;
3691     }
3692     case ZipStream:
3693     {
3694 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3695       status=gzflush(image->blob->file,Z_SYNC_FLUSH);
3696 #endif
3697       break;
3698     }
3699     case BZipStream:
3700     {
3701 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3702       status=BZ2_bzflush((BZFILE *) image->blob->file);
3703 #endif
3704       break;
3705     }
3706     case FifoStream:
3707       break;
3708     case BlobStream:
3709     {
3710 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3711       if (image->blob->mapped != MagickFalse)
3712         status=msync(image->blob->data,image->blob->length,MS_SYNC);
3713 #endif
3714       break;
3715     }
3716   }
3717   return(status);
3718 }
3719 \f
3720 /*
3721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3722 %                                                                             %
3723 %                                                                             %
3724 %                                                                             %
3725 +  T e l l B l o b                                                            %
3726 %                                                                             %
3727 %                                                                             %
3728 %                                                                             %
3729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3730 %
3731 %  TellBlob() obtains the current value of the blob or file position.
3732 %
3733 %  The format of the TellBlob method is:
3734 %
3735 %      MagickOffsetType TellBlob(const Image *image)
3736 %
3737 %  A description of each parameter follows:
3738 %
3739 %    o image: the image.
3740 %
3741 */
3742 MagickExport MagickOffsetType TellBlob(const Image *image)
3743 {
3744   MagickOffsetType
3745     offset;
3746
3747   assert(image != (Image *) NULL);
3748   assert(image->signature == MagickSignature);
3749   if (image->debug != MagickFalse)
3750     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3751   assert(image->blob != (BlobInfo *) NULL);
3752   assert(image->blob->type != UndefinedStream);
3753   offset=(-1);
3754   switch (image->blob->type)
3755   {
3756     case UndefinedStream:
3757       break;
3758     case FileStream:
3759     {
3760       offset=ftell(image->blob->file);
3761       break;
3762     }
3763     case StandardStream:
3764     case PipeStream:
3765       break;
3766     case ZipStream:
3767     {
3768 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3769       offset=(MagickOffsetType) gztell(image->blob->file);
3770 #endif
3771       break;
3772     }
3773     case BZipStream:
3774       break;
3775     case FifoStream:
3776       break;
3777     case BlobStream:
3778     {
3779       offset=image->blob->offset;
3780       break;
3781     }
3782   }
3783   return(offset);
3784 }
3785 \f
3786 /*
3787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3788 %                                                                             %
3789 %                                                                             %
3790 %                                                                             %
3791 +  U n m a p B l o b                                                          %
3792 %                                                                             %
3793 %                                                                             %
3794 %                                                                             %
3795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3796 %
3797 %  UnmapBlob() deallocates the binary large object previously allocated with
3798 %  the MapBlob method.
3799 %
3800 %  The format of the UnmapBlob method is:
3801 %
3802 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
3803 %
3804 %  A description of each parameter follows:
3805 %
3806 %    o map: the address  of the binary large object.
3807 %
3808 %    o length: the length of the binary large object.
3809 %
3810 */
3811 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3812 {
3813 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3814   int
3815     status;
3816
3817   status=munmap(map,length);
3818   return(status == -1 ? MagickFalse : MagickTrue);
3819 #else
3820   (void) map;
3821   (void) length;
3822   return(MagickFalse);
3823 #endif
3824 }
3825 \f
3826 /*
3827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3828 %                                                                             %
3829 %                                                                             %
3830 %                                                                             %
3831 +  W r i t e B l o b                                                          %
3832 %                                                                             %
3833 %                                                                             %
3834 %                                                                             %
3835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836 %
3837 %  WriteBlob() writes data to a blob or image file.  It returns the number of
3838 %  bytes written.
3839 %
3840 %  The format of the WriteBlob method is:
3841 %
3842 %      ssize_t WriteBlob(Image *image,const size_t length,
3843 %        const unsigned char *data)
3844 %
3845 %  A description of each parameter follows:
3846 %
3847 %    o image: the image.
3848 %
3849 %    o length:  Specifies an integer representing the number of bytes to
3850 %      write to the file.
3851 %
3852 %    o data:  The address of the data to write to the blob or file.
3853 %
3854 */
3855 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
3856   const unsigned char *data)
3857 {
3858   int
3859     c;
3860
3861   register const unsigned char
3862     *p;
3863
3864   ssize_t
3865     count;
3866
3867   assert(image != (Image *) NULL);
3868   assert(image->signature == MagickSignature);
3869   assert(data != (const unsigned char *) NULL);
3870   assert(image->blob != (BlobInfo *) NULL);
3871   assert(image->blob->type != UndefinedStream);
3872   if (length == 0)
3873     return(0);
3874   count=0;
3875   p=data;
3876   switch (image->blob->type)
3877   {
3878     case UndefinedStream:
3879       break;
3880     case FileStream:
3881     case StandardStream:
3882     case PipeStream:
3883     {
3884       switch (length)
3885       {
3886         default:
3887         {
3888           count=(ssize_t) fwrite((const char *) data,1,length,
3889             image->blob->file);
3890           break;
3891         }
3892         case 2:
3893         {
3894           c=putc((int) *p++,image->blob->file);
3895           if (c == EOF)
3896             break;
3897           count++;
3898         }
3899         case 1:
3900         {
3901           c=putc((int) *p++,image->blob->file);
3902           if (c == EOF)
3903             break;
3904           count++;
3905         }
3906         case 0:
3907           break;
3908       }
3909       break;
3910     }
3911     case ZipStream:
3912     {
3913 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3914       switch (length)
3915       {
3916         default:
3917         {
3918           count=(ssize_t) gzwrite(image->blob->file,(void *) data,
3919             (unsigned int) length);
3920           break;
3921         }
3922         case 2:
3923         {
3924           c=gzputc(image->blob->file,(int) *p++);
3925           if (c == EOF)
3926             break;
3927           count++;
3928         }
3929         case 1:
3930         {
3931           c=gzputc(image->blob->file,(int) *p++);
3932           if (c == EOF)
3933             break;
3934           count++;
3935         }
3936         case 0:
3937           break;
3938       }
3939 #endif
3940       break;
3941     }
3942     case BZipStream:
3943     {
3944 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3945       count=(ssize_t) BZ2_bzwrite((BZFILE *) image->blob->file,(void *) data,
3946         (int) length);
3947 #endif
3948       break;
3949     }
3950     case FifoStream:
3951     {
3952       count=(ssize_t) image->blob->stream(image,data,length);
3953       break;
3954     }
3955     case BlobStream:
3956     {
3957       register unsigned char
3958         *q;
3959
3960       if ((image->blob->offset+(MagickOffsetType) length) >=
3961           (MagickOffsetType) image->blob->extent)
3962         {
3963           if (image->blob->mapped != MagickFalse)
3964             return(0);
3965           image->blob->quantum<<=1;
3966           image->blob->extent+=length+image->blob->quantum;
3967           image->blob->data=(unsigned char *) ResizeQuantumMemory(
3968             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
3969           (void) SyncBlob(image);
3970           if (image->blob->data == (unsigned char *) NULL)
3971             {
3972               (void) DetachBlob(image->blob);
3973               return(0);
3974             }
3975         }
3976       q=image->blob->data+image->blob->offset;
3977       (void) CopyMagickMemory(q,p,length);
3978       image->blob->offset+=length;
3979       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3980         image->blob->length=(size_t) image->blob->offset;
3981       count=(ssize_t) length;
3982     }
3983   }
3984   return(count);
3985 }
3986 \f
3987 /*
3988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3989 %                                                                             %
3990 %                                                                             %
3991 %                                                                             %
3992 +  W r i t e B l o b B y t e                                                  %
3993 %                                                                             %
3994 %                                                                             %
3995 %                                                                             %
3996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3997 %
3998 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
3999 %  written (either 0 or 1);
4000 %
4001 %  The format of the WriteBlobByte method is:
4002 %
4003 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
4004 %
4005 %  A description of each parameter follows.
4006 %
4007 %    o image: the image.
4008 %
4009 %    o value: Specifies the value to write.
4010 %
4011 */
4012 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4013 {
4014   assert(image != (Image *) NULL);
4015   assert(image->signature == MagickSignature);
4016   return(WriteBlobStream(image,1,&value));
4017 }
4018 \f
4019 /*
4020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4021 %                                                                             %
4022 %                                                                             %
4023 %                                                                             %
4024 +  W r i t e B l o b F l o a t                                                %
4025 %                                                                             %
4026 %                                                                             %
4027 %                                                                             %
4028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4029 %
4030 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4031 %  specified by the endian member of the image structure.
4032 %
4033 %  The format of the WriteBlobFloat method is:
4034 %
4035 %      ssize_t WriteBlobFloat(Image *image,const float value)
4036 %
4037 %  A description of each parameter follows.
4038 %
4039 %    o image: the image.
4040 %
4041 %    o value: Specifies the value to write.
4042 %
4043 */
4044 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4045 {
4046   union
4047   {
4048     unsigned int
4049       unsigned_value;
4050
4051     float
4052       float_value;
4053   } quantum;
4054
4055   quantum.unsigned_value=0U;
4056   quantum.float_value=value;
4057   return(WriteBlobLong(image,quantum.unsigned_value));
4058 }
4059 \f
4060 /*
4061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4062 %                                                                             %
4063 %                                                                             %
4064 %                                                                             %
4065 +  W r i t e B l o b L o n g                                                  %
4066 %                                                                             %
4067 %                                                                             %
4068 %                                                                             %
4069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4070 %
4071 %  WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
4072 %  specified by the endian member of the image structure.
4073 %
4074 %  The format of the WriteBlobLong method is:
4075 %
4076 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
4077 %
4078 %  A description of each parameter follows.
4079 %
4080 %    o image: the image.
4081 %
4082 %    o value: Specifies the value to write.
4083 %
4084 */
4085 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4086 {
4087   unsigned char
4088     buffer[4];
4089
4090   assert(image != (Image *) NULL);
4091   assert(image->signature == MagickSignature);
4092   if (image->endian == LSBEndian)
4093     {
4094       buffer[0]=(unsigned char) value;
4095       buffer[1]=(unsigned char) (value >> 8);
4096       buffer[2]=(unsigned char) (value >> 16);
4097       buffer[3]=(unsigned char) (value >> 24);
4098       return(WriteBlobStream(image,4,buffer));
4099     }
4100   buffer[0]=(unsigned char) (value >> 24);
4101   buffer[1]=(unsigned char) (value >> 16);
4102   buffer[2]=(unsigned char) (value >> 8);
4103   buffer[3]=(unsigned char) value;
4104   return(WriteBlobStream(image,4,buffer));
4105 }
4106 \f
4107 /*
4108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4109 %                                                                             %
4110 %                                                                             %
4111 %                                                                             %
4112 +   W r i t e B l o b S h o r t                                               %
4113 %                                                                             %
4114 %                                                                             %
4115 %                                                                             %
4116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4117 %
4118 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
4119 %  byte-order specified by the endian member of the image structure.
4120 %
4121 %  The format of the WriteBlobShort method is:
4122 %
4123 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
4124 %
4125 %  A description of each parameter follows.
4126 %
4127 %    o image: the image.
4128 %
4129 %    o value:  Specifies the value to write.
4130 %
4131 */
4132 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4133 {
4134   unsigned char
4135     buffer[2];
4136
4137   assert(image != (Image *) NULL);
4138   assert(image->signature == MagickSignature);
4139   if (image->endian == LSBEndian)
4140     {
4141       buffer[0]=(unsigned char) value;
4142       buffer[1]=(unsigned char) (value >> 8);
4143       return(WriteBlobStream(image,2,buffer));
4144     }
4145   buffer[0]=(unsigned char) (value >> 8);
4146   buffer[1]=(unsigned char) value;
4147   return(WriteBlobStream(image,2,buffer));
4148 }
4149 \f
4150 /*
4151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4152 %                                                                             %
4153 %                                                                             %
4154 %                                                                             %
4155 +  W r i t e B l o b L S B L o n g                                            %
4156 %                                                                             %
4157 %                                                                             %
4158 %                                                                             %
4159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4160 %
4161 %  WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
4162 %  least-significant byte first order.
4163 %
4164 %  The format of the WriteBlobLSBLong method is:
4165 %
4166 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4167 %
4168 %  A description of each parameter follows.
4169 %
4170 %    o image: the image.
4171 %
4172 %    o value: Specifies the value to write.
4173 %
4174 */
4175 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4176 {
4177   unsigned char
4178     buffer[4];
4179
4180   assert(image != (Image *) NULL);
4181   assert(image->signature == MagickSignature);
4182   buffer[0]=(unsigned char) value;
4183   buffer[1]=(unsigned char) (value >> 8);
4184   buffer[2]=(unsigned char) (value >> 16);
4185   buffer[3]=(unsigned char) (value >> 24);
4186   return(WriteBlobStream(image,4,buffer));
4187 }
4188 \f
4189 /*
4190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4191 %                                                                             %
4192 %                                                                             %
4193 %                                                                             %
4194 +   W r i t e B l o b L S B S h o r t                                         %
4195 %                                                                             %
4196 %                                                                             %
4197 %                                                                             %
4198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4199 %
4200 %  WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
4201 %  least-significant byte first order.
4202 %
4203 %  The format of the WriteBlobLSBShort method is:
4204 %
4205 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4206 %
4207 %  A description of each parameter follows.
4208 %
4209 %    o image: the image.
4210 %
4211 %    o value:  Specifies the value to write.
4212 %
4213 */
4214 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4215 {
4216   unsigned char
4217     buffer[2];
4218
4219   assert(image != (Image *) NULL);
4220   assert(image->signature == MagickSignature);
4221   buffer[0]=(unsigned char) value;
4222   buffer[1]=(unsigned char) (value >> 8);
4223   return(WriteBlobStream(image,2,buffer));
4224 }
4225 \f
4226 /*
4227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4228 %                                                                             %
4229 %                                                                             %
4230 %                                                                             %
4231 +  W r i t e B l o b M S B L o n g                                            %
4232 %                                                                             %
4233 %                                                                             %
4234 %                                                                             %
4235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4236 %
4237 %  WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
4238 %  most-significant byte first order.
4239 %
4240 %  The format of the WriteBlobMSBLong method is:
4241 %
4242 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4243 %
4244 %  A description of each parameter follows.
4245 %
4246 %    o value:  Specifies the value to write.
4247 %
4248 %    o image: the image.
4249 %
4250 */
4251 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4252 {
4253   unsigned char
4254     buffer[4];
4255
4256   assert(image != (Image *) NULL);
4257   assert(image->signature == MagickSignature);
4258   buffer[0]=(unsigned char) (value >> 24);
4259   buffer[1]=(unsigned char) (value >> 16);
4260   buffer[2]=(unsigned char) (value >> 8);
4261   buffer[3]=(unsigned char) value;
4262   return(WriteBlobStream(image,4,buffer));
4263 }
4264 \f
4265 /*
4266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4267 %                                                                             %
4268 %                                                                             %
4269 %                                                                             %
4270 +  W r i t e B l o b M S B L o n g L o n g                                    %
4271 %                                                                             %
4272 %                                                                             %
4273 %                                                                             %
4274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4275 %
4276 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4277 %  most-significant byte first order.
4278 %
4279 %  The format of the WriteBlobMSBLongLong method is:
4280 %
4281 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4282 %
4283 %  A description of each parameter follows.
4284 %
4285 %    o value:  Specifies the value to write.
4286 %
4287 %    o image: the image.
4288 %
4289 */
4290 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4291   const MagickSizeType value)
4292 {
4293   unsigned char
4294     buffer[8];
4295
4296   assert(image != (Image *) NULL);
4297   assert(image->signature == MagickSignature);
4298   buffer[0]=(unsigned char) (value >> 56);
4299   buffer[1]=(unsigned char) (value >> 48);
4300   buffer[2]=(unsigned char) (value >> 40);
4301   buffer[3]=(unsigned char) (value >> 32);
4302   buffer[4]=(unsigned char) (value >> 24);
4303   buffer[5]=(unsigned char) (value >> 16);
4304   buffer[6]=(unsigned char) (value >> 8);
4305   buffer[7]=(unsigned char) value;
4306   return(WriteBlobStream(image,8,buffer));
4307 }
4308 \f
4309 /*
4310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4311 %                                                                             %
4312 %                                                                             %
4313 %                                                                             %
4314 +  W r i t e B l o b M S B S h o r t                                          %
4315 %                                                                             %
4316 %                                                                             %
4317 %                                                                             %
4318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4319 %
4320 %  WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
4321 %  most-significant byte first order.
4322 %
4323 %  The format of the WriteBlobMSBShort method is:
4324 %
4325 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4326 %
4327 %  A description of each parameter follows.
4328 %
4329 %   o  value:  Specifies the value to write.
4330 %
4331 %   o  file:  Specifies the file to write the data to.
4332 %
4333 */
4334 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4335 {
4336   unsigned char
4337     buffer[2];
4338
4339   assert(image != (Image *) NULL);
4340   assert(image->signature == MagickSignature);
4341   buffer[0]=(unsigned char) (value >> 8);
4342   buffer[1]=(unsigned char) value;
4343   return(WriteBlobStream(image,2,buffer));
4344 }
4345 \f
4346 /*
4347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4348 %                                                                             %
4349 %                                                                             %
4350 %                                                                             %
4351 +  W r i t e B l o b S t r i n g                                              %
4352 %                                                                             %
4353 %                                                                             %
4354 %                                                                             %
4355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4356 %
4357 %  WriteBlobString() write a string to a blob.  It returns the number of
4358 %  characters written.
4359 %
4360 %  The format of the WriteBlobString method is:
4361 %
4362 %      ssize_t WriteBlobString(Image *image,const char *string)
4363 %
4364 %  A description of each parameter follows.
4365 %
4366 %    o image: the image.
4367 %
4368 %    o string: Specifies the string to write.
4369 %
4370 */
4371 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4372 {
4373   assert(image != (Image *) NULL);
4374   assert(image->signature == MagickSignature);
4375   assert(string != (const char *) NULL);
4376   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4377 }