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