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