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