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