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