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