]> granicus.if.org Git - imagemagick/blob - MagickCore/blob.c
Corrected initialization when reading/writing a user blob.
[imagemagick] / MagickCore / 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 %                                   Cristy                                    %
17 %                                 July 1999                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2017 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 #ifdef __VMS
44 #include  <types.h>
45 #include  <mman.h>
46 #endif
47 #include "MagickCore/studio.h"
48 #include "MagickCore/blob.h"
49 #include "MagickCore/blob-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/image-private.h"
57 #include "MagickCore/list.h"
58 #include "MagickCore/locale_.h"
59 #include "MagickCore/log.h"
60 #include "MagickCore/magick.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/nt-base-private.h"
63 #include "MagickCore/option.h"
64 #include "MagickCore/policy.h"
65 #include "MagickCore/resource_.h"
66 #include "MagickCore/semaphore.h"
67 #include "MagickCore/string_.h"
68 #include "MagickCore/string-private.h"
69 #include "MagickCore/token.h"
70 #include "MagickCore/utility.h"
71 #include "MagickCore/utility-private.h"
72 #if defined(MAGICKCORE_ZLIB_DELEGATE)
73 #include "zlib.h"
74 #endif
75 #if defined(MAGICKCORE_BZLIB_DELEGATE)
76 #include "bzlib.h"
77 #endif
78 \f
79 /*
80   Define declarations.
81 */
82 #define MagickMaxBlobExtent  (8*8192)
83 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
84 # define MAP_ANONYMOUS  MAP_ANON
85 #endif
86 #if !defined(MAP_FAILED)
87 #define MAP_FAILED  ((void *) -1)
88 #endif
89 #if defined(__OS2__)
90 #include <io.h>
91 #define _O_BINARY O_BINARY
92 #endif
93 \f
94 /*
95   Typedef declarations.
96 */
97 typedef union FileInfo
98 {
99   FILE
100     *file;
101
102 #if defined(MAGICKCORE_ZLIB_DELEGATE)
103   gzFile
104     gzfile;
105 #endif
106
107 #if defined(MAGICKCORE_BZLIB_DELEGATE)
108   BZFILE
109     *bzfile;
110 #endif
111 } FileInfo;
112
113 struct _BlobInfo
114 {
115   size_t
116     length,
117     extent,
118     quantum;
119
120   MagickBooleanType
121     mapped,
122     eof;
123
124   MagickOffsetType
125     offset;
126
127   MagickSizeType
128     size;
129
130   MagickBooleanType
131     exempt,
132     synchronize,
133     status,
134     temporary;
135
136   StreamType
137     type;
138
139   FileInfo
140     file_info;
141
142   struct stat
143     properties;
144
145   StreamHandler
146     stream;
147
148   UserBlobInfo
149     *user_info;
150
151   unsigned char
152     *data;
153
154   MagickBooleanType
155     debug;
156
157   SemaphoreInfo
158     *semaphore;
159
160   ssize_t
161     reference_count;
162
163   size_t
164     signature;
165 };
166 \f
167 /*
168   Forward declarations.
169 */
170 static int
171   SyncBlob(Image *);
172 \f
173 /*
174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 %                                                                             %
176 %                                                                             %
177 %                                                                             %
178 +   A t t a c h B l o b                                                       %
179 %                                                                             %
180 %                                                                             %
181 %                                                                             %
182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 %
184 %  AttachBlob() attaches a blob to the BlobInfo structure.
185 %
186 %  The format of the AttachBlob method is:
187 %
188 %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
189 %
190 %  A description of each parameter follows:
191 %
192 %    o blob_info: Specifies a pointer to a BlobInfo structure.
193 %
194 %    o blob: the address of a character stream in one of the image formats
195 %      understood by ImageMagick.
196 %
197 %    o length: This size_t integer reflects the length in bytes of the blob.
198 %
199 */
200 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
201   const size_t length)
202 {
203   assert(blob_info != (BlobInfo *) NULL);
204   if (blob_info->debug != MagickFalse)
205     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
206   blob_info->length=length;
207   blob_info->extent=length;
208   blob_info->quantum=(size_t) MagickMaxBlobExtent;
209   blob_info->offset=0;
210   blob_info->type=BlobStream;
211   blob_info->file_info.file=(FILE *) NULL;
212   blob_info->data=(unsigned char *) blob;
213   blob_info->mapped=MagickFalse;
214 }
215 \f
216 /*
217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218 %                                                                             %
219 %                                                                             %
220 %                                                                             %
221 +   B l o b T o F i l e                                                       %
222 %                                                                             %
223 %                                                                             %
224 %                                                                             %
225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 %
227 %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
228 %  occurs otherwise MagickTrue.
229 %
230 %  The format of the BlobToFile method is:
231 %
232 %       MagickBooleanType BlobToFile(char *filename,const void *blob,
233 %         const size_t length,ExceptionInfo *exception)
234 %
235 %  A description of each parameter follows:
236 %
237 %    o filename: Write the blob to this file.
238 %
239 %    o blob: the address of a blob.
240 %
241 %    o length: This length in bytes of the blob.
242 %
243 %    o exception: return any errors or warnings in this structure.
244 %
245 */
246 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
247   const size_t length,ExceptionInfo *exception)
248 {
249   int
250     file;
251
252   register size_t
253     i;
254
255   ssize_t
256     count;
257
258   assert(filename != (const char *) NULL);
259   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
260   assert(blob != (const void *) NULL);
261   if (*filename == '\0')
262     file=AcquireUniqueFileResource(filename);
263   else
264     file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
265   if (file == -1)
266     {
267       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
268       return(MagickFalse);
269     }
270   for (i=0; i < length; i+=count)
271   {
272     count=write(file,(const char *) blob+i,MagickMin(length-i,SSIZE_MAX));
273     if (count <= 0)
274       {
275         count=0;
276         if (errno != EINTR)
277           break;
278       }
279   }
280   file=close(file);
281   if ((file == -1) || (i < length))
282     {
283       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
284       return(MagickFalse);
285     }
286   return(MagickTrue);
287 }
288 \f
289 /*
290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 %                                                                             %
292 %                                                                             %
293 %                                                                             %
294 %   B l o b T o I m a g e                                                     %
295 %                                                                             %
296 %                                                                             %
297 %                                                                             %
298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299 %
300 %  BlobToImage() implements direct to memory image formats.  It returns the
301 %  blob as an image.
302 %
303 %  The format of the BlobToImage method is:
304 %
305 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
306 %        const size_t length,ExceptionInfo *exception)
307 %
308 %  A description of each parameter follows:
309 %
310 %    o image_info: the image info.
311 %
312 %    o blob: the address of a character stream in one of the image formats
313 %      understood by ImageMagick.
314 %
315 %    o length: This size_t integer reflects the length in bytes of the blob.
316 %
317 %    o exception: return any errors or warnings in this structure.
318 %
319 */
320 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
321   const size_t length,ExceptionInfo *exception)
322 {
323   const MagickInfo
324     *magick_info;
325
326   Image
327     *image;
328
329   ImageInfo
330     *blob_info,
331     *clone_info;
332
333   MagickBooleanType
334     status;
335
336   assert(image_info != (ImageInfo *) NULL);
337   assert(image_info->signature == MagickCoreSignature);
338   if (image_info->debug != MagickFalse)
339     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
340       image_info->filename);
341   assert(exception != (ExceptionInfo *) NULL);
342   if ((blob == (const void *) NULL) || (length == 0))
343     {
344       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
345         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
346       return((Image *) NULL);
347     }
348   blob_info=CloneImageInfo(image_info);
349   blob_info->blob=(void *) blob;
350   blob_info->length=length;
351   if (*blob_info->magick == '\0')
352     (void) SetImageInfo(blob_info,0,exception);
353   magick_info=GetMagickInfo(blob_info->magick,exception);
354   if (magick_info == (const MagickInfo *) NULL)
355     {
356       (void) ThrowMagickException(exception,GetMagickModule(),
357         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
358         blob_info->magick);
359       blob_info=DestroyImageInfo(blob_info);
360       return((Image *) NULL);
361     }
362   if (GetMagickBlobSupport(magick_info) != MagickFalse)
363     {
364       /*
365         Native blob support for this image format.
366       */
367       (void) CopyMagickString(blob_info->filename,image_info->filename,
368         MagickPathExtent);
369       (void) CopyMagickString(blob_info->magick,image_info->magick,
370         MagickPathExtent);
371       image=ReadImage(blob_info,exception);
372       if (image != (Image *) NULL)
373         (void) DetachBlob(image->blob);
374       blob_info=DestroyImageInfo(blob_info);
375       return(image);
376     }
377   /*
378     Write blob to a temporary file on disk.
379   */
380   blob_info->blob=(void *) NULL;
381   blob_info->length=0;
382   *blob_info->filename='\0';
383   status=BlobToFile(blob_info->filename,blob,length,exception);
384   if (status == MagickFalse)
385     {
386       (void) RelinquishUniqueFileResource(blob_info->filename);
387       blob_info=DestroyImageInfo(blob_info);
388       return((Image *) NULL);
389     }
390   clone_info=CloneImageInfo(blob_info);
391   (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
392     blob_info->magick,blob_info->filename);
393   image=ReadImage(clone_info,exception);
394   if (image != (Image *) NULL)
395     {
396       Image
397         *images;
398
399       /*
400         Restore original filenames and image format.
401       */
402       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
403       {
404         (void) CopyMagickString(images->filename,image_info->filename,
405           MagickPathExtent);
406         (void) CopyMagickString(images->magick_filename,image_info->filename,
407           MagickPathExtent);
408         (void) CopyMagickString(images->magick,magick_info->name,
409           MagickPathExtent);
410         images=GetNextImageInList(images);
411       }
412     }
413   clone_info=DestroyImageInfo(clone_info);
414   (void) RelinquishUniqueFileResource(blob_info->filename);
415   blob_info=DestroyImageInfo(blob_info);
416   return(image);
417 }
418 \f
419 /*
420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421 %                                                                             %
422 %                                                                             %
423 %                                                                             %
424 +   C l o n e B l o b I n f o                                                 %
425 %                                                                             %
426 %                                                                             %
427 %                                                                             %
428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429 %
430 %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
431 %  blob info is NULL, a new one.
432 %
433 %  The format of the CloneBlobInfo method is:
434 %
435 %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
436 %
437 %  A description of each parameter follows:
438 %
439 %    o blob_info: the blob info.
440 %
441 */
442 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
443 {
444   BlobInfo
445     *clone_info;
446
447   clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
448   if (clone_info == (BlobInfo *) NULL)
449     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
450   GetBlobInfo(clone_info);
451   if (blob_info == (BlobInfo *) NULL)
452     return(clone_info);
453   clone_info->length=blob_info->length;
454   clone_info->extent=blob_info->extent;
455   clone_info->synchronize=blob_info->synchronize;
456   clone_info->quantum=blob_info->quantum;
457   clone_info->mapped=blob_info->mapped;
458   clone_info->eof=blob_info->eof;
459   clone_info->offset=blob_info->offset;
460   clone_info->size=blob_info->size;
461   clone_info->exempt=blob_info->exempt;
462   clone_info->status=blob_info->status;
463   clone_info->temporary=blob_info->temporary;
464   clone_info->type=blob_info->type;
465   clone_info->file_info.file=blob_info->file_info.file;
466   clone_info->properties=blob_info->properties;
467   clone_info->stream=blob_info->stream;
468   clone_info->user_info=blob_info->user_info;
469   clone_info->data=blob_info->data;
470   clone_info->debug=IsEventLogging();
471   clone_info->reference_count=1;
472   return(clone_info);
473 }
474 \f
475 /*
476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 %                                                                             %
478 %                                                                             %
479 %                                                                             %
480 +   C l o s e B l o b                                                         %
481 %                                                                             %
482 %                                                                             %
483 %                                                                             %
484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 %
486 %  CloseBlob() closes a stream associated with the image.
487 %
488 %  The format of the CloseBlob method is:
489 %
490 %      MagickBooleanType CloseBlob(Image *image)
491 %
492 %  A description of each parameter follows:
493 %
494 %    o image: the image.
495 %
496 */
497 MagickExport MagickBooleanType CloseBlob(Image *image)
498 {
499   int
500     status;
501
502   /*
503     Close image file.
504   */
505   assert(image != (Image *) NULL);
506   assert(image->signature == MagickCoreSignature);
507   if (image->debug != MagickFalse)
508     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
509   assert(image->blob != (BlobInfo *) NULL);
510   if (image->blob->type == UndefinedStream)
511     return(MagickTrue);
512   status=SyncBlob(image);
513   switch (image->blob->type)
514   {
515     case UndefinedStream:
516     case StandardStream:
517       break;
518     case FileStream:
519     case PipeStream:
520     {
521       if (image->blob->synchronize != MagickFalse)
522         status=fsync(fileno(image->blob->file_info.file));
523       status=ferror(image->blob->file_info.file);
524       break;
525     }
526     case ZipStream:
527     {
528 #if defined(MAGICKCORE_ZLIB_DELEGATE)
529       (void) gzerror(image->blob->file_info.gzfile,&status);
530 #endif
531       break;
532     }
533     case BZipStream:
534     {
535 #if defined(MAGICKCORE_BZLIB_DELEGATE)
536       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
537 #endif
538       break;
539     }
540     case FifoStream:
541       break;
542     case BlobStream:
543     {
544       if ((image->blob->file_info.file != (FILE *) NULL) &&
545           (image->blob->synchronize != MagickFalse))
546         {
547           (void) fsync(fileno(image->blob->file_info.file));
548           status=ferror(image->blob->file_info.file);
549         }
550       break;
551     }
552     case UserStream:
553       break;
554   }
555   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
556   image->blob->size=GetBlobSize(image);
557   image->extent=image->blob->size;
558   image->blob->eof=MagickFalse;
559   if (image->blob->exempt != MagickFalse)
560     {
561       image->blob->type=UndefinedStream;
562       return(image->blob->status);
563     }
564   switch (image->blob->type)
565   {
566     case UndefinedStream:
567     case StandardStream:
568       break;
569     case FileStream:
570     {
571       status=fclose(image->blob->file_info.file);
572       break;
573     }
574     case PipeStream:
575     {
576 #if defined(MAGICKCORE_HAVE_PCLOSE)
577       status=pclose(image->blob->file_info.file);
578 #endif
579       break;
580     }
581     case ZipStream:
582     {
583 #if defined(MAGICKCORE_ZLIB_DELEGATE)
584       status=gzclose(image->blob->file_info.gzfile);
585 #endif
586       break;
587     }
588     case BZipStream:
589     {
590 #if defined(MAGICKCORE_BZLIB_DELEGATE)
591       BZ2_bzclose(image->blob->file_info.bzfile);
592 #endif
593       break;
594     }
595     case FifoStream:
596       break;
597     case BlobStream:
598     {
599       if (image->blob->file_info.file != (FILE *) NULL)
600         status=fclose(image->blob->file_info.file);
601       break;
602     }
603     case UserStream:
604       break;
605   }
606   (void) DetachBlob(image->blob);
607   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
608   return(image->blob->status);
609 }
610 \f
611 /*
612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 %                                                                             %
614 %                                                                             %
615 %                                                                             %
616 +   D e s t r o y B l o b                                                     %
617 %                                                                             %
618 %                                                                             %
619 %                                                                             %
620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621 %
622 %  DestroyBlob() deallocates memory associated with a blob.
623 %
624 %  The format of the DestroyBlob method is:
625 %
626 %      void DestroyBlob(Image *image)
627 %
628 %  A description of each parameter follows:
629 %
630 %    o image: the image.
631 %
632 */
633 MagickExport void DestroyBlob(Image *image)
634 {
635   MagickBooleanType
636     destroy;
637
638   assert(image != (Image *) NULL);
639   assert(image->signature == MagickCoreSignature);
640   if (image->debug != MagickFalse)
641     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
642   assert(image->blob != (BlobInfo *) NULL);
643   assert(image->blob->signature == MagickCoreSignature);
644   destroy=MagickFalse;
645   LockSemaphoreInfo(image->blob->semaphore);
646   image->blob->reference_count--;
647   assert(image->blob->reference_count >= 0);
648   if (image->blob->reference_count == 0)
649     destroy=MagickTrue;
650   UnlockSemaphoreInfo(image->blob->semaphore);
651   if (destroy == MagickFalse)
652     return;
653   (void) CloseBlob(image);
654   if (image->blob->mapped != MagickFalse)
655     {
656       (void) UnmapBlob(image->blob->data,image->blob->length);
657       RelinquishMagickResource(MapResource,image->blob->length);
658     }
659   if (image->blob->semaphore != (SemaphoreInfo *) NULL)
660     RelinquishSemaphoreInfo(&image->blob->semaphore);
661   image->blob->signature=(~MagickCoreSignature);
662   image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
663 }
664 \f
665 /*
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 %                                                                             %
668 %                                                                             %
669 %                                                                             %
670 +   D e t a c h B l o b                                                       %
671 %                                                                             %
672 %                                                                             %
673 %                                                                             %
674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675 %
676 %  DetachBlob() detaches a blob from the BlobInfo structure.
677 %
678 %  The format of the DetachBlob method is:
679 %
680 %      void *DetachBlob(BlobInfo *blob_info)
681 %
682 %  A description of each parameter follows:
683 %
684 %    o blob_info: Specifies a pointer to a BlobInfo structure.
685 %
686 */
687 MagickExport void *DetachBlob(BlobInfo *blob_info)
688 {
689   void
690     *data;
691
692   assert(blob_info != (BlobInfo *) NULL);
693   if (blob_info->debug != MagickFalse)
694     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
695   if (blob_info->mapped != MagickFalse)
696     {
697       (void) UnmapBlob(blob_info->data,blob_info->length);
698       blob_info->data=(unsigned char *) NULL;
699       RelinquishMagickResource(MapResource,blob_info->length);
700     }
701   blob_info->mapped=MagickFalse;
702   blob_info->length=0;
703   blob_info->offset=0;
704   blob_info->eof=MagickFalse;
705   blob_info->exempt=MagickFalse;
706   blob_info->type=UndefinedStream;
707   blob_info->file_info.file=(FILE *) NULL;
708   data=blob_info->data;
709   blob_info->data=(unsigned char *) NULL;
710   blob_info->stream=(StreamHandler) NULL;
711   blob_info->user_info=(UserBlobInfo*) NULL;
712   return(data);
713 }
714 \f
715 /*
716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717 %                                                                             %
718 %                                                                             %
719 %                                                                             %
720 +   D i s a s s o c i a t e B l o b                                           %
721 %                                                                             %
722 %                                                                             %
723 %                                                                             %
724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
725 %
726 %  DisassociateBlob() disassociates the image stream.  It checks if the
727 %  blob of the specified image is referenced by other images. If the reference
728 %  count is higher then 1 a new blob is assigned to the specified image.
729 %
730 %  The format of the DisassociateBlob method is:
731 %
732 %      void DisassociateBlob(const Image *image)
733 %
734 %  A description of each parameter follows:
735 %
736 %    o image: the image.
737 %
738 */
739 MagickExport void DisassociateBlob(Image *image)
740 {
741   BlobInfo
742     *blob;
743
744   MagickBooleanType
745     clone;
746
747   assert(image != (Image *) NULL);
748   assert(image->signature == MagickCoreSignature);
749   if (image->debug != MagickFalse)
750     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
751   assert(image->blob != (BlobInfo *) NULL);
752   assert(image->blob->signature == MagickCoreSignature);
753   clone=MagickFalse;
754   LockSemaphoreInfo(image->blob->semaphore);
755   assert(image->blob->reference_count >= 0);
756   if (image->blob->reference_count > 1)
757     clone=MagickTrue;
758   UnlockSemaphoreInfo(image->blob->semaphore);
759   if (clone == MagickFalse)
760     return;
761   blob=CloneBlobInfo(image->blob);
762   DestroyBlob(image);
763   image->blob=blob;
764 }
765 \f
766 /*
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768 %                                                                             %
769 %                                                                             %
770 %                                                                             %
771 +  D i s c a r d B l o b B y t e s                                            %
772 %                                                                             %
773 %                                                                             %
774 %                                                                             %
775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
776 %
777 %  DiscardBlobBytes() discards bytes in a blob.
778 %
779 %  The format of the DiscardBlobBytes method is:
780 %
781 %      MagickBooleanType DiscardBlobBytes(Image *image,
782 %        const MagickSizeType length)
783 %
784 %  A description of each parameter follows.
785 %
786 %    o image: the image.
787 %
788 %    o length:  the number of bytes to skip.
789 %
790 */
791 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
792   const MagickSizeType length)
793 {
794   register MagickOffsetType
795     i;
796
797   size_t
798     quantum;
799
800   ssize_t
801     count;
802
803   unsigned char
804     buffer[16384];
805
806   assert(image != (Image *) NULL);
807   assert(image->signature == MagickCoreSignature);
808   if (length != (MagickSizeType) ((MagickOffsetType) length))
809     return(MagickFalse);
810   count=0;
811   for (i=0; i < (MagickOffsetType) length; i+=count)
812   {
813     quantum=(size_t) MagickMin(length-i,sizeof(buffer));
814     (void) ReadBlobStream(image,quantum,buffer,&count);
815     if (count <= 0)
816       {
817         count=0;
818         if (errno != EINTR)
819           break;
820       }
821   }
822   return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
823 }
824 \f
825 /*
826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 %                                                                             %
828 %                                                                             %
829 %                                                                             %
830 +   D u p l i c a t e s B l o b                                               %
831 %                                                                             %
832 %                                                                             %
833 %                                                                             %
834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835 %
836 %  DuplicateBlob() duplicates a blob descriptor.
837 %
838 %  The format of the DuplicateBlob method is:
839 %
840 %      void DuplicateBlob(Image *image,const Image *duplicate)
841 %
842 %  A description of each parameter follows:
843 %
844 %    o image: the image.
845 %
846 %    o duplicate: the duplicate image.
847 %
848 */
849 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
850 {
851   assert(image != (Image *) NULL);
852   assert(image->signature == MagickCoreSignature);
853   if (image->debug != MagickFalse)
854     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
855   assert(duplicate != (Image *) NULL);
856   assert(duplicate->signature == MagickCoreSignature);
857   DestroyBlob(image);
858   image->blob=ReferenceBlob(duplicate->blob);
859 }
860 \f
861 /*
862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863 %                                                                             %
864 %                                                                             %
865 %                                                                             %
866 +  E O F B l o b                                                              %
867 %                                                                             %
868 %                                                                             %
869 %                                                                             %
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 %
872 %  EOFBlob() returns a non-zero value when EOF has been detected reading from
873 %  a blob or file.
874 %
875 %  The format of the EOFBlob method is:
876 %
877 %      int EOFBlob(const Image *image)
878 %
879 %  A description of each parameter follows:
880 %
881 %    o image: the image.
882 %
883 */
884 MagickExport int EOFBlob(const Image *image)
885 {
886   assert(image != (Image *) NULL);
887   assert(image->signature == MagickCoreSignature);
888   if (image->debug != MagickFalse)
889     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
890   assert(image->blob != (BlobInfo *) NULL);
891   assert(image->blob->type != UndefinedStream);
892   switch (image->blob->type)
893   {
894     case UndefinedStream:
895     case StandardStream:
896       break;
897     case FileStream:
898     case PipeStream:
899     {
900       image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
901         MagickFalse;
902       break;
903     }
904     case ZipStream:
905     {
906       image->blob->eof=MagickFalse;
907       break;
908     }
909     case BZipStream:
910     {
911 #if defined(MAGICKCORE_BZLIB_DELEGATE)
912       int
913         status;
914
915       status=0;
916       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
917       image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
918 #endif
919       break;
920     }
921     case FifoStream:
922     {
923       image->blob->eof=MagickFalse;
924       break;
925     }
926     case BlobStream:
927       break;
928     case UserStream:
929       break;
930   }
931   return((int) image->blob->eof);
932 }
933 \f
934 /*
935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936 %                                                                             %
937 %                                                                             %
938 %                                                                             %
939 %   F i l e T o B l o b                                                       %
940 %                                                                             %
941 %                                                                             %
942 %                                                                             %
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 %
945 %  FileToBlob() returns the contents of a file as a buffer terminated with
946 %  the '\0' character.  The length of the buffer (not including the extra
947 %  terminating '\0' character) is returned via the 'length' parameter.  Free
948 %  the buffer with RelinquishMagickMemory().
949 %
950 %  The format of the FileToBlob method is:
951 %
952 %      void *FileToBlob(const char *filename,const size_t extent,
953 %        size_t *length,ExceptionInfo *exception)
954 %
955 %  A description of each parameter follows:
956 %
957 %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
958 %      an error occurs NULL is returned.
959 %
960 %    o filename: the filename.
961 %
962 %    o extent:  The maximum length of the blob.
963 %
964 %    o length: On return, this reflects the actual length of the blob.
965 %
966 %    o exception: return any errors or warnings in this structure.
967 %
968 */
969 MagickExport void *FileToBlob(const char *filename,const size_t extent,
970   size_t *length,ExceptionInfo *exception)
971 {
972   int
973     file;
974
975   MagickOffsetType
976     offset;
977
978   register size_t
979     i;
980
981   ssize_t
982     count;
983
984   unsigned char
985     *blob;
986
987   void
988     *map;
989
990   assert(filename != (const char *) NULL);
991   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
992   assert(exception != (ExceptionInfo *) NULL);
993   *length=0;
994   file=fileno(stdin);
995   if (LocaleCompare(filename,"-") != 0)
996     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
997   if (file == -1)
998     {
999       ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1000       return(NULL);
1001     }
1002   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1003   count=0;
1004   if ((file == fileno(stdin)) || (offset < 0) ||
1005       (offset != (MagickOffsetType) ((ssize_t) offset)))
1006     {
1007       size_t
1008         quantum;
1009
1010       struct stat
1011         file_stats;
1012
1013       /*
1014         Stream is not seekable.
1015       */
1016       offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1017       quantum=(size_t) MagickMaxBufferExtent;
1018       if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1019         quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1020       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1021       for (i=0; blob != (unsigned char *) NULL; i+=count)
1022       {
1023         count=read(file,blob+i,quantum);
1024         if (count <= 0)
1025           {
1026             count=0;
1027             if (errno != EINTR)
1028               break;
1029           }
1030         if (~((size_t) i) < (quantum+1))
1031           {
1032             blob=(unsigned char *) RelinquishMagickMemory(blob);
1033             break;
1034           }
1035         blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1036           sizeof(*blob));
1037         if ((size_t) (i+count) >= extent)
1038           break;
1039       }
1040       if (LocaleCompare(filename,"-") != 0)
1041         file=close(file);
1042       if (blob == (unsigned char *) NULL)
1043         {
1044           (void) ThrowMagickException(exception,GetMagickModule(),
1045             ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1046           return(NULL);
1047         }
1048       if (file == -1)
1049         {
1050           blob=(unsigned char *) RelinquishMagickMemory(blob);
1051           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1052           return(NULL);
1053         }
1054       *length=(size_t) MagickMin(i+count,extent);
1055       blob[*length]='\0';
1056       return(blob);
1057     }
1058   *length=(size_t) MagickMin(offset,(MagickOffsetType) 
1059     MagickMin(extent,SSIZE_MAX));
1060   blob=(unsigned char *) NULL;
1061   if (~(*length) >= (MagickPathExtent-1))
1062     blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1063       sizeof(*blob));
1064   if (blob == (unsigned char *) NULL)
1065     {
1066       file=close(file);
1067       (void) ThrowMagickException(exception,GetMagickModule(),
1068         ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1069       return(NULL);
1070     }
1071   map=MapBlob(file,ReadMode,0,*length);
1072   if (map != (unsigned char *) NULL)
1073     {
1074       (void) memcpy(blob,map,*length);
1075       (void) UnmapBlob(map,*length);
1076     }
1077   else
1078     {
1079       (void) lseek(file,0,SEEK_SET);
1080       for (i=0; i < *length; i+=count)
1081       {
1082         count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
1083         if (count <= 0)
1084           {
1085             count=0;
1086             if (errno != EINTR)
1087               break;
1088           }
1089       }
1090       if (i < *length)
1091         {
1092           file=close(file)-1;
1093           blob=(unsigned char *) RelinquishMagickMemory(blob);
1094           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1095           return(NULL);
1096         }
1097     }
1098   blob[*length]='\0';
1099   if (LocaleCompare(filename,"-") != 0)
1100     file=close(file);
1101   if (file == -1)
1102     {
1103       blob=(unsigned char *) RelinquishMagickMemory(blob);
1104       ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1105     }
1106   return(blob);
1107 }
1108 \f
1109 /*
1110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 %                                                                             %
1112 %                                                                             %
1113 %                                                                             %
1114 %   F i l e T o I m a g e                                                     %
1115 %                                                                             %
1116 %                                                                             %
1117 %                                                                             %
1118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1119 %
1120 %  FileToImage() write the contents of a file to an image.
1121 %
1122 %  The format of the FileToImage method is:
1123 %
1124 %      MagickBooleanType FileToImage(Image *,const char *filename)
1125 %
1126 %  A description of each parameter follows:
1127 %
1128 %    o image: the image.
1129 %
1130 %    o filename: the filename.
1131 %
1132 */
1133
1134 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1135   const void *data)
1136 {
1137   MagickSizeType
1138     extent;
1139
1140   register unsigned char
1141     *q;
1142
1143   assert(image->blob != (BlobInfo *) NULL);
1144   assert(image->blob->type != UndefinedStream);
1145   assert(data != NULL);
1146   if (image->blob->type != BlobStream)
1147     return(WriteBlob(image,length,(const unsigned char *) data));
1148   extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1149   if (extent >= image->blob->extent)
1150     {
1151       extent=image->blob->extent+image->blob->quantum+length;
1152       image->blob->quantum<<=1;
1153       if (SetBlobExtent(image,extent) == MagickFalse)
1154         return(0);
1155     }
1156   q=image->blob->data+image->blob->offset;
1157   (void) memcpy(q,data,length);
1158   image->blob->offset+=length;
1159   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1160     image->blob->length=(size_t) image->blob->offset;
1161   return((ssize_t) length);
1162 }
1163
1164 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1165   ExceptionInfo *exception)
1166 {
1167   int
1168     file;
1169
1170   size_t
1171     length,
1172     quantum;
1173
1174   ssize_t
1175     count;
1176
1177   struct stat
1178     file_stats;
1179
1180   unsigned char
1181     *blob;
1182
1183   assert(image != (const Image *) NULL);
1184   assert(image->signature == MagickCoreSignature);
1185   assert(filename != (const char *) NULL);
1186   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1187   file=fileno(stdin);
1188   if (LocaleCompare(filename,"-") != 0)
1189     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1190   if (file == -1)
1191     {
1192       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1193       return(MagickFalse);
1194     }
1195   quantum=(size_t) MagickMaxBufferExtent;
1196   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1197     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1198   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1199   if (blob == (unsigned char *) NULL)
1200     {
1201       file=close(file);
1202       ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1203         filename);
1204       return(MagickFalse);
1205     }
1206   for ( ; ; )
1207   {
1208     count=read(file,blob,quantum);
1209     if (count <= 0)
1210       {
1211         count=0;
1212         if (errno != EINTR)
1213           break;
1214       }
1215     length=(size_t) count;
1216     count=WriteBlobStream(image,length,blob);
1217     if (count != (ssize_t) length)
1218       {
1219         ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1220         break;
1221       }
1222   }
1223   file=close(file);
1224   if (file == -1)
1225     ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1226   blob=(unsigned char *) RelinquishMagickMemory(blob);
1227   return(MagickTrue);
1228 }
1229 \f
1230 /*
1231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1232 %                                                                             %
1233 %                                                                             %
1234 %                                                                             %
1235 +   G e t B l o b E r r o r                                                   %
1236 %                                                                             %
1237 %                                                                             %
1238 %                                                                             %
1239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1240 %
1241 %  GetBlobError() returns MagickTrue if the blob associated with the specified
1242 %  image encountered an error.
1243 %
1244 %  The format of the GetBlobError method is:
1245 %
1246 %       MagickBooleanType GetBlobError(const Image *image)
1247 %
1248 %  A description of each parameter follows:
1249 %
1250 %    o image: the image.
1251 %
1252 */
1253 MagickExport MagickBooleanType GetBlobError(const Image *image)
1254 {
1255   assert(image != (const Image *) NULL);
1256   assert(image->signature == MagickCoreSignature);
1257   if (image->debug != MagickFalse)
1258     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1259   return(image->blob->status);
1260 }
1261 \f
1262 /*
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 %                                                                             %
1265 %                                                                             %
1266 %                                                                             %
1267 +   G e t B l o b F i l e H a n d l e                                         %
1268 %                                                                             %
1269 %                                                                             %
1270 %                                                                             %
1271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1272 %
1273 %  GetBlobFileHandle() returns the file handle associated with the image blob.
1274 %
1275 %  The format of the GetBlobFile method is:
1276 %
1277 %      FILE *GetBlobFileHandle(const Image *image)
1278 %
1279 %  A description of each parameter follows:
1280 %
1281 %    o image: the image.
1282 %
1283 */
1284 MagickExport FILE *GetBlobFileHandle(const Image *image)
1285 {
1286   assert(image != (const Image *) NULL);
1287   assert(image->signature == MagickCoreSignature);
1288   return(image->blob->file_info.file);
1289 }
1290 \f
1291 /*
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 %                                                                             %
1294 %                                                                             %
1295 %                                                                             %
1296 +   G e t B l o b I n f o                                                     %
1297 %                                                                             %
1298 %                                                                             %
1299 %                                                                             %
1300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1301 %
1302 %  GetBlobInfo() initializes the BlobInfo structure.
1303 %
1304 %  The format of the GetBlobInfo method is:
1305 %
1306 %      void GetBlobInfo(BlobInfo *blob_info)
1307 %
1308 %  A description of each parameter follows:
1309 %
1310 %    o blob_info: Specifies a pointer to a BlobInfo structure.
1311 %
1312 */
1313 MagickExport void GetBlobInfo(BlobInfo *blob_info)
1314 {
1315   assert(blob_info != (BlobInfo *) NULL);
1316   (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1317   blob_info->type=UndefinedStream;
1318   blob_info->quantum=(size_t) MagickMaxBlobExtent;
1319   blob_info->properties.st_mtime=time((time_t *) NULL);
1320   blob_info->properties.st_ctime=time((time_t *) NULL);
1321   blob_info->debug=IsEventLogging();
1322   blob_info->reference_count=1;
1323   blob_info->semaphore=AcquireSemaphoreInfo();
1324   blob_info->signature=MagickCoreSignature;
1325 }
1326 \f
1327 /*
1328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329 %                                                                             %
1330 %                                                                             %
1331 %                                                                             %
1332 %  G e t B l o b P r o p e r t i e s                                          %
1333 %                                                                             %
1334 %                                                                             %
1335 %                                                                             %
1336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 %
1338 %  GetBlobProperties() returns information about an image blob.
1339 %
1340 %  The format of the GetBlobProperties method is:
1341 %
1342 %      const struct stat *GetBlobProperties(const Image *image)
1343 %
1344 %  A description of each parameter follows:
1345 %
1346 %    o image: the image.
1347 %
1348 */
1349 MagickExport const struct stat *GetBlobProperties(const Image *image)
1350 {
1351   assert(image != (Image *) NULL);
1352   assert(image->signature == MagickCoreSignature);
1353   if (image->debug != MagickFalse)
1354     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1355   return(&image->blob->properties);
1356 }
1357 \f
1358 /*
1359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1360 %                                                                             %
1361 %                                                                             %
1362 %                                                                             %
1363 +  G e t B l o b S i z e                                                      %
1364 %                                                                             %
1365 %                                                                             %
1366 %                                                                             %
1367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1368 %
1369 %  GetBlobSize() returns the current length of the image file or blob; zero is
1370 %  returned if the size cannot be determined.
1371 %
1372 %  The format of the GetBlobSize method is:
1373 %
1374 %      MagickSizeType GetBlobSize(const Image *image)
1375 %
1376 %  A description of each parameter follows:
1377 %
1378 %    o image: the image.
1379 %
1380 */
1381 MagickExport MagickSizeType GetBlobSize(const Image *image)
1382 {
1383   MagickSizeType
1384     extent;
1385
1386   assert(image != (Image *) NULL);
1387   assert(image->signature == MagickCoreSignature);
1388   if (image->debug != MagickFalse)
1389     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1390   assert(image->blob != (BlobInfo *) NULL);
1391   extent=0;
1392   switch (image->blob->type)
1393   {
1394     case UndefinedStream:
1395     case StandardStream:
1396     {
1397       extent=image->blob->size;
1398       break;
1399     }
1400     case FileStream:
1401     {
1402       if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
1403         extent=(MagickSizeType) image->blob->properties.st_size;
1404       break;
1405     }
1406     case PipeStream:
1407     {
1408       extent=image->blob->size;
1409       break;
1410     }
1411     case ZipStream:
1412     case BZipStream:
1413     {
1414       MagickBooleanType
1415         status;
1416
1417       status=GetPathAttributes(image->filename,&image->blob->properties);
1418       if (status != MagickFalse)
1419         extent=(MagickSizeType) image->blob->properties.st_size;
1420       break;
1421     }
1422     case FifoStream:
1423       break;
1424     case BlobStream:
1425     {
1426       extent=(MagickSizeType) image->blob->length;
1427       break;
1428     }
1429     case UserStream:
1430       break;
1431   }
1432   return(extent);
1433 }
1434 \f
1435 /*
1436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1437 %                                                                             %
1438 %                                                                             %
1439 %                                                                             %
1440 +   G e t B l o b S t r e a m D a t a                                         %
1441 %                                                                             %
1442 %                                                                             %
1443 %                                                                             %
1444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1445 %
1446 %  GetBlobStreamData() returns the stream data for the image.
1447 %
1448 %  The format of the GetBlobStreamData method is:
1449 %
1450 %      void *GetBlobStreamData(const Image *image)
1451 %
1452 %  A description of each parameter follows:
1453 %
1454 %    o image: the image.
1455 %
1456 */
1457 MagickExport void *GetBlobStreamData(const Image *image)
1458 {
1459   assert(image != (const Image *) NULL);
1460   assert(image->signature == MagickCoreSignature);
1461   return(image->blob->data);
1462 }
1463 \f
1464 /*
1465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466 %                                                                             %
1467 %                                                                             %
1468 %                                                                             %
1469 +   G e t B l o b S t r e a m H a n d l e r                                   %
1470 %                                                                             %
1471 %                                                                             %
1472 %                                                                             %
1473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474 %
1475 %  GetBlobStreamHandler() returns the stream handler for the image.
1476 %
1477 %  The format of the GetBlobStreamHandler method is:
1478 %
1479 %      StreamHandler GetBlobStreamHandler(const Image *image)
1480 %
1481 %  A description of each parameter follows:
1482 %
1483 %    o image: the image.
1484 %
1485 */
1486 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1487 {
1488   assert(image != (const Image *) NULL);
1489   assert(image->signature == MagickCoreSignature);
1490   if (image->debug != MagickFalse)
1491     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1492   return(image->blob->stream);
1493 }
1494 \f
1495 /*
1496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497 %                                                                             %
1498 %                                                                             %
1499 %                                                                             %
1500 %   I m a g e T o B l o b                                                     %
1501 %                                                                             %
1502 %                                                                             %
1503 %                                                                             %
1504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505 %
1506 %  ImageToBlob() implements direct to memory image formats.  It returns the
1507 %  image as a formatted blob and its length.  The magick member of the Image
1508 %  structure determines the format of the returned blob (GIF, JPEG, PNG,
1509 %  etc.).  This method is the equivalent of WriteImage(), but writes the
1510 %  formatted "file" to a memory buffer rather than to an actual file.
1511 %
1512 %  The format of the ImageToBlob method is:
1513 %
1514 %      void *ImageToBlob(const ImageInfo *image_info,Image *image,
1515 %        size_t *length,ExceptionInfo *exception)
1516 %
1517 %  A description of each parameter follows:
1518 %
1519 %    o image_info: the image info.
1520 %
1521 %    o image: the image.
1522 %
1523 %    o length: return the actual length of the blob.
1524 %
1525 %    o exception: return any errors or warnings in this structure.
1526 %
1527 */
1528 MagickExport void *ImageToBlob(const ImageInfo *image_info,
1529   Image *image,size_t *length,ExceptionInfo *exception)
1530 {
1531   const MagickInfo
1532     *magick_info;
1533
1534   ImageInfo
1535     *blob_info;
1536
1537   MagickBooleanType
1538     status;
1539
1540   void
1541     *blob;
1542
1543   assert(image_info != (const ImageInfo *) NULL);
1544   assert(image_info->signature == MagickCoreSignature);
1545   if (image_info->debug != MagickFalse)
1546     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1547       image_info->filename);
1548   assert(image != (Image *) NULL);
1549   assert(image->signature == MagickCoreSignature);
1550   assert(exception != (ExceptionInfo *) NULL);
1551   *length=0;
1552   blob=(unsigned char *) NULL;
1553   blob_info=CloneImageInfo(image_info);
1554   blob_info->adjoin=MagickFalse;
1555   (void) SetImageInfo(blob_info,1,exception);
1556   if (*blob_info->magick != '\0')
1557     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1558   magick_info=GetMagickInfo(image->magick,exception);
1559   if (magick_info == (const MagickInfo *) NULL)
1560     {
1561       (void) ThrowMagickException(exception,GetMagickModule(),
1562         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1563         image->magick);
1564       blob_info=DestroyImageInfo(blob_info);
1565       return(blob);
1566     }
1567   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
1568   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1569     {
1570       /*
1571         Native blob support for this image format.
1572       */
1573       blob_info->length=0;
1574       blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
1575         sizeof(unsigned char));
1576       if (blob_info->blob == NULL)
1577         (void) ThrowMagickException(exception,GetMagickModule(),
1578           ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1579       else
1580         {
1581           (void) CloseBlob(image);
1582           image->blob->exempt=MagickTrue;
1583           *image->filename='\0';
1584           status=WriteImage(blob_info,image,exception);
1585           *length=image->blob->length;
1586           blob=DetachBlob(image->blob);
1587           if (status == MagickFalse)
1588             blob=RelinquishMagickMemory(blob);
1589           else
1590             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
1591         }
1592     }
1593   else
1594     {
1595       char
1596         unique[MagickPathExtent];
1597
1598       int
1599         file;
1600
1601       /*
1602         Write file to disk in blob image format.
1603       */
1604       file=AcquireUniqueFileResource(unique);
1605       if (file == -1)
1606         {
1607           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1608             image_info->filename);
1609         }
1610       else
1611         {
1612           blob_info->file=fdopen(file,"wb");
1613           if (blob_info->file != (FILE *) NULL)
1614             {
1615               (void) FormatLocaleString(image->filename,MagickPathExtent,
1616                 "%s:%s",image->magick,unique);
1617               status=WriteImage(blob_info,image,exception);
1618               (void) CloseBlob(image);
1619               (void) fclose(blob_info->file);
1620               if (status != MagickFalse)
1621                 blob=FileToBlob(unique,~0UL,length,exception);
1622             }
1623           (void) RelinquishUniqueFileResource(unique);
1624         }
1625     }
1626   blob_info=DestroyImageInfo(blob_info);
1627   return(blob);
1628 }
1629 \f
1630 /*
1631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1632 %                                                                             %
1633 %                                                                             %
1634 %                                                                             %
1635 +  I m a g e T o U s e r B l o b                                              %
1636 %                                                                             %
1637 %                                                                             %
1638 %                                                                             %
1639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1640 %
1641 %  ImageToUserBlob() is the equivalent of WriteImage(), but writes the
1642 %  formatted "file" to the suplied method rather than to an actual file.
1643 %
1644 %  The format of the ImageToUserBlob method is:
1645 %
1646 %      void ImageToUserBlob(const ImageInfo *image_info,Image *image,
1647 %        UserBlobInfo *user_info,ExceptionInfo *exception)
1648 %
1649 %  A description of each parameter follows:
1650 %
1651 %    o image_info: the image info.
1652 %
1653 %    o image: the image.
1654 %
1655 %    o user_info: the methods to use when writing and seeking.
1656 %
1657 %    o exception: return any errors or warnings in this structure.
1658 %
1659 */
1660 MagickExport void ImageToUserBlob(const ImageInfo *image_info,Image *image,
1661   UserBlobInfo *user_info,ExceptionInfo *exception)
1662 {
1663   const MagickInfo
1664     *magick_info;
1665
1666   ImageInfo
1667     *blob_info;
1668
1669   MagickBooleanType
1670     status;
1671
1672   assert(image_info != (const ImageInfo *) NULL);
1673   assert(image_info->signature == MagickCoreSignature);
1674   if (image_info->debug != MagickFalse)
1675     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1676       image_info->filename);
1677   assert(image != (Image *) NULL);
1678   assert(image->signature == MagickCoreSignature);
1679   assert(user_info != (UserBlobInfo *) NULL);
1680   assert(user_info->handler != (BlobHandler) NULL);
1681   assert(exception != (ExceptionInfo *) NULL);
1682   blob_info=CloneImageInfo(image_info);
1683   blob_info->adjoin=MagickFalse;
1684   blob_info->user_info=user_info;
1685   (void) SetImageInfo(blob_info,1,exception);
1686   if (*blob_info->magick != '\0')
1687     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1688   magick_info=GetMagickInfo(image->magick,exception);
1689   if (magick_info == (const MagickInfo *) NULL)
1690     {
1691       (void) ThrowMagickException(exception,GetMagickModule(),
1692         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1693         image->magick);
1694       blob_info=DestroyImageInfo(blob_info);
1695       return;
1696     }
1697   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
1698   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1699     {
1700       /*
1701         Native blob support for this image format.
1702       */
1703       (void) CloseBlob(image);
1704       *image->filename='\0';
1705       (void) WriteImage(blob_info,image,exception);
1706       (void) CloseBlob(image);
1707     }
1708   else
1709     {
1710       char
1711         unique[MagickPathExtent];
1712
1713       int
1714         file;
1715
1716       unsigned char
1717         *blob;
1718
1719       /*
1720         Write file to disk in blob image format.
1721       */
1722       blob_info->user_info=(UserBlobInfo *) NULL;
1723       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
1724         sizeof(*blob));
1725       if (blob == (unsigned char *) NULL)
1726         {
1727           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1728             image_info->filename);
1729           blob_info=DestroyImageInfo(blob_info);
1730           return;
1731         }
1732       file=AcquireUniqueFileResource(unique);
1733       if (file == -1)
1734         {
1735           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1736             image_info->filename);
1737           blob=(unsigned char *) RelinquishMagickMemory(blob);
1738           blob_info=DestroyImageInfo(blob_info);
1739           return;
1740         }
1741       blob_info->file=fdopen(file,"wb+");
1742       if (blob_info->file != (FILE *) NULL)
1743         {
1744           ssize_t
1745             count;
1746
1747           (void) FormatLocaleString(image->filename,MagickPathExtent,
1748             "%s:%s",image->magick,unique);
1749           status=WriteImage(blob_info,image,exception);
1750           (void) CloseBlob(image);
1751           if (status != MagickFalse)
1752             {
1753               (void) fseek(blob_info->file,0,SEEK_SET);
1754               count=(ssize_t) MagickMaxBufferExtent;
1755               while (count == (ssize_t) MagickMaxBufferExtent)
1756               {
1757                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
1758                   blob_info->file);
1759                 user_info->handler(blob,count,user_info->data);
1760               }
1761             }
1762           (void) fclose(blob_info->file);
1763         }
1764       blob=(unsigned char *) RelinquishMagickMemory(blob);
1765       (void) RelinquishUniqueFileResource(unique);
1766     }
1767   blob_info=DestroyImageInfo(blob_info);
1768 }
1769 \f
1770 /*
1771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1772 %                                                                             %
1773 %                                                                             %
1774 %                                                                             %
1775 %   I m a g e T o F i l e                                                     %
1776 %                                                                             %
1777 %                                                                             %
1778 %                                                                             %
1779 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1780 %
1781 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
1782 %  occurs otherwise MagickTrue.
1783 %
1784 %  The format of the ImageToFile method is:
1785 %
1786 %       MagickBooleanType ImageToFile(Image *image,char *filename,
1787 %         ExceptionInfo *exception)
1788 %
1789 %  A description of each parameter follows:
1790 %
1791 %    o image: the image.
1792 %
1793 %    o filename: Write the image to this file.
1794 %
1795 %    o exception: return any errors or warnings in this structure.
1796 %
1797 */
1798 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1799   ExceptionInfo *exception)
1800 {
1801   int
1802     file;
1803
1804   register const unsigned char
1805     *p;
1806
1807   register size_t
1808     i;
1809
1810   size_t
1811     length,
1812     quantum;
1813
1814   ssize_t
1815     count;
1816
1817   struct stat
1818     file_stats;
1819
1820   unsigned char
1821     *buffer;
1822
1823   assert(image != (Image *) NULL);
1824   assert(image->signature == MagickCoreSignature);
1825   assert(image->blob != (BlobInfo *) NULL);
1826   assert(image->blob->type != UndefinedStream);
1827   if (image->debug != MagickFalse)
1828     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1829   assert(filename != (const char *) NULL);
1830   if (*filename == '\0')
1831     file=AcquireUniqueFileResource(filename);
1832   else
1833     if (LocaleCompare(filename,"-") == 0)
1834       file=fileno(stdout);
1835     else
1836       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1837   if (file == -1)
1838     {
1839       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1840       return(MagickFalse);
1841     }
1842   quantum=(size_t) MagickMaxBufferExtent;
1843   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1844     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1845   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1846   if (buffer == (unsigned char *) NULL)
1847     {
1848       file=close(file)-1;
1849       (void) ThrowMagickException(exception,GetMagickModule(),
1850         ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1851       return(MagickFalse);
1852     }
1853   length=0;
1854   p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1855   for (i=0; count > 0; )
1856   {
1857     length=(size_t) count;
1858     for (i=0; i < length; i+=count)
1859     {
1860       count=write(file,p+i,(size_t) (length-i));
1861       if (count <= 0)
1862         {
1863           count=0;
1864           if (errno != EINTR)
1865             break;
1866         }
1867     }
1868     if (i < length)
1869       break;
1870     p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1871   }
1872   if (LocaleCompare(filename,"-") != 0)
1873     file=close(file);
1874   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1875   if ((file == -1) || (i < length))
1876     {
1877       if (file != -1)
1878         file=close(file);
1879       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1880       return(MagickFalse);
1881     }
1882   return(MagickTrue);
1883 }
1884 \f
1885 /*
1886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1887 %                                                                             %
1888 %                                                                             %
1889 %                                                                             %
1890 %   I m a g e s T o B l o b                                                   %
1891 %                                                                             %
1892 %                                                                             %
1893 %                                                                             %
1894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1895 %
1896 %  ImagesToBlob() implements direct to memory image formats.  It returns the
1897 %  image sequence as a blob and its length.  The magick member of the ImageInfo
1898 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
1899 %
1900 %  Note, some image formats do not permit multiple images to the same image
1901 %  stream (e.g. JPEG).  in this instance, just the first image of the
1902 %  sequence is returned as a blob.
1903 %
1904 %  The format of the ImagesToBlob method is:
1905 %
1906 %      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1907 %        size_t *length,ExceptionInfo *exception)
1908 %
1909 %  A description of each parameter follows:
1910 %
1911 %    o image_info: the image info.
1912 %
1913 %    o images: the image list.
1914 %
1915 %    o length: return the actual length of the blob.
1916 %
1917 %    o exception: return any errors or warnings in this structure.
1918 %
1919 */
1920 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1921   size_t *length,ExceptionInfo *exception)
1922 {
1923   const MagickInfo
1924     *magick_info;
1925
1926   ImageInfo
1927     *blob_info;
1928
1929   MagickBooleanType
1930     status;
1931
1932   void
1933     *blob;
1934
1935   assert(image_info != (const ImageInfo *) NULL);
1936   assert(image_info->signature == MagickCoreSignature);
1937   if (image_info->debug != MagickFalse)
1938     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1939       image_info->filename);
1940   assert(images != (Image *) NULL);
1941   assert(images->signature == MagickCoreSignature);
1942   assert(exception != (ExceptionInfo *) NULL);
1943   *length=0;
1944   blob=(unsigned char *) NULL;
1945   blob_info=CloneImageInfo(image_info);
1946   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1947     exception);
1948   if (*blob_info->magick != '\0')
1949     (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
1950   magick_info=GetMagickInfo(images->magick,exception);
1951   if (magick_info == (const MagickInfo *) NULL)
1952     {
1953       (void) ThrowMagickException(exception,GetMagickModule(),
1954         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1955         images->magick);
1956       blob_info=DestroyImageInfo(blob_info);
1957       return(blob);
1958     }
1959   if (GetMagickAdjoin(magick_info) == MagickFalse)
1960     {
1961       blob_info=DestroyImageInfo(blob_info);
1962       return(ImageToBlob(image_info,images,length,exception));
1963     }
1964   (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
1965   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1966     {
1967       /*
1968         Native blob support for this images format.
1969       */
1970       blob_info->length=0;
1971       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1972         sizeof(unsigned char));
1973       if (blob_info->blob == (void *) NULL)
1974         (void) ThrowMagickException(exception,GetMagickModule(),
1975           ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1976       else
1977         {
1978           (void) CloseBlob(images);
1979           images->blob->exempt=MagickTrue;
1980           *images->filename='\0';
1981           status=WriteImages(blob_info,images,images->filename,exception);
1982           *length=images->blob->length;
1983           blob=DetachBlob(images->blob);
1984           if (status == MagickFalse)
1985             blob=RelinquishMagickMemory(blob);
1986           else
1987             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
1988         }
1989     }
1990   else
1991     {
1992       char
1993         filename[MagickPathExtent],
1994         unique[MagickPathExtent];
1995
1996       int
1997         file;
1998
1999       /*
2000         Write file to disk in blob images format.
2001       */
2002       file=AcquireUniqueFileResource(unique);
2003       if (file == -1)
2004         {
2005           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2006             image_info->filename);
2007         }
2008       else
2009         {
2010           blob_info->file=fdopen(file,"wb");
2011           if (blob_info->file != (FILE *) NULL)
2012             {
2013               (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2014                 images->magick,unique);
2015               status=WriteImages(blob_info,images,filename,exception);
2016               (void) CloseBlob(images);
2017               (void) fclose(blob_info->file);
2018               if (status != MagickFalse)
2019                 blob=FileToBlob(unique,~0UL,length,exception);
2020             }
2021           (void) RelinquishUniqueFileResource(unique);
2022         }
2023     }
2024   blob_info=DestroyImageInfo(blob_info);
2025   return(blob);
2026 }
2027 \f
2028 /*
2029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2030 %                                                                             %
2031 %                                                                             %
2032 %                                                                             %
2033 +  I m a g e s T o U s e r B l o b                                            %
2034 %                                                                             %
2035 %                                                                             %
2036 %                                                                             %
2037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2038 %
2039 %  ImagesToUserBlob() is the equivalent of WriteImages(), but writes the
2040 %  formatted "file" to the suplied method rather than to an actual file.
2041 %
2042 %  The format of the ImageToUserBlob method is:
2043 %
2044 %      void ImagesToUserBlob(const ImageInfo *image_info,Image *images,
2045 %        UserBlobInfo *user_info,ExceptionInfo *exception)
2046 %
2047 %  A description of each parameter follows:
2048 %
2049 %    o image_info: the image info.
2050 %
2051 %    o images: the image list.
2052 %
2053 %    o user_info: the methods to use when writing and seeking.
2054 %
2055 %    o exception: return any errors or warnings in this structure.
2056 %
2057 */
2058 MagickExport void ImagesToUserBlob(const ImageInfo *image_info,Image *images,
2059   UserBlobInfo *user_info,ExceptionInfo *exception)
2060 {
2061   const MagickInfo
2062     *magick_info;
2063
2064   ImageInfo
2065     *blob_info;
2066
2067   MagickBooleanType
2068     status;
2069
2070   assert(image_info != (const ImageInfo *) NULL);
2071   assert(image_info->signature == MagickCoreSignature);
2072   if (image_info->debug != MagickFalse)
2073     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2074       image_info->filename);
2075   assert(images != (Image *) NULL);
2076   assert(images->signature == MagickCoreSignature);
2077   assert(user_info != (UserBlobInfo *) NULL);
2078   assert(user_info->handler != (BlobHandler) NULL);
2079   assert(exception != (ExceptionInfo *) NULL);
2080   blob_info=CloneImageInfo(image_info);
2081   blob_info->adjoin=MagickFalse;
2082   blob_info->user_info=user_info;
2083   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2084     exception);
2085   if (*blob_info->magick != '\0')
2086     (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2087   magick_info=GetMagickInfo(images->magick,exception);
2088   if (magick_info == (const MagickInfo *) NULL)
2089     {
2090       (void) ThrowMagickException(exception,GetMagickModule(),
2091         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2092         images->magick);
2093       blob_info=DestroyImageInfo(blob_info);
2094       return;
2095     }
2096   (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2097   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2098     {
2099       /*
2100         Native blob support for this image format.
2101       */
2102       (void) CloseBlob(images);
2103       *images->filename='\0';
2104       (void) WriteImages(blob_info,images,images->filename,exception);
2105       (void) CloseBlob(images);
2106     }
2107   else
2108     {
2109       char
2110         filename[MagickPathExtent],
2111         unique[MagickPathExtent];
2112
2113       int
2114         file;
2115
2116       unsigned char
2117         *blob;
2118
2119       /*
2120         Write file to disk in blob image format.
2121       */
2122       blob_info->user_info=(UserBlobInfo *) NULL;
2123       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2124         sizeof(*blob));
2125       if (blob == (unsigned char *) NULL)
2126         {
2127           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2128             image_info->filename);
2129           blob_info=DestroyImageInfo(blob_info);
2130           return;
2131         }
2132       file=AcquireUniqueFileResource(unique);
2133       if (file == -1)
2134         {
2135           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2136             image_info->filename);
2137           blob=(unsigned char *) RelinquishMagickMemory(blob);
2138           blob_info=DestroyImageInfo(blob_info);
2139           return;
2140         }
2141       blob_info->file=fdopen(file,"wb+");
2142       if (blob_info->file != (FILE *) NULL)
2143         {
2144           ssize_t
2145             count;
2146
2147           (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2148             images->magick,unique);
2149           status=WriteImages(blob_info,images,filename,exception);
2150           (void) CloseBlob(images);
2151           if (status != MagickFalse)
2152             {
2153               (void) fseek(blob_info->file,0,SEEK_SET);
2154               count=(ssize_t) MagickMaxBufferExtent;
2155               while (count == (ssize_t) MagickMaxBufferExtent)
2156               {
2157                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2158                   blob_info->file);
2159                 user_info->handler(blob,count,user_info->data);
2160               }
2161             }
2162           (void) fclose(blob_info->file);
2163         }
2164       blob=(unsigned char *) RelinquishMagickMemory(blob);
2165       (void) RelinquishUniqueFileResource(unique);
2166     }
2167   blob_info=DestroyImageInfo(blob_info);
2168   return;
2169 }
2170 \f
2171 /*
2172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2173 %                                                                             %
2174 %                                                                             %
2175 %                                                                             %
2176 %   I n j e c t I m a g e B l o b                                             %
2177 %                                                                             %
2178 %                                                                             %
2179 %                                                                             %
2180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2181 %
2182 %  InjectImageBlob() injects the image with a copy of itself in the specified
2183 %  format (e.g. inject JPEG into a PDF image).
2184 %
2185 %  The format of the InjectImageBlob method is:
2186 %
2187 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2188 %        Image *image,Image *inject_image,const char *format,
2189 %        ExceptionInfo *exception)
2190 %
2191 %  A description of each parameter follows:
2192 %
2193 %    o image_info: the image info..
2194 %
2195 %    o image: the image.
2196 %
2197 %    o inject_image: inject into the image stream.
2198 %
2199 %    o format: the image format.
2200 %
2201 %    o exception: return any errors or warnings in this structure.
2202 %
2203 */
2204 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2205   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2206 {
2207   char
2208     filename[MagickPathExtent];
2209
2210   FILE
2211     *unique_file;
2212
2213   Image
2214     *byte_image;
2215
2216   ImageInfo
2217     *write_info;
2218
2219   int
2220     file;
2221
2222   MagickBooleanType
2223     status;
2224
2225   register ssize_t
2226     i;
2227
2228   size_t
2229     quantum;
2230
2231   ssize_t
2232     count;
2233
2234   struct stat
2235     file_stats;
2236
2237   unsigned char
2238     *buffer;
2239
2240   /*
2241     Write inject image to a temporary file.
2242   */
2243   assert(image_info != (ImageInfo *) NULL);
2244   assert(image_info->signature == MagickCoreSignature);
2245   assert(image != (Image *) NULL);
2246   assert(image->signature == MagickCoreSignature);
2247   if (image->debug != MagickFalse)
2248     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2249   assert(inject_image != (Image *) NULL);
2250   assert(inject_image->signature == MagickCoreSignature);
2251   assert(exception != (ExceptionInfo *) NULL);
2252   unique_file=(FILE *) NULL;
2253   file=AcquireUniqueFileResource(filename);
2254   if (file != -1)
2255     unique_file=fdopen(file,"wb");
2256   if ((file == -1) || (unique_file == (FILE *) NULL))
2257     {
2258       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2259       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2260         image->filename);
2261       return(MagickFalse);
2262     }
2263   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2264   if (byte_image == (Image *) NULL)
2265     {
2266       (void) fclose(unique_file);
2267       (void) RelinquishUniqueFileResource(filename);
2268       return(MagickFalse);
2269     }
2270   (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",format,
2271     filename);
2272   DestroyBlob(byte_image);
2273   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2274   write_info=CloneImageInfo(image_info);
2275   SetImageInfoFile(write_info,unique_file);
2276   status=WriteImage(write_info,byte_image,exception);
2277   write_info=DestroyImageInfo(write_info);
2278   byte_image=DestroyImage(byte_image);
2279   (void) fclose(unique_file);
2280   if (status == MagickFalse)
2281     {
2282       (void) RelinquishUniqueFileResource(filename);
2283       return(MagickFalse);
2284     }
2285   /*
2286     Inject into image stream.
2287   */
2288   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2289   if (file == -1)
2290     {
2291       (void) RelinquishUniqueFileResource(filename);
2292       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2293         image_info->filename);
2294       return(MagickFalse);
2295     }
2296   quantum=(size_t) MagickMaxBufferExtent;
2297   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2298     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2299   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2300   if (buffer == (unsigned char *) NULL)
2301     {
2302       (void) RelinquishUniqueFileResource(filename);
2303       file=close(file);
2304       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2305         image->filename);
2306     }
2307   for (i=0; ; i+=count)
2308   {
2309     count=read(file,buffer,quantum);
2310     if (count <= 0)
2311       {
2312         count=0;
2313         if (errno != EINTR)
2314           break;
2315       }
2316     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2317       MagickFalse;
2318   }
2319   file=close(file);
2320   if (file == -1)
2321     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2322   (void) RelinquishUniqueFileResource(filename);
2323   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2324   return(status);
2325 }
2326 \f
2327 /*
2328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2329 %                                                                             %
2330 %                                                                             %
2331 %                                                                             %
2332 %   I s B l o b E x e m p t                                                   %
2333 %                                                                             %
2334 %                                                                             %
2335 %                                                                             %
2336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2337 %
2338 %  IsBlobExempt() returns true if the blob is exempt.
2339 %
2340 %  The format of the IsBlobExempt method is:
2341 %
2342 %       MagickBooleanType IsBlobExempt(const Image *image)
2343 %
2344 %  A description of each parameter follows:
2345 %
2346 %    o image: the image.
2347 %
2348 */
2349 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2350 {
2351   assert(image != (const Image *) NULL);
2352   assert(image->signature == MagickCoreSignature);
2353   if (image->debug != MagickFalse)
2354     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2355   return(image->blob->exempt);
2356 }
2357 \f
2358 /*
2359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2360 %                                                                             %
2361 %                                                                             %
2362 %                                                                             %
2363 %   I s B l o b S e e k a b l e                                               %
2364 %                                                                             %
2365 %                                                                             %
2366 %                                                                             %
2367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2368 %
2369 %  IsBlobSeekable() returns true if the blob is seekable.
2370 %
2371 %  The format of the IsBlobSeekable method is:
2372 %
2373 %       MagickBooleanType IsBlobSeekable(const Image *image)
2374 %
2375 %  A description of each parameter follows:
2376 %
2377 %    o image: the image.
2378 %
2379 */
2380 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2381 {
2382   MagickBooleanType
2383     seekable;
2384
2385   assert(image != (const Image *) NULL);
2386   assert(image->signature == MagickCoreSignature);
2387   if (image->debug != MagickFalse)
2388     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2389   switch (image->blob->type)
2390   {
2391     case FileStream:
2392     case BlobStream:
2393     case ZipStream:
2394     {
2395       seekable=MagickTrue;
2396       break;
2397     }
2398     case UndefinedStream:
2399     case StandardStream:
2400     case BZipStream:
2401     case FifoStream:
2402     case PipeStream:
2403     default:
2404     {
2405       seekable=MagickFalse;
2406       break;
2407     }
2408     case UserStream:
2409     {
2410       if ((image->blob->user_info->seeker != (BlobSeeker) NULL) &&
2411           (image->blob->user_info->teller != (BlobTeller) NULL))
2412         seekable=MagickTrue;
2413       else
2414         seekable=MagickFalse;
2415       break;
2416     }
2417   }
2418   return(seekable);
2419 }
2420 \f
2421 /*
2422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2423 %                                                                             %
2424 %                                                                             %
2425 %                                                                             %
2426 %   I s B l o b T e m p o r a r y                                             %
2427 %                                                                             %
2428 %                                                                             %
2429 %                                                                             %
2430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2431 %
2432 %  IsBlobTemporary() returns true if the blob is temporary.
2433 %
2434 %  The format of the IsBlobTemporary method is:
2435 %
2436 %       MagickBooleanType IsBlobTemporary(const Image *image)
2437 %
2438 %  A description of each parameter follows:
2439 %
2440 %    o image: the image.
2441 %
2442 */
2443 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2444 {
2445   assert(image != (const Image *) NULL);
2446   assert(image->signature == MagickCoreSignature);
2447   if (image->debug != MagickFalse)
2448     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2449   return(image->blob->temporary);
2450 }
2451 \f
2452 /*
2453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2454 %                                                                             %
2455 %                                                                             %
2456 %                                                                             %
2457 +  M a p B l o b                                                              %
2458 %                                                                             %
2459 %                                                                             %
2460 %                                                                             %
2461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2462 %
2463 %  MapBlob() creates a mapping from a file to a binary large object.
2464 %
2465 %  The format of the MapBlob method is:
2466 %
2467 %      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2468 %        const size_t length)
2469 %
2470 %  A description of each parameter follows:
2471 %
2472 %    o file: map this file descriptor.
2473 %
2474 %    o mode: ReadMode, WriteMode, or IOMode.
2475 %
2476 %    o offset: starting at this offset within the file.
2477 %
2478 %    o length: the length of the mapping is returned in this pointer.
2479 %
2480 */
2481 MagickExport void *MapBlob(int file,const MapMode mode,
2482   const MagickOffsetType offset,const size_t length)
2483 {
2484 #if defined(MAGICKCORE_HAVE_MMAP)
2485   int
2486     flags,
2487     protection;
2488
2489   void
2490     *map;
2491
2492   /*
2493     Map file.
2494   */
2495   flags=0;
2496   if (file == -1)
2497 #if defined(MAP_ANONYMOUS)
2498     flags|=MAP_ANONYMOUS;
2499 #else
2500     return(NULL);
2501 #endif
2502   switch (mode)
2503   {
2504     case ReadMode:
2505     default:
2506     {
2507       protection=PROT_READ;
2508       flags|=MAP_PRIVATE;
2509       break;
2510     }
2511     case WriteMode:
2512     {
2513       protection=PROT_WRITE;
2514       flags|=MAP_SHARED;
2515       break;
2516     }
2517     case IOMode:
2518     {
2519       protection=PROT_READ | PROT_WRITE;
2520       flags|=MAP_SHARED;
2521       break;
2522     }
2523   }
2524 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2525   map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2526 #else
2527   map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
2528     offset);
2529   if (map == MAP_FAILED)
2530     map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2531 #endif
2532   if (map == MAP_FAILED)
2533     return(NULL);
2534   return(map);
2535 #else
2536   (void) file;
2537   (void) mode;
2538   (void) offset;
2539   (void) length;
2540   return(NULL);
2541 #endif
2542 }
2543 \f
2544 /*
2545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2546 %                                                                             %
2547 %                                                                             %
2548 %                                                                             %
2549 +  M S B O r d e r L o n g                                                    %
2550 %                                                                             %
2551 %                                                                             %
2552 %                                                                             %
2553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2554 %
2555 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
2556 %  most-significant byte first.
2557 %
2558 %  The format of the MSBOrderLong method is:
2559 %
2560 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
2561 %
2562 %  A description of each parameter follows.
2563 %
2564 %   o  buffer:  Specifies a pointer to a buffer of integers.
2565 %
2566 %   o  length:  Specifies the length of the buffer.
2567 %
2568 */
2569 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2570 {
2571   int
2572     c;
2573
2574   register unsigned char
2575     *p,
2576     *q;
2577
2578   assert(buffer != (unsigned char *) NULL);
2579   q=buffer+length;
2580   while (buffer < q)
2581   {
2582     p=buffer+3;
2583     c=(int) (*p);
2584     *p=(*buffer);
2585     *buffer++=(unsigned char) c;
2586     p=buffer+1;
2587     c=(int) (*p);
2588     *p=(*buffer);
2589     *buffer++=(unsigned char) c;
2590     buffer+=2;
2591   }
2592 }
2593 \f
2594 /*
2595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2596 %                                                                             %
2597 %                                                                             %
2598 %                                                                             %
2599 +  M S B O r d e r S h o r t                                                  %
2600 %                                                                             %
2601 %                                                                             %
2602 %                                                                             %
2603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2604 %
2605 %  MSBOrderShort() converts a least-significant byte first buffer of integers
2606 %  to most-significant byte first.
2607 %
2608 %  The format of the MSBOrderShort method is:
2609 %
2610 %      void MSBOrderShort(unsigned char *p,const size_t length)
2611 %
2612 %  A description of each parameter follows.
2613 %
2614 %   o  p:  Specifies a pointer to a buffer of integers.
2615 %
2616 %   o  length:  Specifies the length of the buffer.
2617 %
2618 */
2619 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2620 {
2621   int
2622     c;
2623
2624   register unsigned char
2625     *q;
2626
2627   assert(p != (unsigned char *) NULL);
2628   q=p+length;
2629   while (p < q)
2630   {
2631     c=(int) (*p);
2632     *p=(*(p+1));
2633     p++;
2634     *p++=(unsigned char) c;
2635   }
2636 }
2637 \f
2638 /*
2639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2640 %                                                                             %
2641 %                                                                             %
2642 %                                                                             %
2643 +   O p e n B l o b                                                           %
2644 %                                                                             %
2645 %                                                                             %
2646 %                                                                             %
2647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2648 %
2649 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
2650 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
2651 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2652 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
2653 %  from a system command.
2654 %
2655 %  The format of the OpenBlob method is:
2656 %
2657 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2658 %        const BlobMode mode,ExceptionInfo *exception)
2659 %
2660 %  A description of each parameter follows:
2661 %
2662 %    o image_info: the image info.
2663 %
2664 %    o image: the image.
2665 %
2666 %    o mode: the mode for opening the file.
2667 %
2668 */
2669
2670 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2671   Image *image)
2672 {
2673   const char
2674     *option;
2675
2676   int
2677     status;
2678
2679   size_t
2680     size;
2681
2682   size=16384;
2683   option=GetImageOption(image_info,"stream:buffer-size");
2684   if (option != (const char *) NULL)
2685     size=StringToUnsignedLong(option);
2686   status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2687     _IONBF : _IOFBF,size);
2688   return(status == 0 ? MagickTrue : MagickFalse);
2689 }
2690
2691 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2692   Image *image,const BlobMode mode,ExceptionInfo *exception)
2693 {
2694   char
2695     extension[MagickPathExtent],
2696     filename[MagickPathExtent];
2697
2698   const char
2699     *type;
2700
2701   MagickBooleanType
2702     status;
2703
2704   PolicyRights
2705     rights;
2706
2707   assert(image_info != (ImageInfo *) NULL);
2708   assert(image_info->signature == MagickCoreSignature);
2709   if (image_info->debug != MagickFalse)
2710     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2711       image_info->filename);
2712   assert(image != (Image *) NULL);
2713   assert(image->signature == MagickCoreSignature);
2714   if (image_info->blob != (void *) NULL)
2715     {
2716       if (image_info->stream != (StreamHandler) NULL)
2717         image->blob->stream=(StreamHandler) image_info->stream;
2718       AttachBlob(image->blob,image_info->blob,image_info->length);
2719       return(MagickTrue);
2720     }
2721   if (image_info->user_info != (UserBlobInfo *) NULL)
2722     {
2723       image->blob->type=UserStream;
2724       image->blob->user_info=image_info->user_info;
2725       return(MagickTrue);
2726     }
2727   (void) DetachBlob(image->blob);
2728   switch (mode)
2729   {
2730     default: type="r"; break;
2731     case ReadBlobMode: type="r"; break;
2732     case ReadBinaryBlobMode: type="rb"; break;
2733     case WriteBlobMode: type="w"; break;
2734     case WriteBinaryBlobMode: type="w+b"; break;
2735     case AppendBlobMode: type="a"; break;
2736     case AppendBinaryBlobMode: type="a+b"; break;
2737   }
2738   if (*type != 'r')
2739     image->blob->synchronize=image_info->synchronize;
2740   if (image_info->stream != (StreamHandler) NULL)
2741     {
2742       image->blob->stream=(StreamHandler) image_info->stream;
2743       if (*type == 'w')
2744         {
2745           image->blob->type=FifoStream;
2746           return(MagickTrue);
2747         }
2748     }
2749   /*
2750     Open image file.
2751   */
2752   *filename='\0';
2753   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2754   rights=ReadPolicyRights;
2755   if (*type == 'w')
2756     rights=WritePolicyRights;
2757   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2758     {
2759       errno=EPERM;
2760       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2761         "NotAuthorized","`%s'",filename);
2762       return(MagickFalse);
2763     }
2764   if ((LocaleCompare(filename,"-") == 0) ||
2765       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2766     {
2767       image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2768 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2769       if (strchr(type,'b') != (char *) NULL)
2770         setmode(fileno(image->blob->file_info.file),_O_BINARY);
2771 #endif
2772       image->blob->type=StandardStream;
2773       image->blob->exempt=MagickTrue;
2774       return(SetStreamBuffering(image_info,image));
2775     }
2776   if (LocaleNCompare(filename,"fd:",3) == 0)
2777     {
2778       char
2779         fileMode[MagickPathExtent];
2780
2781       *fileMode =(*type);
2782       fileMode[1]='\0';
2783       image->blob->file_info.file=fdopen(StringToLong(filename+3),fileMode);
2784 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2785       if (strchr(type,'b') != (char *) NULL)
2786         setmode(fileno(image->blob->file_info.file),_O_BINARY);
2787 #endif
2788       image->blob->type=StandardStream;
2789       image->blob->exempt=MagickTrue;
2790       return(SetStreamBuffering(image_info,image));
2791     }
2792 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
2793   if (*filename == '|')
2794     {
2795       char
2796         fileMode[MagickPathExtent],
2797         *sanitize_command;
2798
2799       /*
2800         Pipe image to or from a system command.
2801       */
2802 #if defined(SIGPIPE)
2803       if (*type == 'w')
2804         (void) signal(SIGPIPE,SIG_IGN);
2805 #endif
2806       *fileMode =(*type);
2807       fileMode[1]='\0';
2808       sanitize_command=SanitizeString(filename+1);
2809       image->blob->file_info.file=(FILE *) popen_utf8(sanitize_command,
2810         fileMode);
2811       sanitize_command=DestroyString(sanitize_command);
2812       if (image->blob->file_info.file == (FILE *) NULL)
2813         {
2814           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2815           return(MagickFalse);
2816         }
2817       image->blob->type=PipeStream;
2818       image->blob->exempt=MagickTrue;
2819       return(SetStreamBuffering(image_info,image));
2820     }
2821 #endif
2822   status=GetPathAttributes(filename,&image->blob->properties);
2823 #if defined(S_ISFIFO)
2824   if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
2825     {
2826       image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2827       if (image->blob->file_info.file == (FILE *) NULL)
2828         {
2829           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2830           return(MagickFalse);
2831         }
2832       image->blob->type=FileStream;
2833       image->blob->exempt=MagickTrue;
2834       return(SetStreamBuffering(image_info,image));
2835     }
2836 #endif
2837   GetPathComponent(image->filename,ExtensionPath,extension);
2838   if (*type == 'w')
2839     {
2840       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2841       if ((image_info->adjoin == MagickFalse) ||
2842           (strchr(filename,'%') != (char *) NULL))
2843         {
2844           /*
2845             Form filename for multi-part images.
2846           */
2847           (void) InterpretImageFilename(image_info,image,image->filename,(int)
2848             image->scene,filename,exception);
2849           if ((LocaleCompare(filename,image->filename) == 0) &&
2850               ((GetPreviousImageInList(image) != (Image *) NULL) ||
2851                (GetNextImageInList(image) != (Image *) NULL)))
2852             {
2853               char
2854                 path[MagickPathExtent];
2855
2856               GetPathComponent(image->filename,RootPath,path);
2857               if (*extension == '\0')
2858                 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
2859                   path,(double) image->scene);
2860               else
2861                 (void) FormatLocaleString(filename,MagickPathExtent,
2862                   "%s-%.20g.%s",path,(double) image->scene,extension);
2863             }
2864           (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2865 #if defined(macintosh)
2866           SetApplicationType(filename,image_info->magick,'8BIM');
2867 #endif
2868         }
2869     }
2870   if (image_info->file != (FILE *) NULL)
2871     {
2872       image->blob->file_info.file=image_info->file;
2873       image->blob->type=FileStream;
2874       image->blob->exempt=MagickTrue;
2875     }
2876   else
2877     if (*type == 'r')
2878       {
2879         image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2880         if (image->blob->file_info.file != (FILE *) NULL)
2881           {
2882             size_t
2883               count;
2884
2885             unsigned char
2886               magick[3];
2887
2888             image->blob->type=FileStream;
2889             (void) SetStreamBuffering(image_info,image);
2890             (void) ResetMagickMemory(magick,0,sizeof(magick));
2891             count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2892             (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
2893 #if defined(MAGICKCORE_POSIX_SUPPORT)
2894             (void) fflush(image->blob->file_info.file);
2895 #endif
2896             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2897                "  read %.20g magic header bytes",(double) count);
2898 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2899             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2900                 ((int) magick[2] == 0x08))
2901               {
2902                 if (image->blob->file_info.file != (FILE *) NULL)
2903                   (void) fclose(image->blob->file_info.file);
2904                 image->blob->file_info.file=(FILE *) NULL;
2905                 image->blob->file_info.gzfile=gzopen(filename,type);
2906                 if (image->blob->file_info.gzfile != (gzFile) NULL)
2907                   image->blob->type=ZipStream;
2908                }
2909 #endif
2910 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2911             if (strncmp((char *) magick,"BZh",3) == 0)
2912               {
2913                 if (image->blob->file_info.file != (FILE *) NULL)
2914                   (void) fclose(image->blob->file_info.file);
2915                 image->blob->file_info.file=(FILE *) NULL;
2916                 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2917                 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2918                   image->blob->type=BZipStream;
2919               }
2920 #endif
2921             if (image->blob->type == FileStream)
2922               {
2923                 const MagickInfo
2924                   *magick_info;
2925
2926                 ExceptionInfo
2927                   *sans_exception;
2928
2929                 size_t
2930                   length;
2931
2932                 sans_exception=AcquireExceptionInfo();
2933                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2934                 sans_exception=DestroyExceptionInfo(sans_exception);
2935                 length=(size_t) image->blob->properties.st_size;
2936                 if ((magick_info != (const MagickInfo *) NULL) &&
2937                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2938                     (length > MagickMaxBufferExtent) &&
2939                     (AcquireMagickResource(MapResource,length) != MagickFalse))
2940                   {
2941                     void
2942                       *blob;
2943
2944                     blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2945                       length);
2946                     if (blob == (void *) NULL)
2947                       RelinquishMagickResource(MapResource,length);
2948                     else
2949                       {
2950                         /*
2951                           Format supports blobs-- use memory-mapped I/O.
2952                         */
2953                         if (image_info->file != (FILE *) NULL)
2954                           image->blob->exempt=MagickFalse;
2955                         else
2956                           {
2957                             (void) fclose(image->blob->file_info.file);
2958                             image->blob->file_info.file=(FILE *) NULL;
2959                           }
2960                         AttachBlob(image->blob,blob,length);
2961                         image->blob->mapped=MagickTrue;
2962                       }
2963                   }
2964               }
2965           }
2966         }
2967       else
2968 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2969         if ((LocaleCompare(extension,"Z") == 0) ||
2970             (LocaleCompare(extension,"gz") == 0) ||
2971             (LocaleCompare(extension,"wmz") == 0) ||
2972             (LocaleCompare(extension,"svgz") == 0))
2973           {
2974             if (mode == WriteBinaryBlobMode)
2975               type="wb";
2976             image->blob->file_info.gzfile=gzopen(filename,type);
2977             if (image->blob->file_info.gzfile != (gzFile) NULL)
2978               image->blob->type=ZipStream;
2979           }
2980         else
2981 #endif
2982 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2983           if (LocaleCompare(extension,"bz2") == 0)
2984             {
2985               image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2986               if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2987                 image->blob->type=BZipStream;
2988             }
2989           else
2990 #endif
2991             {
2992               image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2993               if (image->blob->file_info.file != (FILE *) NULL)
2994                 {
2995                   image->blob->type=FileStream;
2996                   (void) SetStreamBuffering(image_info,image);
2997                 }
2998        }
2999   image->blob->status=MagickFalse;
3000   if (image->blob->type != UndefinedStream)
3001     image->blob->size=GetBlobSize(image);
3002   else
3003     {
3004       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3005       return(MagickFalse);
3006     }
3007   return(MagickTrue);
3008 }
3009 \f
3010 /*
3011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3012 %                                                                             %
3013 %                                                                             %
3014 %                                                                             %
3015 +   P i n g B l o b                                                           %
3016 %                                                                             %
3017 %                                                                             %
3018 %                                                                             %
3019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3020 %
3021 %  PingBlob() returns all the attributes of an image or image sequence except
3022 %  for the pixels.  It is much faster and consumes far less memory than
3023 %  BlobToImage().  On failure, a NULL image is returned and exception
3024 %  describes the reason for the failure.
3025 %
3026 %  The format of the PingBlob method is:
3027 %
3028 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
3029 %        const size_t length,ExceptionInfo *exception)
3030 %
3031 %  A description of each parameter follows:
3032 %
3033 %    o image_info: the image info.
3034 %
3035 %    o blob: the address of a character stream in one of the image formats
3036 %      understood by ImageMagick.
3037 %
3038 %    o length: This size_t integer reflects the length in bytes of the blob.
3039 %
3040 %    o exception: return any errors or warnings in this structure.
3041 %
3042 */
3043
3044 #if defined(__cplusplus) || defined(c_plusplus)
3045 extern "C" {
3046 #endif
3047
3048 static size_t PingStream(const Image *magick_unused(image),
3049   const void *magick_unused(pixels),const size_t columns)
3050 {
3051   magick_unreferenced(image);
3052   magick_unreferenced(pixels);
3053   return(columns);
3054 }
3055
3056 #if defined(__cplusplus) || defined(c_plusplus)
3057 }
3058 #endif
3059
3060 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3061   const size_t length,ExceptionInfo *exception)
3062 {
3063   Image
3064     *image;
3065
3066   ImageInfo
3067     *ping_info;
3068
3069   assert(image_info != (ImageInfo *) NULL);
3070   assert(image_info->signature == MagickCoreSignature);
3071   if (image_info->debug != MagickFalse)
3072     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3073       image_info->filename);
3074   assert(exception != (ExceptionInfo *) NULL);
3075   if ((blob == (const void *) NULL) || (length == 0))
3076     {
3077       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3078         "UnrecognizedImageFormat","`%s'",image_info->magick);
3079       return((Image *) NULL);
3080     }
3081   ping_info=CloneImageInfo(image_info);
3082   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
3083   if (ping_info->blob == (const void *) NULL)
3084     {
3085       (void) ThrowMagickException(exception,GetMagickModule(),
3086         ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
3087       return((Image *) NULL);
3088     }
3089   (void) memcpy(ping_info->blob,blob,length);
3090   ping_info->length=length;
3091   ping_info->ping=MagickTrue;
3092   image=ReadStream(ping_info,&PingStream,exception);
3093   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
3094   ping_info=DestroyImageInfo(ping_info);
3095   return(image);
3096 }
3097 \f
3098 /*
3099 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3100 %                                                                             %
3101 %                                                                             %
3102 %                                                                             %
3103 +  R e a d B l o b                                                            %
3104 %                                                                             %
3105 %                                                                             %
3106 %                                                                             %
3107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3108 %
3109 %  ReadBlob() reads data from the blob or image file and returns it.  It
3110 %  returns the number of bytes read. If length is zero, ReadBlob() returns
3111 %  zero and has no other results. If length is greater than SSIZE_MAX, the
3112 %  result is unspecified.
3113 %
3114 %  The format of the ReadBlob method is:
3115 %
3116 %      ssize_t ReadBlob(Image *image,const size_t length,void *data)
3117 %
3118 %  A description of each parameter follows:
3119 %
3120 %    o image: the image.
3121 %
3122 %    o length:  Specifies an integer representing the number of bytes to read
3123 %      from the file.
3124 %
3125 %    o data:  Specifies an area to place the information requested from the
3126 %      file.
3127 %
3128 */
3129 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3130 {
3131   int
3132     c;
3133
3134   register unsigned char
3135     *q;
3136
3137   ssize_t
3138     count;
3139
3140   assert(image != (Image *) NULL);
3141   assert(image->signature == MagickCoreSignature);
3142   assert(image->blob != (BlobInfo *) NULL);
3143   assert(image->blob->type != UndefinedStream);
3144   if (length == 0)
3145     return(0);
3146   assert(data != (void *) NULL);
3147   count=0;
3148   q=(unsigned char *) data;
3149   switch (image->blob->type)
3150   {
3151     case UndefinedStream:
3152       break;
3153     case StandardStream:
3154     case FileStream:
3155     case PipeStream:
3156     {
3157       switch (length)
3158       {
3159         default:
3160         {
3161           count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
3162           break;
3163         }
3164         case 4:
3165         {
3166           c=getc(image->blob->file_info.file);
3167           if (c == EOF)
3168             break;
3169           *q++=(unsigned char) c;
3170           count++;
3171         }
3172         case 3:
3173         {
3174           c=getc(image->blob->file_info.file);
3175           if (c == EOF)
3176             break;
3177           *q++=(unsigned char) c;
3178           count++;
3179         }
3180         case 2:
3181         {
3182           c=getc(image->blob->file_info.file);
3183           if (c == EOF)
3184             break;
3185           *q++=(unsigned char) c;
3186           count++;
3187         }
3188         case 1:
3189         {
3190           c=getc(image->blob->file_info.file);
3191           if (c == EOF)
3192             break;
3193           *q++=(unsigned char) c;
3194           count++;
3195         }
3196         case 0:
3197           break;
3198       }
3199       break;
3200     }
3201     case ZipStream:
3202     {
3203 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3204       switch (length)
3205       {
3206         default:
3207         {
3208           count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
3209             (unsigned int) length);
3210           break;
3211         }
3212         case 4:
3213         {
3214           c=gzgetc(image->blob->file_info.gzfile);
3215           if (c == EOF)
3216             break;
3217           *q++=(unsigned char) c;
3218           count++;
3219         }
3220         case 3:
3221         {
3222           c=gzgetc(image->blob->file_info.gzfile);
3223           if (c == EOF)
3224             break;
3225           *q++=(unsigned char) c;
3226           count++;
3227         }
3228         case 2:
3229         {
3230           c=gzgetc(image->blob->file_info.gzfile);
3231           if (c == EOF)
3232             break;
3233           *q++=(unsigned char) c;
3234           count++;
3235         }
3236         case 1:
3237         {
3238           c=gzgetc(image->blob->file_info.gzfile);
3239           if (c == EOF)
3240             break;
3241           *q++=(unsigned char) c;
3242           count++;
3243         }
3244         case 0:
3245           break;
3246       }
3247 #endif
3248       break;
3249     }
3250     case BZipStream:
3251     {
3252 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3253       count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
3254 #endif
3255       break;
3256     }
3257     case FifoStream:
3258       break;
3259     case BlobStream:
3260     {
3261       register const unsigned char
3262         *p;
3263
3264       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3265         {
3266           image->blob->eof=MagickTrue;
3267           break;
3268         }
3269       p=image->blob->data+image->blob->offset;
3270       count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
3271       image->blob->offset+=count;
3272       if (count != (ssize_t) length)
3273         image->blob->eof=MagickTrue;
3274       (void) memcpy(q,p,(size_t) count);
3275       break;
3276     }
3277     case UserStream:
3278     {
3279       count=image->blob->user_info->handler(q,length,
3280         image->blob->user_info->data);
3281       break;
3282     }
3283   }
3284   return(count);
3285 }
3286 \f
3287 /*
3288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3289 %                                                                             %
3290 %                                                                             %
3291 %                                                                             %
3292 +  R e a d B l o b B y t e                                                    %
3293 %                                                                             %
3294 %                                                                             %
3295 %                                                                             %
3296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3297 %
3298 %  ReadBlobByte() reads a single byte from the image file and returns it.
3299 %
3300 %  The format of the ReadBlobByte method is:
3301 %
3302 %      int ReadBlobByte(Image *image)
3303 %
3304 %  A description of each parameter follows.
3305 %
3306 %    o image: the image.
3307 %
3308 */
3309 MagickExport int ReadBlobByte(Image *image)
3310 {
3311   register const unsigned char
3312     *p;
3313
3314   ssize_t
3315     count;
3316
3317   unsigned char
3318     buffer[1];
3319
3320   assert(image != (Image *) NULL);
3321   assert(image->signature == MagickCoreSignature);
3322   p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3323   if (count != 1)
3324     return(EOF);
3325   return((int) (*p));
3326 }
3327 \f
3328 /*
3329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3330 %                                                                             %
3331 %                                                                             %
3332 %                                                                             %
3333 +  R e a d B l o b D o u b l e                                                %
3334 %                                                                             %
3335 %                                                                             %
3336 %                                                                             %
3337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3338 %
3339 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3340 %  specified by the endian member of the image structure.
3341 %
3342 %  The format of the ReadBlobDouble method is:
3343 %
3344 %      double ReadBlobDouble(Image *image)
3345 %
3346 %  A description of each parameter follows.
3347 %
3348 %    o image: the image.
3349 %
3350 */
3351 MagickExport double ReadBlobDouble(Image *image)
3352 {
3353   union
3354   {
3355     MagickSizeType
3356       unsigned_value;
3357
3358     double
3359       double_value;
3360   } quantum;
3361
3362   quantum.double_value=0.0;
3363   quantum.unsigned_value=ReadBlobLongLong(image);
3364   return(quantum.double_value);
3365 }
3366 \f
3367 /*
3368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3369 %                                                                             %
3370 %                                                                             %
3371 %                                                                             %
3372 +  R e a d B l o b F l o a t                                                  %
3373 %                                                                             %
3374 %                                                                             %
3375 %                                                                             %
3376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3377 %
3378 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3379 %  specified by the endian member of the image structure.
3380 %
3381 %  The format of the ReadBlobFloat method is:
3382 %
3383 %      float ReadBlobFloat(Image *image)
3384 %
3385 %  A description of each parameter follows.
3386 %
3387 %    o image: the image.
3388 %
3389 */
3390 MagickExport float ReadBlobFloat(Image *image)
3391 {
3392   union
3393   {
3394     unsigned int
3395       unsigned_value;
3396
3397     float
3398       float_value;
3399   } quantum;
3400
3401   quantum.float_value=0.0;
3402   quantum.unsigned_value=ReadBlobLong(image);
3403   return(quantum.float_value);
3404 }
3405 \f
3406 /*
3407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3408 %                                                                             %
3409 %                                                                             %
3410 %                                                                             %
3411 +  R e a d B l o b L o n g                                                    %
3412 %                                                                             %
3413 %                                                                             %
3414 %                                                                             %
3415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3416 %
3417 %  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3418 %  byte-order specified by the endian member of the image structure.
3419 %
3420 %  The format of the ReadBlobLong method is:
3421 %
3422 %      unsigned int ReadBlobLong(Image *image)
3423 %
3424 %  A description of each parameter follows.
3425 %
3426 %    o image: the image.
3427 %
3428 */
3429 MagickExport unsigned int ReadBlobLong(Image *image)
3430 {
3431   register const unsigned char
3432     *p;
3433
3434   ssize_t
3435     count;
3436
3437   unsigned char
3438     buffer[4];
3439
3440   unsigned int
3441     value;
3442
3443   assert(image != (Image *) NULL);
3444   assert(image->signature == MagickCoreSignature);
3445   *buffer='\0';
3446   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3447   if (count != 4)
3448     return(0UL);
3449   if (image->endian == LSBEndian)
3450     {
3451       value=(unsigned int) (*p++);
3452       value|=(unsigned int) (*p++) << 8;
3453       value|=(unsigned int) (*p++) << 16;
3454       value|=(unsigned int) (*p++) << 24;
3455       return(value & 0xffffffff);
3456     }
3457   value=(unsigned int) (*p++) << 24;
3458   value|=(unsigned int) (*p++) << 16;
3459   value|=(unsigned int) (*p++) << 8;
3460   value|=(unsigned int) (*p++);
3461   return(value & 0xffffffff);
3462 }
3463 \f
3464 /*
3465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3466 %                                                                             %
3467 %                                                                             %
3468 %                                                                             %
3469 +  R e a d B l o b L o n g L o n g                                            %
3470 %                                                                             %
3471 %                                                                             %
3472 %                                                                             %
3473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3474 %
3475 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3476 %  byte-order specified by the endian member of the image structure.
3477 %
3478 %  The format of the ReadBlobLongLong method is:
3479 %
3480 %      MagickSizeType ReadBlobLongLong(Image *image)
3481 %
3482 %  A description of each parameter follows.
3483 %
3484 %    o image: the image.
3485 %
3486 */
3487 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3488 {
3489   MagickSizeType
3490     value;
3491
3492   register const unsigned char
3493     *p;
3494
3495   ssize_t
3496     count;
3497
3498   unsigned char
3499     buffer[8];
3500
3501   assert(image != (Image *) NULL);
3502   assert(image->signature == MagickCoreSignature);
3503   *buffer='\0';
3504   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3505   if (count != 8)
3506     return(MagickULLConstant(0));
3507   if (image->endian == LSBEndian)
3508     {
3509       value=(MagickSizeType) (*p++);
3510       value|=(MagickSizeType) (*p++) << 8;
3511       value|=(MagickSizeType) (*p++) << 16;
3512       value|=(MagickSizeType) (*p++) << 24;
3513       value|=(MagickSizeType) (*p++) << 32;
3514       value|=(MagickSizeType) (*p++) << 40;
3515       value|=(MagickSizeType) (*p++) << 48;
3516       value|=(MagickSizeType) (*p++) << 56;
3517       return(value & MagickULLConstant(0xffffffffffffffff));
3518     }
3519   value=(MagickSizeType) (*p++) << 56;
3520   value|=(MagickSizeType) (*p++) << 48;
3521   value|=(MagickSizeType) (*p++) << 40;
3522   value|=(MagickSizeType) (*p++) << 32;
3523   value|=(MagickSizeType) (*p++) << 24;
3524   value|=(MagickSizeType) (*p++) << 16;
3525   value|=(MagickSizeType) (*p++) << 8;
3526   value|=(MagickSizeType) (*p++);
3527   return(value & MagickULLConstant(0xffffffffffffffff));
3528 }
3529 \f
3530 /*
3531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3532 %                                                                             %
3533 %                                                                             %
3534 %                                                                             %
3535 +  R e a d B l o b S h o r t                                                  %
3536 %                                                                             %
3537 %                                                                             %
3538 %                                                                             %
3539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3540 %
3541 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3542 %  specified by the endian member of the image structure.
3543 %
3544 %  The format of the ReadBlobShort method is:
3545 %
3546 %      unsigned short ReadBlobShort(Image *image)
3547 %
3548 %  A description of each parameter follows.
3549 %
3550 %    o image: the image.
3551 %
3552 */
3553 MagickExport unsigned short ReadBlobShort(Image *image)
3554 {
3555   register const unsigned char
3556     *p;
3557
3558   register unsigned short
3559     value;
3560
3561   ssize_t
3562     count;
3563
3564   unsigned char
3565     buffer[2];
3566
3567   assert(image != (Image *) NULL);
3568   assert(image->signature == MagickCoreSignature);
3569   *buffer='\0';
3570   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3571   if (count != 2)
3572     return((unsigned short) 0U);
3573   if (image->endian == LSBEndian)
3574     {
3575       value=(unsigned short) (*p++);
3576       value|=(unsigned short) (*p++) << 8;
3577       return(value);
3578     }
3579   value=(unsigned short) (*p++) << 8;
3580   value|=(unsigned short) (*p++);
3581   return(value);
3582 }
3583 \f
3584 /*
3585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3586 %                                                                             %
3587 %                                                                             %
3588 %                                                                             %
3589 +  R e a d B l o b L S B L o n g                                              %
3590 %                                                                             %
3591 %                                                                             %
3592 %                                                                             %
3593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3594 %
3595 %  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3596 %  least-significant byte first order.
3597 %
3598 %  The format of the ReadBlobLSBLong method is:
3599 %
3600 %      unsigned int ReadBlobLSBLong(Image *image)
3601 %
3602 %  A description of each parameter follows.
3603 %
3604 %    o image: the image.
3605 %
3606 */
3607 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3608 {
3609   register const unsigned char
3610     *p;
3611
3612   register unsigned int
3613     value;
3614
3615   ssize_t
3616     count;
3617
3618   unsigned char
3619     buffer[4];
3620
3621   assert(image != (Image *) NULL);
3622   assert(image->signature == MagickCoreSignature);
3623   *buffer='\0';
3624   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3625   if (count != 4)
3626     return(0U);
3627   value=(unsigned int) (*p++);
3628   value|=(unsigned int) (*p++) << 8;
3629   value|=(unsigned int) (*p++) << 16;
3630   value|=(unsigned int) (*p++) << 24;
3631   return(value & 0xffffffff);
3632 }
3633 \f
3634 /*
3635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3636 %                                                                             %
3637 %                                                                             %
3638 %                                                                             %
3639 +  R e a d B l o b L S B S i g n e d L o n g                                  %
3640 %                                                                             %
3641 %                                                                             %
3642 %                                                                             %
3643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3644 %
3645 %  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3646 %  least-significant byte first order.
3647 %
3648 %  The format of the ReadBlobLSBSignedLong method is:
3649 %
3650 %      signed int ReadBlobLSBSignedLong(Image *image)
3651 %
3652 %  A description of each parameter follows.
3653 %
3654 %    o image: the image.
3655 %
3656 */
3657 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
3658 {
3659   union
3660   {
3661     unsigned int
3662       unsigned_value;
3663
3664     signed int
3665       signed_value;
3666   } quantum;
3667
3668   quantum.unsigned_value=ReadBlobLSBLong(image);
3669   return(quantum.signed_value);
3670 }
3671 \f
3672 /*
3673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3674 %                                                                             %
3675 %                                                                             %
3676 %                                                                             %
3677 +  R e a d B l o b L S B S h o r t                                            %
3678 %                                                                             %
3679 %                                                                             %
3680 %                                                                             %
3681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682 %
3683 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3684 %  least-significant byte first order.
3685 %
3686 %  The format of the ReadBlobLSBShort method is:
3687 %
3688 %      unsigned short ReadBlobLSBShort(Image *image)
3689 %
3690 %  A description of each parameter follows.
3691 %
3692 %    o image: the image.
3693 %
3694 */
3695 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3696 {
3697   register const unsigned char
3698     *p;
3699
3700   register unsigned short
3701     value;
3702
3703   ssize_t
3704     count;
3705
3706   unsigned char
3707     buffer[2];
3708
3709   assert(image != (Image *) NULL);
3710   assert(image->signature == MagickCoreSignature);
3711   *buffer='\0';
3712   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3713   if (count != 2)
3714     return((unsigned short) 0U);
3715   value=(unsigned int) (*p++);
3716   value|=(unsigned int) (*p++) << 8;
3717   return(value & 0xffff);
3718 }
3719 \f
3720 /*
3721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3722 %                                                                             %
3723 %                                                                             %
3724 %                                                                             %
3725 +  R e a d B l o b L S B S i g n e d S h o r t                                %
3726 %                                                                             %
3727 %                                                                             %
3728 %                                                                             %
3729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3730 %
3731 %  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
3732 %  least-significant byte-order.
3733 %
3734 %  The format of the ReadBlobLSBSignedShort method is:
3735 %
3736 %      signed short ReadBlobLSBSignedShort(Image *image)
3737 %
3738 %  A description of each parameter follows.
3739 %
3740 %    o image: the image.
3741 %
3742 */
3743 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
3744 {
3745   union
3746   {
3747     unsigned short
3748       unsigned_value;
3749
3750     signed short
3751       signed_value;
3752   } quantum;
3753
3754   quantum.unsigned_value=ReadBlobLSBShort(image);
3755   return(quantum.signed_value);
3756 }
3757 \f
3758 /*
3759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3760 %                                                                             %
3761 %                                                                             %
3762 %                                                                             %
3763 +  R e a d B l o b M S B L o n g                                              %
3764 %                                                                             %
3765 %                                                                             %
3766 %                                                                             %
3767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3768 %
3769 %  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
3770 %  most-significant byte first order.
3771 %
3772 %  The format of the ReadBlobMSBLong method is:
3773 %
3774 %      unsigned int ReadBlobMSBLong(Image *image)
3775 %
3776 %  A description of each parameter follows.
3777 %
3778 %    o image: the image.
3779 %
3780 */
3781 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3782 {
3783   register const unsigned char
3784     *p;
3785
3786   register unsigned int
3787     value;
3788
3789   ssize_t
3790     count;
3791
3792   unsigned char
3793     buffer[4];
3794
3795   assert(image != (Image *) NULL);
3796   assert(image->signature == MagickCoreSignature);
3797   *buffer='\0';
3798   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3799   if (count != 4)
3800     return(0UL);
3801   value=(unsigned int) (*p++) << 24;
3802   value|=(unsigned int) (*p++) << 16;
3803   value|=(unsigned int) (*p++) << 8;
3804   value|=(unsigned int) (*p++);
3805   return(value);
3806 }
3807 \f
3808 /*
3809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3810 %                                                                             %
3811 %                                                                             %
3812 %                                                                             %
3813 +  R e a d B l o b M S B L o n g L o n g                                      %
3814 %                                                                             %
3815 %                                                                             %
3816 %                                                                             %
3817 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3818 %
3819 %  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
3820 %  in most-significant byte first order.
3821 %
3822 %  The format of the ReadBlobMSBLongLong method is:
3823 %
3824 %      unsigned int ReadBlobMSBLongLong(Image *image)
3825 %
3826 %  A description of each parameter follows.
3827 %
3828 %    o image: the image.
3829 %
3830 */
3831 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3832 {
3833   register const unsigned char
3834     *p;
3835
3836   register MagickSizeType
3837     value;
3838
3839   ssize_t
3840     count;
3841
3842   unsigned char
3843     buffer[8];
3844
3845   assert(image != (Image *) NULL);
3846   assert(image->signature == MagickCoreSignature);
3847   *buffer='\0';
3848   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3849   if (count != 8)
3850     return(MagickULLConstant(0));
3851   value=(MagickSizeType) (*p++) << 56;
3852   value|=(MagickSizeType) (*p++) << 48;
3853   value|=(MagickSizeType) (*p++) << 40;
3854   value|=(MagickSizeType) (*p++) << 32;
3855   value|=(MagickSizeType) (*p++) << 24;
3856   value|=(MagickSizeType) (*p++) << 16;
3857   value|=(MagickSizeType) (*p++) << 8;
3858   value|=(MagickSizeType) (*p++);
3859   return(value & MagickULLConstant(0xffffffffffffffff));
3860 }
3861 \f
3862 /*
3863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3864 %                                                                             %
3865 %                                                                             %
3866 %                                                                             %
3867 +  R e a d B l o b M S B S h o r t                                            %
3868 %                                                                             %
3869 %                                                                             %
3870 %                                                                             %
3871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3872 %
3873 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3874 %  most-significant byte first order.
3875 %
3876 %  The format of the ReadBlobMSBShort method is:
3877 %
3878 %      unsigned short ReadBlobMSBShort(Image *image)
3879 %
3880 %  A description of each parameter follows.
3881 %
3882 %    o image: the image.
3883 %
3884 */
3885 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3886 {
3887   register const unsigned char
3888     *p;
3889
3890   register unsigned short
3891     value;
3892
3893   ssize_t
3894     count;
3895
3896   unsigned char
3897     buffer[2];
3898
3899   assert(image != (Image *) NULL);
3900   assert(image->signature == MagickCoreSignature);
3901   *buffer='\0';
3902   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3903   if (count != 2)
3904     return((unsigned short) 0U);
3905   value=(unsigned short) (*p++) << 8;
3906   value|=(unsigned short) (*p++);
3907   return(value & 0xffff);
3908 }
3909 \f
3910 /*
3911 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3912 %                                                                             %
3913 %                                                                             %
3914 %                                                                             %
3915 +  R e a d B l o b M S B S i g n e d L o n g                                  %
3916 %                                                                             %
3917 %                                                                             %
3918 %                                                                             %
3919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3920 %
3921 %  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
3922 %  most-significant byte-order.
3923 %
3924 %  The format of the ReadBlobMSBSignedLong method is:
3925 %
3926 %      signed int ReadBlobMSBSignedLong(Image *image)
3927 %
3928 %  A description of each parameter follows.
3929 %
3930 %    o image: the image.
3931 %
3932 */
3933 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
3934 {
3935   union
3936   {
3937     unsigned int
3938       unsigned_value;
3939
3940     signed int
3941       signed_value;
3942   } quantum;
3943
3944   quantum.unsigned_value=ReadBlobMSBLong(image);
3945   return(quantum.signed_value);
3946 }
3947 \f
3948 /*
3949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3950 %                                                                             %
3951 %                                                                             %
3952 %                                                                             %
3953 +  R e a d B l o b M S B S i g n e d S h o r t                                %
3954 %                                                                             %
3955 %                                                                             %
3956 %                                                                             %
3957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3958 %
3959 %  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
3960 %  most-significant byte-order.
3961 %
3962 %  The format of the ReadBlobMSBSignedShort method is:
3963 %
3964 %      signed short ReadBlobMSBSignedShort(Image *image)
3965 %
3966 %  A description of each parameter follows.
3967 %
3968 %    o image: the image.
3969 %
3970 */
3971 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
3972 {
3973   union
3974   {
3975     unsigned short
3976       unsigned_value;
3977
3978     signed short
3979       signed_value;
3980   } quantum;
3981
3982   quantum.unsigned_value=ReadBlobMSBShort(image);
3983   return(quantum.signed_value);
3984 }
3985 \f
3986 /*
3987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3988 %                                                                             %
3989 %                                                                             %
3990 %                                                                             %
3991 +  R e a d B l o b S i g n e d L o n g                                        %
3992 %                                                                             %
3993 %                                                                             %
3994 %                                                                             %
3995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3996 %
3997 %  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
3998 %  byte-order specified by the endian member of the image structure.
3999 %
4000 %  The format of the ReadBlobSignedLong method is:
4001 %
4002 %      signed int ReadBlobSignedLong(Image *image)
4003 %
4004 %  A description of each parameter follows.
4005 %
4006 %    o image: the image.
4007 %
4008 */
4009 MagickExport signed int ReadBlobSignedLong(Image *image)
4010 {
4011   union
4012   {
4013     unsigned int
4014       unsigned_value;
4015
4016     signed int
4017       signed_value;
4018   } quantum;
4019
4020   quantum.unsigned_value=ReadBlobLong(image);
4021   return(quantum.signed_value);
4022 }
4023 \f
4024 /*
4025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4026 %                                                                             %
4027 %                                                                             %
4028 %                                                                             %
4029 +  R e a d B l o b S i g n e d S h o r t                                      %
4030 %                                                                             %
4031 %                                                                             %
4032 %                                                                             %
4033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4034 %
4035 %  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4036 %  byte-order specified by the endian member of the image structure.
4037 %
4038 %  The format of the ReadBlobSignedShort method is:
4039 %
4040 %      signed short ReadBlobSignedShort(Image *image)
4041 %
4042 %  A description of each parameter follows.
4043 %
4044 %    o image: the image.
4045 %
4046 */
4047 MagickExport signed short ReadBlobSignedShort(Image *image)
4048 {
4049   union
4050   {
4051     unsigned short
4052       unsigned_value;
4053
4054     signed short
4055       signed_value;
4056   } quantum;
4057
4058   quantum.unsigned_value=ReadBlobShort(image);
4059   return(quantum.signed_value);
4060 }
4061 \f
4062 /*
4063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4064 %                                                                             %
4065 %                                                                             %
4066 %                                                                             %
4067 +  R e a d B l o b S t r e a m                                                %
4068 %                                                                             %
4069 %                                                                             %
4070 %                                                                             %
4071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4072 %
4073 %  ReadBlobStream() reads data from the blob or image file and returns it.  It
4074 %  returns a pointer to the data buffer you supply or to the image memory
4075 %  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4076 %  returns a count of zero and has no other results. If length is greater than
4077 %  SSIZE_MAX, the result is unspecified.
4078 %
4079 %  The format of the ReadBlobStream method is:
4080 %
4081 %      const void *ReadBlobStream(Image *image,const size_t length,void *data,
4082 %        ssize_t *count)
4083 %
4084 %  A description of each parameter follows:
4085 %
4086 %    o image: the image.
4087 %
4088 %    o length:  Specifies an integer representing the number of bytes to read
4089 %      from the file.
4090 %
4091 %    o count: returns the number of bytes read.
4092 %
4093 %    o data:  Specifies an area to place the information requested from the
4094 %      file.
4095 %
4096 */
4097 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
4098   void *data,ssize_t *count)
4099 {
4100   assert(image != (Image *) NULL);
4101   assert(image->signature == MagickCoreSignature);
4102   assert(image->blob != (BlobInfo *) NULL);
4103   assert(image->blob->type != UndefinedStream);
4104   assert(count != (ssize_t *) NULL);
4105   if (image->blob->type != BlobStream)
4106     {
4107       assert(data != NULL);
4108       *count=ReadBlob(image,length,(unsigned char *) data);
4109       return(data);
4110     }
4111   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4112     {
4113       *count=0;
4114       image->blob->eof=MagickTrue;
4115       return(data);
4116     }
4117   data=image->blob->data+image->blob->offset;
4118   *count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
4119   image->blob->offset+=(*count);
4120   if (*count != (ssize_t) length)
4121     image->blob->eof=MagickTrue;
4122   return(data);
4123 }
4124 \f
4125 /*
4126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4127 %                                                                             %
4128 %                                                                             %
4129 %                                                                             %
4130 +   R e a d B l o b S t r i n g                                               %
4131 %                                                                             %
4132 %                                                                             %
4133 %                                                                             %
4134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4135 %
4136 %  ReadBlobString() reads characters from a blob or file until a newline
4137 %  character is read or an end-of-file condition is encountered.
4138 %
4139 %  The format of the ReadBlobString method is:
4140 %
4141 %      char *ReadBlobString(Image *image,char *string)
4142 %
4143 %  A description of each parameter follows:
4144 %
4145 %    o image: the image.
4146 %
4147 %    o string: the address of a character buffer.
4148 %
4149 */
4150 MagickExport char *ReadBlobString(Image *image,char *string)
4151 {
4152   register const unsigned char
4153     *p;
4154
4155   register ssize_t
4156     i;
4157
4158   ssize_t
4159     count;
4160
4161   unsigned char
4162     buffer[1];
4163
4164   assert(image != (Image *) NULL);
4165   assert(image->signature == MagickCoreSignature);
4166   for (i=0; i < (MagickPathExtent-1L); i++)
4167   {
4168     p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
4169     if (count != 1)
4170       {
4171         if (i == 0)
4172           return((char *) NULL);
4173         break;
4174       }
4175     string[i]=(char) (*p);
4176     if ((string[i] == '\r') || (string[i] == '\n'))
4177       break;
4178   }
4179   if (string[i] == '\r')
4180     (void) ReadBlobStream(image,1,buffer,&count);
4181   string[i]='\0';
4182   return(string);
4183 }
4184 \f
4185 /*
4186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4187 %                                                                             %
4188 %                                                                             %
4189 %                                                                             %
4190 +   R e f e r e n c e B l o b                                                 %
4191 %                                                                             %
4192 %                                                                             %
4193 %                                                                             %
4194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4195 %
4196 %  ReferenceBlob() increments the reference count associated with the pixel
4197 %  blob returning a pointer to the blob.
4198 %
4199 %  The format of the ReferenceBlob method is:
4200 %
4201 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
4202 %
4203 %  A description of each parameter follows:
4204 %
4205 %    o blob_info: the blob_info.
4206 %
4207 */
4208 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4209 {
4210   assert(blob != (BlobInfo *) NULL);
4211   assert(blob->signature == MagickCoreSignature);
4212   if (blob->debug != MagickFalse)
4213     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4214   LockSemaphoreInfo(blob->semaphore);
4215   blob->reference_count++;
4216   UnlockSemaphoreInfo(blob->semaphore);
4217   return(blob);
4218 }
4219 \f
4220 /*
4221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4222 %                                                                             %
4223 %                                                                             %
4224 %                                                                             %
4225 +  S e e k B l o b                                                            %
4226 %                                                                             %
4227 %                                                                             %
4228 %                                                                             %
4229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4230 %
4231 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
4232 %  and returns the resulting offset.
4233 %
4234 %  The format of the SeekBlob method is:
4235 %
4236 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4237 %        const int whence)
4238 %
4239 %  A description of each parameter follows:
4240 %
4241 %    o image: the image.
4242 %
4243 %    o offset:  Specifies an integer representing the offset in bytes.
4244 %
4245 %    o whence:  Specifies an integer representing how the offset is
4246 %      treated relative to the beginning of the blob as follows:
4247 %
4248 %        SEEK_SET  Set position equal to offset bytes.
4249 %        SEEK_CUR  Set position to current location plus offset.
4250 %        SEEK_END  Set position to EOF plus offset.
4251 %
4252 */
4253 MagickExport MagickOffsetType SeekBlob(Image *image,
4254   const MagickOffsetType offset,const int whence)
4255 {
4256   assert(image != (Image *) NULL);
4257   assert(image->signature == MagickCoreSignature);
4258   if (image->debug != MagickFalse)
4259     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4260   assert(image->blob != (BlobInfo *) NULL);
4261   assert(image->blob->type != UndefinedStream);
4262   switch (image->blob->type)
4263   {
4264     case UndefinedStream:
4265       break;
4266     case StandardStream:
4267     case PipeStream:
4268       return(-1);
4269     case FileStream:
4270     {
4271       if ((offset < 0) && (whence == SEEK_SET))
4272         return(-1);
4273       if (fseek(image->blob->file_info.file,offset,whence) < 0)
4274         return(-1);
4275       image->blob->offset=TellBlob(image);
4276       break;
4277     }
4278     case ZipStream:
4279     {
4280 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4281       if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
4282         return(-1);
4283 #endif
4284       image->blob->offset=TellBlob(image);
4285       break;
4286     }
4287     case BZipStream:
4288       return(-1);
4289     case FifoStream:
4290       return(-1);
4291     case BlobStream:
4292     {
4293       switch (whence)
4294       {
4295         case SEEK_SET:
4296         default:
4297         {
4298           if (offset < 0)
4299             return(-1);
4300           image->blob->offset=offset;
4301           break;
4302         }
4303         case SEEK_CUR:
4304         {
4305           if ((image->blob->offset+offset) < 0)
4306             return(-1);
4307           image->blob->offset+=offset;
4308           break;
4309         }
4310         case SEEK_END:
4311         {
4312           if (((MagickOffsetType) image->blob->length+offset) < 0)
4313             return(-1);
4314           image->blob->offset=image->blob->length+offset;
4315           break;
4316         }
4317       }
4318       if (image->blob->offset < (MagickOffsetType)
4319           ((off_t) image->blob->length))
4320         {
4321           image->blob->eof=MagickFalse;
4322           break;
4323         }
4324       if (image->blob->offset < (MagickOffsetType)
4325           ((off_t) image->blob->extent))
4326         break;
4327       if (image->blob->mapped != MagickFalse)
4328         {
4329           image->blob->eof=MagickTrue;
4330           return(-1);
4331         }
4332       image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
4333       image->blob->quantum<<=1;
4334       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
4335         image->blob->extent+1,sizeof(*image->blob->data));
4336       (void) SyncBlob(image);
4337       if (image->blob->data == NULL)
4338         {
4339           (void) DetachBlob(image->blob);
4340           return(-1);
4341         }
4342       break;
4343     }
4344     case UserStream:
4345     {
4346       if (image->blob->user_info->seeker == (BlobSeeker) NULL)
4347         return(-1);
4348       image->blob->user_info->seeker(offset,whence,
4349         image->blob->user_info->data);
4350       image->blob->offset=TellBlob(image);
4351       break;
4352     }
4353   }
4354   return(image->blob->offset);
4355 }
4356 \f
4357 /*
4358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4359 %                                                                             %
4360 %                                                                             %
4361 %                                                                             %
4362 +   S e t B l o b E x e m p t                                                 %
4363 %                                                                             %
4364 %                                                                             %
4365 %                                                                             %
4366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4367 %
4368 %  SetBlobExempt() sets the blob exempt status.
4369 %
4370 %  The format of the SetBlobExempt method is:
4371 %
4372 %      MagickBooleanType SetBlobExempt(const Image *image,
4373 %        const MagickBooleanType exempt)
4374 %
4375 %  A description of each parameter follows:
4376 %
4377 %    o image: the image.
4378 %
4379 %    o exempt: Set to true if this blob is exempt from being closed.
4380 %
4381 */
4382 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4383 {
4384   assert(image != (const Image *) NULL);
4385   assert(image->signature == MagickCoreSignature);
4386   if (image->debug != MagickFalse)
4387     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4388   image->blob->exempt=exempt;
4389 }
4390 \f
4391 /*
4392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4393 %                                                                             %
4394 %                                                                             %
4395 %                                                                             %
4396 +  S e t B l o b E x t e n t                                                  %
4397 %                                                                             %
4398 %                                                                             %
4399 %                                                                             %
4400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4401 %
4402 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
4403 %  method is successful, subsequent writes to bytes in the specified range are
4404 %  guaranteed not to fail.
4405 %
4406 %  The format of the SetBlobExtent method is:
4407 %
4408 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
4409 %
4410 %  A description of each parameter follows:
4411 %
4412 %    o image: the image.
4413 %
4414 %    o extent:  the blob maximum extent.
4415 %
4416 */
4417 MagickExport MagickBooleanType SetBlobExtent(Image *image,
4418   const MagickSizeType extent)
4419 {
4420   assert(image != (Image *) NULL);
4421   assert(image->signature == MagickCoreSignature);
4422   if (image->debug != MagickFalse)
4423     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4424   assert(image->blob != (BlobInfo *) NULL);
4425   assert(image->blob->type != UndefinedStream);
4426   switch (image->blob->type)
4427   {
4428     case UndefinedStream:
4429       break;
4430     case StandardStream:
4431       return(MagickFalse);
4432     case FileStream:
4433     {
4434       MagickOffsetType
4435         offset;
4436
4437       ssize_t
4438         count;
4439
4440       if (extent != (MagickSizeType) ((off_t) extent))
4441         return(MagickFalse);
4442       offset=SeekBlob(image,0,SEEK_END);
4443       if (offset < 0)
4444         return(MagickFalse);
4445       if ((MagickSizeType) offset >= extent)
4446         break;
4447       offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4448       if (offset < 0)
4449         break;
4450       count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4451         image->blob->file_info.file);
4452 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4453       if (image->blob->synchronize != MagickFalse)
4454         {
4455           int
4456             file;
4457
4458           file=fileno(image->blob->file_info.file);
4459           if ((file == -1) || (offset < 0))
4460             return(MagickFalse);
4461           (void) posix_fallocate(file,offset,extent-offset);
4462         }
4463 #endif
4464       offset=SeekBlob(image,offset,SEEK_SET);
4465       if (count != 1)
4466         return(MagickFalse);
4467       break;
4468     }
4469     case PipeStream:
4470     case ZipStream:
4471       return(MagickFalse);
4472     case BZipStream:
4473       return(MagickFalse);
4474     case FifoStream:
4475       return(MagickFalse);
4476     case BlobStream:
4477     {
4478       if (extent != (MagickSizeType) ((size_t) extent))
4479         return(MagickFalse);
4480       if (image->blob->mapped != MagickFalse)
4481         {
4482           MagickOffsetType
4483             offset;
4484
4485           ssize_t
4486             count;
4487
4488           (void) UnmapBlob(image->blob->data,image->blob->length);
4489           RelinquishMagickResource(MapResource,image->blob->length);
4490           if (extent != (MagickSizeType) ((off_t) extent))
4491             return(MagickFalse);
4492           offset=SeekBlob(image,0,SEEK_END);
4493           if (offset < 0)
4494             return(MagickFalse);
4495           if ((MagickSizeType) offset >= extent)
4496             break;
4497           offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4498           count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4499             image->blob->file_info.file);
4500 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4501           if (image->blob->synchronize != MagickFalse)
4502             {
4503               int
4504                 file;
4505
4506               file=fileno(image->blob->file_info.file);
4507               if ((file == -1) || (offset < 0))
4508                 return(MagickFalse);
4509               (void) posix_fallocate(file,offset,extent-offset);
4510             }
4511 #endif
4512           offset=SeekBlob(image,offset,SEEK_SET);
4513           if (count != 1)
4514             return(MagickFalse);
4515           (void) AcquireMagickResource(MapResource,extent);
4516           image->blob->data=(unsigned char*) MapBlob(fileno(
4517             image->blob->file_info.file),WriteMode,0,(size_t) extent);
4518           image->blob->extent=(size_t) extent;
4519           image->blob->length=(size_t) extent;
4520           (void) SyncBlob(image);
4521           break;
4522         }
4523       image->blob->extent=(size_t) extent;
4524       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
4525         image->blob->extent+1,sizeof(*image->blob->data));
4526       (void) SyncBlob(image);
4527       if (image->blob->data == (unsigned char *) NULL)
4528         {
4529           (void) DetachBlob(image->blob);
4530           return(MagickFalse);
4531         }
4532       break;
4533     }
4534     case UserStream:
4535       break;
4536   }
4537   return(MagickTrue);
4538 }
4539 \f
4540 /*
4541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4542 %                                                                             %
4543 %                                                                             %
4544 %                                                                             %
4545 +  S y n c B l o b                                                            %
4546 %                                                                             %
4547 %                                                                             %
4548 %                                                                             %
4549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4550 %
4551 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
4552 %  attributes if it is an blob.
4553 %
4554 %  The format of the SyncBlob method is:
4555 %
4556 %      int SyncBlob(Image *image)
4557 %
4558 %  A description of each parameter follows:
4559 %
4560 %    o image: the image.
4561 %
4562 */
4563 static int SyncBlob(Image *image)
4564 {
4565   int
4566     status;
4567
4568   assert(image != (Image *) NULL);
4569   assert(image->signature == MagickCoreSignature);
4570   if (image->debug != MagickFalse)
4571     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4572   assert(image->blob != (BlobInfo *) NULL);
4573   assert(image->blob->type != UndefinedStream);
4574   status=0;
4575   switch (image->blob->type)
4576   {
4577     case UndefinedStream:
4578     case StandardStream:
4579       break;
4580     case FileStream:
4581     case PipeStream:
4582     {
4583       status=fflush(image->blob->file_info.file);
4584       break;
4585     }
4586     case ZipStream:
4587     {
4588 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4589       status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
4590 #endif
4591       break;
4592     }
4593     case BZipStream:
4594     {
4595 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4596       status=BZ2_bzflush(image->blob->file_info.bzfile);
4597 #endif
4598       break;
4599     }
4600     case FifoStream:
4601       break;
4602     case BlobStream:
4603       break;
4604     case UserStream:
4605       break;
4606   }
4607   return(status);
4608 }
4609 \f
4610 /*
4611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4612 %                                                                             %
4613 %                                                                             %
4614 %                                                                             %
4615 +  T e l l B l o b                                                            %
4616 %                                                                             %
4617 %                                                                             %
4618 %                                                                             %
4619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4620 %
4621 %  TellBlob() obtains the current value of the blob or file position.
4622 %
4623 %  The format of the TellBlob method is:
4624 %
4625 %      MagickOffsetType TellBlob(const Image *image)
4626 %
4627 %  A description of each parameter follows:
4628 %
4629 %    o image: the image.
4630 %
4631 */
4632 MagickExport MagickOffsetType TellBlob(const Image *image)
4633 {
4634   MagickOffsetType
4635     offset;
4636
4637   assert(image != (Image *) NULL);
4638   assert(image->signature == MagickCoreSignature);
4639   if (image->debug != MagickFalse)
4640     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4641   assert(image->blob != (BlobInfo *) NULL);
4642   assert(image->blob->type != UndefinedStream);
4643   offset=(-1);
4644   switch (image->blob->type)
4645   {
4646     case UndefinedStream:
4647     case StandardStream:
4648       break;
4649     case FileStream:
4650     {
4651       offset=ftell(image->blob->file_info.file);
4652       break;
4653     }
4654     case PipeStream:
4655       break;
4656     case ZipStream:
4657     {
4658 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4659       offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
4660 #endif
4661       break;
4662     }
4663     case BZipStream:
4664       break;
4665     case FifoStream:
4666       break;
4667     case BlobStream:
4668     {
4669       offset=image->blob->offset;
4670       break;
4671     }
4672     case UserStream:
4673     {
4674       if (image->blob->user_info->teller != (BlobTeller) NULL)
4675         offset=image->blob->user_info->teller(image->blob->user_info->data);
4676       break;
4677     }
4678   }
4679   return(offset);
4680 }
4681 \f
4682 /*
4683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4684 %                                                                             %
4685 %                                                                             %
4686 %                                                                             %
4687 +  U n m a p B l o b                                                          %
4688 %                                                                             %
4689 %                                                                             %
4690 %                                                                             %
4691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4692 %
4693 %  UnmapBlob() deallocates the binary large object previously allocated with
4694 %  the MapBlob method.
4695 %
4696 %  The format of the UnmapBlob method is:
4697 %
4698 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
4699 %
4700 %  A description of each parameter follows:
4701 %
4702 %    o map: the address  of the binary large object.
4703 %
4704 %    o length: the length of the binary large object.
4705 %
4706 */
4707 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4708 {
4709 #if defined(MAGICKCORE_HAVE_MMAP)
4710   int
4711     status;
4712
4713   status=munmap(map,length);
4714   return(status == -1 ? MagickFalse : MagickTrue);
4715 #else
4716   (void) map;
4717   (void) length;
4718   return(MagickFalse);
4719 #endif
4720 }
4721 \f
4722 /*
4723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4724 %                                                                             %
4725 %                                                                             %
4726 %                                                                             %
4727 %   U s e r B l o b T o I m a g e                                             %
4728 %                                                                             %
4729 %                                                                             %
4730 %                                                                             %
4731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4732 %
4733 %  UserBlobToImage() is the equivalent of ReadImage(), but reads the
4734 %  formatted "file" from the suplied method rather than to an actual file.
4735 %
4736 %  The format of the BlobToImage method is:
4737 %
4738 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
4739 %        const size_t length,ExceptionInfo *exception)
4740 %
4741 %  A description of each parameter follows:
4742 %
4743 %    o image_info: the image info.
4744 %
4745 %    o blob: the address of a character stream in one of the image formats
4746 %      understood by ImageMagick.
4747 %
4748 %    o length: This size_t integer reflects the length in bytes of the blob.
4749 %
4750 %    o exception: return any errors or warnings in this structure.
4751 %
4752 */
4753 MagickExport Image *UserBlobToImage(const ImageInfo *image_info,
4754   UserBlobInfo *user_info,ExceptionInfo *exception)
4755 {
4756   const MagickInfo
4757     *magick_info;
4758
4759   Image
4760     *image;
4761
4762   ImageInfo
4763     *blob_info;
4764
4765   assert(image_info != (ImageInfo *) NULL);
4766   assert(image_info->signature == MagickCoreSignature);
4767   if (image_info->debug != MagickFalse)
4768     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4769       image_info->filename);
4770   assert(user_info != (UserBlobInfo *) NULL);
4771   assert(user_info->handler != (BlobHandler) NULL);
4772   assert(exception != (ExceptionInfo *) NULL);
4773   blob_info=CloneImageInfo(image_info);
4774   blob_info->user_info=user_info;
4775   if (*blob_info->magick == '\0')
4776     (void) SetImageInfo(blob_info,0,exception);
4777   magick_info=GetMagickInfo(blob_info->magick,exception);
4778   if (magick_info == (const MagickInfo *) NULL)
4779     {
4780       (void) ThrowMagickException(exception,GetMagickModule(),
4781         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
4782         blob_info->magick);
4783       blob_info=DestroyImageInfo(blob_info);
4784       return((Image *) NULL);
4785     }
4786   image=(Image *) NULL;
4787   if (GetMagickBlobSupport(magick_info) != MagickFalse)
4788     {
4789       /*
4790         Native blob support for this image format.
4791       */
4792       (void) CopyMagickString(blob_info->filename,image_info->filename,
4793         MagickPathExtent);
4794       (void) CopyMagickString(blob_info->magick,image_info->magick,
4795         MagickPathExtent);
4796       image=ReadImage(blob_info,exception);
4797       if (image != (Image *) NULL)
4798         (void) CloseBlob(image);
4799     }
4800   else
4801     {
4802       char
4803         unique[MagickPathExtent];
4804
4805       int
4806         file;
4807
4808       ImageInfo
4809         *clone_info;
4810
4811       unsigned char
4812         *blob;
4813
4814       /*
4815         Write data to file on disk.
4816       */
4817       blob_info->user_info=(UserBlobInfo *) NULL;
4818       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
4819         sizeof(*blob));
4820       if (blob == (unsigned char *) NULL)
4821         {
4822           ThrowFileException(exception,BlobError,"UnableToReadBlob",
4823             image_info->filename);
4824           blob_info=DestroyImageInfo(blob_info);
4825           return((Image *) NULL);
4826         }
4827       file=AcquireUniqueFileResource(unique);
4828       if (file == -1)
4829         {
4830           ThrowFileException(exception,BlobError,"UnableToReadBlob",
4831             image_info->filename);
4832           blob=(unsigned char *) RelinquishMagickMemory(blob);
4833           blob_info=DestroyImageInfo(blob_info);
4834           return((Image *) NULL);
4835         }
4836       clone_info=CloneImageInfo(blob_info);
4837       blob_info->file=fdopen(file,"wb+");
4838       if (blob_info->file != (FILE *) NULL)
4839         {
4840           ssize_t
4841             count;
4842
4843           count=(ssize_t) MagickMaxBufferExtent;
4844           while (count == (ssize_t) MagickMaxBufferExtent)
4845           {
4846             count=user_info->handler(blob,MagickMaxBufferExtent,
4847               user_info->data);
4848             count=(ssize_t) write(file,(const char *) blob,count);
4849           }
4850           (void) fclose(blob_info->file);
4851           (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
4852             "%s:%s",blob_info->magick,unique);
4853           image=ReadImage(clone_info,exception);
4854           if (image != (Image *) NULL)
4855             {
4856               Image
4857                 *images;
4858
4859               /*
4860                 Restore original filenames and image format.
4861               */
4862               for (images=GetFirstImageInList(image); images != (Image *) NULL; )
4863               {
4864                 (void) CopyMagickString(images->filename,image_info->filename,
4865                   MagickPathExtent);
4866                 (void) CopyMagickString(images->magick_filename,
4867                   image_info->filename,MagickPathExtent);
4868                 (void) CopyMagickString(images->magick,magick_info->name,
4869                   MagickPathExtent);
4870                 (void) CloseBlob(images);
4871                 images=GetNextImageInList(images);
4872               }
4873             }
4874         }
4875       clone_info=DestroyImageInfo(clone_info);
4876       blob=(unsigned char *) RelinquishMagickMemory(blob);
4877       (void) RelinquishUniqueFileResource(unique);
4878     }
4879   blob_info=DestroyImageInfo(blob_info);
4880   return(image);
4881 }
4882 \f
4883 /*
4884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4885 %                                                                             %
4886 %                                                                             %
4887 %                                                                             %
4888 +  W r i t e B l o b                                                          %
4889 %                                                                             %
4890 %                                                                             %
4891 %                                                                             %
4892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4893 %
4894 %  WriteBlob() writes data to a blob or image file.  It returns the number of
4895 %  bytes written.
4896 %
4897 %  The format of the WriteBlob method is:
4898 %
4899 %      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
4900 %
4901 %  A description of each parameter follows:
4902 %
4903 %    o image: the image.
4904 %
4905 %    o length:  Specifies an integer representing the number of bytes to
4906 %      write to the file.
4907 %
4908 %    o data:  The address of the data to write to the blob or file.
4909 %
4910 */
4911 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4912   const void *data)
4913 {
4914   int
4915     c;
4916
4917   register const unsigned char
4918     *p;
4919
4920   ssize_t
4921     count;
4922
4923   assert(image != (Image *) NULL);
4924   assert(image->signature == MagickCoreSignature);
4925   assert(data != (const void *) NULL);
4926   assert(image->blob != (BlobInfo *) NULL);
4927   assert(image->blob->type != UndefinedStream);
4928   if (length == 0)
4929     return(0);
4930   count=0;
4931   p=(const unsigned char *) data;
4932   switch (image->blob->type)
4933   {
4934     case UndefinedStream:
4935       break;
4936     case StandardStream:
4937     case FileStream:
4938     case PipeStream:
4939     {
4940       switch (length)
4941       {
4942         default:
4943         {
4944           count=(ssize_t) fwrite((const char *) data,1,length,
4945             image->blob->file_info.file);
4946           break;
4947         }
4948         case 4:
4949         {
4950           c=putc((int) *p++,image->blob->file_info.file);
4951           if (c == EOF)
4952             break;
4953           count++;
4954         }
4955         case 3:
4956         {
4957           c=putc((int) *p++,image->blob->file_info.file);
4958           if (c == EOF)
4959             break;
4960           count++;
4961         }
4962         case 2:
4963         {
4964           c=putc((int) *p++,image->blob->file_info.file);
4965           if (c == EOF)
4966             break;
4967           count++;
4968         }
4969         case 1:
4970         {
4971           c=putc((int) *p++,image->blob->file_info.file);
4972           if (c == EOF)
4973             break;
4974           count++;
4975         }
4976         case 0:
4977           break;
4978       }
4979       break;
4980     }
4981     case ZipStream:
4982     {
4983 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4984       switch (length)
4985       {
4986         default:
4987         {
4988           count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
4989             (unsigned int) length);
4990           break;
4991         }
4992         case 4:
4993         {
4994           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4995           if (c == EOF)
4996             break;
4997           count++;
4998         }
4999         case 3:
5000         {
5001           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5002           if (c == EOF)
5003             break;
5004           count++;
5005         }
5006         case 2:
5007         {
5008           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5009           if (c == EOF)
5010             break;
5011           count++;
5012         }
5013         case 1:
5014         {
5015           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5016           if (c == EOF)
5017             break;
5018           count++;
5019         }
5020         case 0:
5021           break;
5022       }
5023 #endif
5024       break;
5025     }
5026     case BZipStream:
5027     {
5028 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5029       count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
5030         (int) length);
5031 #endif
5032       break;
5033     }
5034     case FifoStream:
5035     {
5036       count=(ssize_t) image->blob->stream(image,data,length);
5037       break;
5038     }
5039     case BlobStream:
5040     {
5041       register unsigned char
5042         *q;
5043
5044       if ((image->blob->offset+(MagickOffsetType) length) >=
5045           (MagickOffsetType) image->blob->extent)
5046         {
5047           if (image->blob->mapped != MagickFalse)
5048             return(0);
5049           image->blob->extent+=length+image->blob->quantum;
5050           image->blob->quantum<<=1;
5051           image->blob->data=(unsigned char *) ResizeQuantumMemory(
5052             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
5053           (void) SyncBlob(image);
5054           if (image->blob->data == (unsigned char *) NULL)
5055             {
5056               (void) DetachBlob(image->blob);
5057               return(0);
5058             }
5059         }
5060       q=image->blob->data+image->blob->offset;
5061       (void) memcpy(q,p,length);
5062       image->blob->offset+=length;
5063       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
5064         image->blob->length=(size_t) image->blob->offset;
5065       count=(ssize_t) length;
5066       break;
5067     }
5068     case UserStream:
5069     {
5070       count=image->blob->user_info->handler((const unsigned char *) data,
5071         length,image->blob->user_info->data);
5072       break;
5073     }
5074   }
5075   return(count);
5076 }
5077 \f
5078 /*
5079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5080 %                                                                             %
5081 %                                                                             %
5082 %                                                                             %
5083 +  W r i t e B l o b B y t e                                                  %
5084 %                                                                             %
5085 %                                                                             %
5086 %                                                                             %
5087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5088 %
5089 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
5090 %  written (either 0 or 1);
5091 %
5092 %  The format of the WriteBlobByte method is:
5093 %
5094 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
5095 %
5096 %  A description of each parameter follows.
5097 %
5098 %    o image: the image.
5099 %
5100 %    o value: Specifies the value to write.
5101 %
5102 */
5103 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5104 {
5105   assert(image != (Image *) NULL);
5106   assert(image->signature == MagickCoreSignature);
5107   return(WriteBlobStream(image,1,&value));
5108 }
5109 \f
5110 /*
5111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5112 %                                                                             %
5113 %                                                                             %
5114 %                                                                             %
5115 +  W r i t e B l o b F l o a t                                                %
5116 %                                                                             %
5117 %                                                                             %
5118 %                                                                             %
5119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5120 %
5121 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5122 %  specified by the endian member of the image structure.
5123 %
5124 %  The format of the WriteBlobFloat method is:
5125 %
5126 %      ssize_t WriteBlobFloat(Image *image,const float value)
5127 %
5128 %  A description of each parameter follows.
5129 %
5130 %    o image: the image.
5131 %
5132 %    o value: Specifies the value to write.
5133 %
5134 */
5135 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5136 {
5137   union
5138   {
5139     unsigned int
5140       unsigned_value;
5141
5142     float
5143       float_value;
5144   } quantum;
5145
5146   quantum.unsigned_value=0U;
5147   quantum.float_value=value;
5148   return(WriteBlobLong(image,quantum.unsigned_value));
5149 }
5150 \f
5151 /*
5152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5153 %                                                                             %
5154 %                                                                             %
5155 %                                                                             %
5156 +  W r i t e B l o b L o n g                                                  %
5157 %                                                                             %
5158 %                                                                             %
5159 %                                                                             %
5160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5161 %
5162 %  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5163 %  byte-order specified by the endian member of the image structure.
5164 %
5165 %  The format of the WriteBlobLong method is:
5166 %
5167 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
5168 %
5169 %  A description of each parameter follows.
5170 %
5171 %    o image: the image.
5172 %
5173 %    o value: Specifies the value to write.
5174 %
5175 */
5176 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5177 {
5178   unsigned char
5179     buffer[4];
5180
5181   assert(image != (Image *) NULL);
5182   assert(image->signature == MagickCoreSignature);
5183   if (image->endian == LSBEndian)
5184     {
5185       buffer[0]=(unsigned char) value;
5186       buffer[1]=(unsigned char) (value >> 8);
5187       buffer[2]=(unsigned char) (value >> 16);
5188       buffer[3]=(unsigned char) (value >> 24);
5189       return(WriteBlobStream(image,4,buffer));
5190     }
5191   buffer[0]=(unsigned char) (value >> 24);
5192   buffer[1]=(unsigned char) (value >> 16);
5193   buffer[2]=(unsigned char) (value >> 8);
5194   buffer[3]=(unsigned char) value;
5195   return(WriteBlobStream(image,4,buffer));
5196 }
5197 \f
5198 /*
5199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5200 %                                                                             %
5201 %                                                                             %
5202 %                                                                             %
5203 +   W r i t e B l o b S h o r t                                               %
5204 %                                                                             %
5205 %                                                                             %
5206 %                                                                             %
5207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5208 %
5209 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
5210 %  byte-order specified by the endian member of the image structure.
5211 %
5212 %  The format of the WriteBlobShort method is:
5213 %
5214 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
5215 %
5216 %  A description of each parameter follows.
5217 %
5218 %    o image: the image.
5219 %
5220 %    o value:  Specifies the value to write.
5221 %
5222 */
5223 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5224 {
5225   unsigned char
5226     buffer[2];
5227
5228   assert(image != (Image *) NULL);
5229   assert(image->signature == MagickCoreSignature);
5230   if (image->endian == LSBEndian)
5231     {
5232       buffer[0]=(unsigned char) value;
5233       buffer[1]=(unsigned char) (value >> 8);
5234       return(WriteBlobStream(image,2,buffer));
5235     }
5236   buffer[0]=(unsigned char) (value >> 8);
5237   buffer[1]=(unsigned char) value;
5238   return(WriteBlobStream(image,2,buffer));
5239 }
5240 \f
5241 /*
5242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5243 %                                                                             %
5244 %                                                                             %
5245 %                                                                             %
5246 +  W r i t e B l o b L S B L o n g                                            %
5247 %                                                                             %
5248 %                                                                             %
5249 %                                                                             %
5250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5251 %
5252 %  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
5253 %  least-significant byte first order.
5254 %
5255 %  The format of the WriteBlobLSBLong method is:
5256 %
5257 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5258 %
5259 %  A description of each parameter follows.
5260 %
5261 %    o image: the image.
5262 %
5263 %    o value: Specifies the value to write.
5264 %
5265 */
5266 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5267 {
5268   unsigned char
5269     buffer[4];
5270
5271   assert(image != (Image *) NULL);
5272   assert(image->signature == MagickCoreSignature);
5273   buffer[0]=(unsigned char) value;
5274   buffer[1]=(unsigned char) (value >> 8);
5275   buffer[2]=(unsigned char) (value >> 16);
5276   buffer[3]=(unsigned char) (value >> 24);
5277   return(WriteBlobStream(image,4,buffer));
5278 }
5279 \f
5280 /*
5281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5282 %                                                                             %
5283 %                                                                             %
5284 %                                                                             %
5285 +   W r i t e B l o b L S B S h o r t                                         %
5286 %                                                                             %
5287 %                                                                             %
5288 %                                                                             %
5289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5290 %
5291 %  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
5292 %  least-significant byte first order.
5293 %
5294 %  The format of the WriteBlobLSBShort method is:
5295 %
5296 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5297 %
5298 %  A description of each parameter follows.
5299 %
5300 %    o image: the image.
5301 %
5302 %    o value:  Specifies the value to write.
5303 %
5304 */
5305 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5306 {
5307   unsigned char
5308     buffer[2];
5309
5310   assert(image != (Image *) NULL);
5311   assert(image->signature == MagickCoreSignature);
5312   buffer[0]=(unsigned char) value;
5313   buffer[1]=(unsigned char) (value >> 8);
5314   return(WriteBlobStream(image,2,buffer));
5315 }
5316 \f
5317 /*
5318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5319 %                                                                             %
5320 %                                                                             %
5321 %                                                                             %
5322 +  W r i t e B l o b L S B S i g n e d L o n g                                %
5323 %                                                                             %
5324 %                                                                             %
5325 %                                                                             %
5326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5327 %
5328 %  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
5329 %  least-significant byte first order.
5330 %
5331 %  The format of the WriteBlobLSBSignedLong method is:
5332 %
5333 %      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5334 %
5335 %  A description of each parameter follows.
5336 %
5337 %    o image: the image.
5338 %
5339 %    o value: Specifies the value to write.
5340 %
5341 */
5342 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5343 {
5344   union
5345   {
5346     unsigned int
5347       unsigned_value;
5348
5349     signed int
5350       signed_value;
5351   } quantum;
5352
5353   unsigned char
5354     buffer[4];
5355
5356   assert(image != (Image *) NULL);
5357   assert(image->signature == MagickCoreSignature);
5358   quantum.signed_value=value;
5359   buffer[0]=(unsigned char) quantum.unsigned_value;
5360   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5361   buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5362   buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5363   return(WriteBlobStream(image,4,buffer));
5364 }
5365 \f
5366 /*
5367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5368 %                                                                             %
5369 %                                                                             %
5370 %                                                                             %
5371 +   W r i t e B l o b L S B S i g n e d S h o r t                             %
5372 %                                                                             %
5373 %                                                                             %
5374 %                                                                             %
5375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5376 %
5377 %  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
5378 %  in least-significant byte first order.
5379 %
5380 %  The format of the WriteBlobLSBSignedShort method is:
5381 %
5382 %      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
5383 %
5384 %  A description of each parameter follows.
5385 %
5386 %    o image: the image.
5387 %
5388 %    o value:  Specifies the value to write.
5389 %
5390 */
5391 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
5392   const signed short value)
5393 {
5394   union
5395   {
5396     unsigned short
5397       unsigned_value;
5398
5399     signed short
5400       signed_value;
5401   } quantum;
5402
5403   unsigned char
5404     buffer[2];
5405
5406   assert(image != (Image *) NULL);
5407   assert(image->signature == MagickCoreSignature);
5408   quantum.signed_value=value;
5409   buffer[0]=(unsigned char) quantum.unsigned_value;
5410   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5411   return(WriteBlobStream(image,2,buffer));
5412 }
5413 \f
5414 /*
5415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5416 %                                                                             %
5417 %                                                                             %
5418 %                                                                             %
5419 +  W r i t e B l o b M S B L o n g                                            %
5420 %                                                                             %
5421 %                                                                             %
5422 %                                                                             %
5423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5424 %
5425 %  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
5426 %  most-significant byte first order.
5427 %
5428 %  The format of the WriteBlobMSBLong method is:
5429 %
5430 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5431 %
5432 %  A description of each parameter follows.
5433 %
5434 %    o value:  Specifies the value to write.
5435 %
5436 %    o image: the image.
5437 %
5438 */
5439 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5440 {
5441   unsigned char
5442     buffer[4];
5443
5444   assert(image != (Image *) NULL);
5445   assert(image->signature == MagickCoreSignature);
5446   buffer[0]=(unsigned char) (value >> 24);
5447   buffer[1]=(unsigned char) (value >> 16);
5448   buffer[2]=(unsigned char) (value >> 8);
5449   buffer[3]=(unsigned char) value;
5450   return(WriteBlobStream(image,4,buffer));
5451 }
5452 \f
5453 /*
5454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5455 %                                                                             %
5456 %                                                                             %
5457 %                                                                             %
5458 +  W r i t e B l o b M S B L o n g L o n g                                    %
5459 %                                                                             %
5460 %                                                                             %
5461 %                                                                             %
5462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5463 %
5464 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
5465 %  most-significant byte first order.
5466 %
5467 %  The format of the WriteBlobMSBLongLong method is:
5468 %
5469 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
5470 %
5471 %  A description of each parameter follows.
5472 %
5473 %    o value:  Specifies the value to write.
5474 %
5475 %    o image: the image.
5476 %
5477 */
5478 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
5479   const MagickSizeType value)
5480 {
5481   unsigned char
5482     buffer[8];
5483
5484   assert(image != (Image *) NULL);
5485   assert(image->signature == MagickCoreSignature);
5486   buffer[0]=(unsigned char) (value >> 56);
5487   buffer[1]=(unsigned char) (value >> 48);
5488   buffer[2]=(unsigned char) (value >> 40);
5489   buffer[3]=(unsigned char) (value >> 32);
5490   buffer[4]=(unsigned char) (value >> 24);
5491   buffer[5]=(unsigned char) (value >> 16);
5492   buffer[6]=(unsigned char) (value >> 8);
5493   buffer[7]=(unsigned char) value;
5494   return(WriteBlobStream(image,8,buffer));
5495 }
5496 \f
5497 /*
5498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5499 %                                                                             %
5500 %                                                                             %
5501 %                                                                             %
5502 +  W r i t e B l o b M S B S i g n e d L o n g                                %
5503 %                                                                             %
5504 %                                                                             %
5505 %                                                                             %
5506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5507 %
5508 %  WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
5509 %  most-significant byte first order.
5510 %
5511 %  The format of the WriteBlobMSBSignedLong method is:
5512 %
5513 %      ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5514 %
5515 %  A description of each parameter follows.
5516 %
5517 %    o image: the image.
5518 %
5519 %    o value: Specifies the value to write.
5520 %
5521 */
5522 MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5523 {
5524   union
5525   {
5526     unsigned int
5527       unsigned_value;
5528
5529     signed int
5530       signed_value;
5531   } quantum;
5532
5533   unsigned char
5534     buffer[4];
5535
5536   assert(image != (Image *) NULL);
5537   assert(image->signature == MagickCoreSignature);
5538   quantum.signed_value=value;
5539   buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5540   buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5541   buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5542   buffer[3]=(unsigned char) quantum.unsigned_value;
5543   return(WriteBlobStream(image,4,buffer));
5544 }
5545 \f
5546 /*
5547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5548 %                                                                             %
5549 %                                                                             %
5550 %                                                                             %
5551 +   W r i t e B l o b M S B S i g n e d S h o r t                             %
5552 %                                                                             %
5553 %                                                                             %
5554 %                                                                             %
5555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5556 %
5557 %  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5558 %  in most-significant byte first order.
5559 %
5560 %  The format of the WriteBlobMSBSignedShort method is:
5561 %
5562 %      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5563 %
5564 %  A description of each parameter follows.
5565 %
5566 %    o image: the image.
5567 %
5568 %    o value:  Specifies the value to write.
5569 %
5570 */
5571 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
5572   const signed short value)
5573 {
5574   union
5575   {
5576     unsigned short
5577       unsigned_value;
5578
5579     signed short
5580       signed_value;
5581   } quantum;
5582
5583   unsigned char
5584     buffer[2];
5585
5586   assert(image != (Image *) NULL);
5587   assert(image->signature == MagickCoreSignature);
5588   quantum.signed_value=value;
5589   buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5590   buffer[1]=(unsigned char) quantum.unsigned_value;
5591   return(WriteBlobStream(image,2,buffer));
5592 }
5593 \f
5594 /*
5595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5596 %                                                                             %
5597 %                                                                             %
5598 %                                                                             %
5599 +  W r i t e B l o b M S B S h o r t                                          %
5600 %                                                                             %
5601 %                                                                             %
5602 %                                                                             %
5603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5604 %
5605 %  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
5606 %  most-significant byte first order.
5607 %
5608 %  The format of the WriteBlobMSBShort method is:
5609 %
5610 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5611 %
5612 %  A description of each parameter follows.
5613 %
5614 %   o  value:  Specifies the value to write.
5615 %
5616 %   o  file:  Specifies the file to write the data to.
5617 %
5618 */
5619 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5620 {
5621   unsigned char
5622     buffer[2];
5623
5624   assert(image != (Image *) NULL);
5625   assert(image->signature == MagickCoreSignature);
5626   buffer[0]=(unsigned char) (value >> 8);
5627   buffer[1]=(unsigned char) value;
5628   return(WriteBlobStream(image,2,buffer));
5629 }
5630 \f
5631 /*
5632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5633 %                                                                             %
5634 %                                                                             %
5635 %                                                                             %
5636 +  W r i t e B l o b S t r i n g                                              %
5637 %                                                                             %
5638 %                                                                             %
5639 %                                                                             %
5640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5641 %
5642 %  WriteBlobString() write a string to a blob.  It returns the number of
5643 %  characters written.
5644 %
5645 %  The format of the WriteBlobString method is:
5646 %
5647 %      ssize_t WriteBlobString(Image *image,const char *string)
5648 %
5649 %  A description of each parameter follows.
5650 %
5651 %    o image: the image.
5652 %
5653 %    o string: Specifies the string to write.
5654 %
5655 */
5656 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
5657 {
5658   assert(image != (Image *) NULL);
5659   assert(image->signature == MagickCoreSignature);
5660   assert(string != (const char *) NULL);
5661   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
5662 }