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