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