]> granicus.if.org Git - imagemagick/blob - MagickCore/blob.c
Removed assert for the writer.
[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->reader != (BlobHandler) NULL);
1681   assert(user_info->writer != (BlobHandler) NULL);
1682   assert(exception != (ExceptionInfo *) NULL);
1683   blob_info=CloneImageInfo(image_info);
1684   blob_info->adjoin=MagickFalse;
1685   blob_info->user_info=user_info;
1686   (void) SetImageInfo(blob_info,1,exception);
1687   if (*blob_info->magick != '\0')
1688     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1689   magick_info=GetMagickInfo(image->magick,exception);
1690   if (magick_info == (const MagickInfo *) NULL)
1691     {
1692       (void) ThrowMagickException(exception,GetMagickModule(),
1693         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1694         image->magick);
1695       blob_info=DestroyImageInfo(blob_info);
1696       return;
1697     }
1698   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
1699   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1700     {
1701       /*
1702         Native blob support for this image format.
1703       */
1704       (void) CloseBlob(image);
1705       *image->filename='\0';
1706       (void) WriteImage(blob_info,image,exception);
1707       (void) CloseBlob(image);
1708     }
1709   else
1710     {
1711       char
1712         unique[MagickPathExtent];
1713
1714       int
1715         file;
1716
1717       unsigned char
1718         *blob;
1719
1720       /*
1721         Write file to disk in blob image format.
1722       */
1723       blob_info->user_info=(UserBlobInfo *) NULL;
1724       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
1725         sizeof(*blob));
1726       if (blob == (unsigned char *) NULL)
1727         {
1728           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1729             image_info->filename);
1730           blob_info=DestroyImageInfo(blob_info);
1731           return;
1732         }
1733       file=AcquireUniqueFileResource(unique);
1734       if (file == -1)
1735         {
1736           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1737             image_info->filename);
1738           blob=(unsigned char *) RelinquishMagickMemory(blob);
1739           blob_info=DestroyImageInfo(blob_info);
1740           return;
1741         }
1742       blob_info->file=fdopen(file,"wb+");
1743       if (blob_info->file != (FILE *) NULL)
1744         {
1745           ssize_t
1746             count;
1747
1748           (void) FormatLocaleString(image->filename,MagickPathExtent,
1749             "%s:%s",image->magick,unique);
1750           status=WriteImage(blob_info,image,exception);
1751           (void) CloseBlob(image);
1752           if (status != MagickFalse)
1753             {
1754               (void) fseek(blob_info->file,0,SEEK_SET);
1755               count=(ssize_t) MagickMaxBufferExtent;
1756               while (count == (ssize_t) MagickMaxBufferExtent)
1757               {
1758                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
1759                   blob_info->file);
1760                 user_info->writer(blob,count,user_info->data);
1761               }
1762             }
1763           (void) fclose(blob_info->file);
1764         }
1765       blob=(unsigned char *) RelinquishMagickMemory(blob);
1766       (void) RelinquishUniqueFileResource(unique);
1767     }
1768   blob_info=DestroyImageInfo(blob_info);
1769 }
1770 \f
1771 /*
1772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773 %                                                                             %
1774 %                                                                             %
1775 %                                                                             %
1776 %   I m a g e T o F i l e                                                     %
1777 %                                                                             %
1778 %                                                                             %
1779 %                                                                             %
1780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 %
1782 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
1783 %  occurs otherwise MagickTrue.
1784 %
1785 %  The format of the ImageToFile method is:
1786 %
1787 %       MagickBooleanType ImageToFile(Image *image,char *filename,
1788 %         ExceptionInfo *exception)
1789 %
1790 %  A description of each parameter follows:
1791 %
1792 %    o image: the image.
1793 %
1794 %    o filename: Write the image to this file.
1795 %
1796 %    o exception: return any errors or warnings in this structure.
1797 %
1798 */
1799 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1800   ExceptionInfo *exception)
1801 {
1802   int
1803     file;
1804
1805   register const unsigned char
1806     *p;
1807
1808   register size_t
1809     i;
1810
1811   size_t
1812     length,
1813     quantum;
1814
1815   ssize_t
1816     count;
1817
1818   struct stat
1819     file_stats;
1820
1821   unsigned char
1822     *buffer;
1823
1824   assert(image != (Image *) NULL);
1825   assert(image->signature == MagickCoreSignature);
1826   assert(image->blob != (BlobInfo *) NULL);
1827   assert(image->blob->type != UndefinedStream);
1828   if (image->debug != MagickFalse)
1829     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1830   assert(filename != (const char *) NULL);
1831   if (*filename == '\0')
1832     file=AcquireUniqueFileResource(filename);
1833   else
1834     if (LocaleCompare(filename,"-") == 0)
1835       file=fileno(stdout);
1836     else
1837       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1838   if (file == -1)
1839     {
1840       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1841       return(MagickFalse);
1842     }
1843   quantum=(size_t) MagickMaxBufferExtent;
1844   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1845     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1846   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1847   if (buffer == (unsigned char *) NULL)
1848     {
1849       file=close(file)-1;
1850       (void) ThrowMagickException(exception,GetMagickModule(),
1851         ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1852       return(MagickFalse);
1853     }
1854   length=0;
1855   p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1856   for (i=0; count > 0; )
1857   {
1858     length=(size_t) count;
1859     for (i=0; i < length; i+=count)
1860     {
1861       count=write(file,p+i,(size_t) (length-i));
1862       if (count <= 0)
1863         {
1864           count=0;
1865           if (errno != EINTR)
1866             break;
1867         }
1868     }
1869     if (i < length)
1870       break;
1871     p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1872   }
1873   if (LocaleCompare(filename,"-") != 0)
1874     file=close(file);
1875   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1876   if ((file == -1) || (i < length))
1877     {
1878       if (file != -1)
1879         file=close(file);
1880       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1881       return(MagickFalse);
1882     }
1883   return(MagickTrue);
1884 }
1885 \f
1886 /*
1887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1888 %                                                                             %
1889 %                                                                             %
1890 %                                                                             %
1891 %   I m a g e s T o B l o b                                                   %
1892 %                                                                             %
1893 %                                                                             %
1894 %                                                                             %
1895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1896 %
1897 %  ImagesToBlob() implements direct to memory image formats.  It returns the
1898 %  image sequence as a blob and its length.  The magick member of the ImageInfo
1899 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
1900 %
1901 %  Note, some image formats do not permit multiple images to the same image
1902 %  stream (e.g. JPEG).  in this instance, just the first image of the
1903 %  sequence is returned as a blob.
1904 %
1905 %  The format of the ImagesToBlob method is:
1906 %
1907 %      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1908 %        size_t *length,ExceptionInfo *exception)
1909 %
1910 %  A description of each parameter follows:
1911 %
1912 %    o image_info: the image info.
1913 %
1914 %    o images: the image list.
1915 %
1916 %    o length: return the actual length of the blob.
1917 %
1918 %    o exception: return any errors or warnings in this structure.
1919 %
1920 */
1921 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1922   size_t *length,ExceptionInfo *exception)
1923 {
1924   const MagickInfo
1925     *magick_info;
1926
1927   ImageInfo
1928     *blob_info;
1929
1930   MagickBooleanType
1931     status;
1932
1933   void
1934     *blob;
1935
1936   assert(image_info != (const ImageInfo *) NULL);
1937   assert(image_info->signature == MagickCoreSignature);
1938   if (image_info->debug != MagickFalse)
1939     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1940       image_info->filename);
1941   assert(images != (Image *) NULL);
1942   assert(images->signature == MagickCoreSignature);
1943   assert(exception != (ExceptionInfo *) NULL);
1944   *length=0;
1945   blob=(unsigned char *) NULL;
1946   blob_info=CloneImageInfo(image_info);
1947   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1948     exception);
1949   if (*blob_info->magick != '\0')
1950     (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
1951   magick_info=GetMagickInfo(images->magick,exception);
1952   if (magick_info == (const MagickInfo *) NULL)
1953     {
1954       (void) ThrowMagickException(exception,GetMagickModule(),
1955         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1956         images->magick);
1957       blob_info=DestroyImageInfo(blob_info);
1958       return(blob);
1959     }
1960   if (GetMagickAdjoin(magick_info) == MagickFalse)
1961     {
1962       blob_info=DestroyImageInfo(blob_info);
1963       return(ImageToBlob(image_info,images,length,exception));
1964     }
1965   (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
1966   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1967     {
1968       /*
1969         Native blob support for this images format.
1970       */
1971       blob_info->length=0;
1972       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
1973         sizeof(unsigned char));
1974       if (blob_info->blob == (void *) NULL)
1975         (void) ThrowMagickException(exception,GetMagickModule(),
1976           ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
1977       else
1978         {
1979           (void) CloseBlob(images);
1980           images->blob->exempt=MagickTrue;
1981           *images->filename='\0';
1982           status=WriteImages(blob_info,images,images->filename,exception);
1983           *length=images->blob->length;
1984           blob=DetachBlob(images->blob);
1985           if (status == MagickFalse)
1986             blob=RelinquishMagickMemory(blob);
1987           else
1988             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
1989         }
1990     }
1991   else
1992     {
1993       char
1994         filename[MagickPathExtent],
1995         unique[MagickPathExtent];
1996
1997       int
1998         file;
1999
2000       /*
2001         Write file to disk in blob images format.
2002       */
2003       file=AcquireUniqueFileResource(unique);
2004       if (file == -1)
2005         {
2006           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2007             image_info->filename);
2008         }
2009       else
2010         {
2011           blob_info->file=fdopen(file,"wb");
2012           if (blob_info->file != (FILE *) NULL)
2013             {
2014               (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2015                 images->magick,unique);
2016               status=WriteImages(blob_info,images,filename,exception);
2017               (void) CloseBlob(images);
2018               (void) fclose(blob_info->file);
2019               if (status != MagickFalse)
2020                 blob=FileToBlob(unique,~0UL,length,exception);
2021             }
2022           (void) RelinquishUniqueFileResource(unique);
2023         }
2024     }
2025   blob_info=DestroyImageInfo(blob_info);
2026   return(blob);
2027 }
2028 \f
2029 /*
2030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2031 %                                                                             %
2032 %                                                                             %
2033 %                                                                             %
2034 +  I m a g e s T o U s e r B l o b                                            %
2035 %                                                                             %
2036 %                                                                             %
2037 %                                                                             %
2038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2039 %
2040 %  ImagesToUserBlob() is the equivalent of WriteImages(), but writes the
2041 %  formatted "file" to the suplied method rather than to an actual file.
2042 %
2043 %  The format of the ImageToUserBlob method is:
2044 %
2045 %      void ImagesToUserBlob(const ImageInfo *image_info,Image *images,
2046 %        UserBlobInfo *user_info,ExceptionInfo *exception)
2047 %
2048 %  A description of each parameter follows:
2049 %
2050 %    o image_info: the image info.
2051 %
2052 %    o images: the image list.
2053 %
2054 %    o user_info: the methods to use when writing and seeking.
2055 %
2056 %    o exception: return any errors or warnings in this structure.
2057 %
2058 */
2059 MagickExport void ImagesToUserBlob(const ImageInfo *image_info,Image *images,
2060   UserBlobInfo *user_info,ExceptionInfo *exception)
2061 {
2062   const MagickInfo
2063     *magick_info;
2064
2065   ImageInfo
2066     *blob_info;
2067
2068   MagickBooleanType
2069     status;
2070
2071   assert(image_info != (const ImageInfo *) NULL);
2072   assert(image_info->signature == MagickCoreSignature);
2073   if (image_info->debug != MagickFalse)
2074     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2075       image_info->filename);
2076   assert(images != (Image *) NULL);
2077   assert(images->signature == MagickCoreSignature);
2078   assert(user_info != (UserBlobInfo *) NULL);
2079   assert(user_info->reader != (BlobHandler) NULL);
2080   assert(user_info->writer != (BlobHandler) NULL);
2081   assert(exception != (ExceptionInfo *) NULL);
2082   blob_info=CloneImageInfo(image_info);
2083   blob_info->user_info=user_info;
2084   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2085     exception);
2086   if (*blob_info->magick != '\0')
2087     (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2088   magick_info=GetMagickInfo(images->magick,exception);
2089   if (magick_info == (const MagickInfo *) NULL)
2090     {
2091       (void) ThrowMagickException(exception,GetMagickModule(),
2092         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2093         images->magick);
2094       blob_info=DestroyImageInfo(blob_info);
2095       return;
2096     }
2097   (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2098   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2099     {
2100       /*
2101         Native blob support for this image format.
2102       */
2103       (void) CloseBlob(images);
2104       *images->filename='\0';
2105       (void) WriteImages(blob_info,images,images->filename,exception);
2106       (void) CloseBlob(images);
2107     }
2108   else
2109     {
2110       char
2111         filename[MagickPathExtent],
2112         unique[MagickPathExtent];
2113
2114       int
2115         file;
2116
2117       unsigned char
2118         *blob;
2119
2120       /*
2121         Write file to disk in blob image format.
2122       */
2123       blob_info->user_info=(UserBlobInfo *) NULL;
2124       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2125         sizeof(*blob));
2126       if (blob == (unsigned char *) NULL)
2127         {
2128           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2129             image_info->filename);
2130           blob_info=DestroyImageInfo(blob_info);
2131           return;
2132         }
2133       file=AcquireUniqueFileResource(unique);
2134       if (file == -1)
2135         {
2136           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2137             image_info->filename);
2138           blob=(unsigned char *) RelinquishMagickMemory(blob);
2139           blob_info=DestroyImageInfo(blob_info);
2140           return;
2141         }
2142       blob_info->file=fdopen(file,"wb+");
2143       if (blob_info->file != (FILE *) NULL)
2144         {
2145           ssize_t
2146             count;
2147
2148           (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2149             images->magick,unique);
2150           status=WriteImages(blob_info,images,filename,exception);
2151           (void) CloseBlob(images);
2152           if (status != MagickFalse)
2153             {
2154               (void) fseek(blob_info->file,0,SEEK_SET);
2155               count=(ssize_t) MagickMaxBufferExtent;
2156               while (count == (ssize_t) MagickMaxBufferExtent)
2157               {
2158                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2159                   blob_info->file);
2160                 user_info->writer(blob,count,user_info->data);
2161               }
2162             }
2163           (void) fclose(blob_info->file);
2164         }
2165       blob=(unsigned char *) RelinquishMagickMemory(blob);
2166       (void) RelinquishUniqueFileResource(unique);
2167     }
2168   blob_info=DestroyImageInfo(blob_info);
2169   return;
2170 }
2171 \f
2172 /*
2173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2174 %                                                                             %
2175 %                                                                             %
2176 %                                                                             %
2177 %   I n j e c t I m a g e B l o b                                             %
2178 %                                                                             %
2179 %                                                                             %
2180 %                                                                             %
2181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2182 %
2183 %  InjectImageBlob() injects the image with a copy of itself in the specified
2184 %  format (e.g. inject JPEG into a PDF image).
2185 %
2186 %  The format of the InjectImageBlob method is:
2187 %
2188 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2189 %        Image *image,Image *inject_image,const char *format,
2190 %        ExceptionInfo *exception)
2191 %
2192 %  A description of each parameter follows:
2193 %
2194 %    o image_info: the image info..
2195 %
2196 %    o image: the image.
2197 %
2198 %    o inject_image: inject into the image stream.
2199 %
2200 %    o format: the image format.
2201 %
2202 %    o exception: return any errors or warnings in this structure.
2203 %
2204 */
2205 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2206   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2207 {
2208   char
2209     filename[MagickPathExtent];
2210
2211   FILE
2212     *unique_file;
2213
2214   Image
2215     *byte_image;
2216
2217   ImageInfo
2218     *write_info;
2219
2220   int
2221     file;
2222
2223   MagickBooleanType
2224     status;
2225
2226   register ssize_t
2227     i;
2228
2229   size_t
2230     quantum;
2231
2232   ssize_t
2233     count;
2234
2235   struct stat
2236     file_stats;
2237
2238   unsigned char
2239     *buffer;
2240
2241   /*
2242     Write inject image to a temporary file.
2243   */
2244   assert(image_info != (ImageInfo *) NULL);
2245   assert(image_info->signature == MagickCoreSignature);
2246   assert(image != (Image *) NULL);
2247   assert(image->signature == MagickCoreSignature);
2248   if (image->debug != MagickFalse)
2249     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2250   assert(inject_image != (Image *) NULL);
2251   assert(inject_image->signature == MagickCoreSignature);
2252   assert(exception != (ExceptionInfo *) NULL);
2253   unique_file=(FILE *) NULL;
2254   file=AcquireUniqueFileResource(filename);
2255   if (file != -1)
2256     unique_file=fdopen(file,"wb");
2257   if ((file == -1) || (unique_file == (FILE *) NULL))
2258     {
2259       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2260       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2261         image->filename);
2262       return(MagickFalse);
2263     }
2264   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2265   if (byte_image == (Image *) NULL)
2266     {
2267       (void) fclose(unique_file);
2268       (void) RelinquishUniqueFileResource(filename);
2269       return(MagickFalse);
2270     }
2271   (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",format,
2272     filename);
2273   DestroyBlob(byte_image);
2274   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2275   write_info=CloneImageInfo(image_info);
2276   SetImageInfoFile(write_info,unique_file);
2277   status=WriteImage(write_info,byte_image,exception);
2278   write_info=DestroyImageInfo(write_info);
2279   byte_image=DestroyImage(byte_image);
2280   (void) fclose(unique_file);
2281   if (status == MagickFalse)
2282     {
2283       (void) RelinquishUniqueFileResource(filename);
2284       return(MagickFalse);
2285     }
2286   /*
2287     Inject into image stream.
2288   */
2289   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2290   if (file == -1)
2291     {
2292       (void) RelinquishUniqueFileResource(filename);
2293       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2294         image_info->filename);
2295       return(MagickFalse);
2296     }
2297   quantum=(size_t) MagickMaxBufferExtent;
2298   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2299     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2300   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2301   if (buffer == (unsigned char *) NULL)
2302     {
2303       (void) RelinquishUniqueFileResource(filename);
2304       file=close(file);
2305       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2306         image->filename);
2307     }
2308   for (i=0; ; i+=count)
2309   {
2310     count=read(file,buffer,quantum);
2311     if (count <= 0)
2312       {
2313         count=0;
2314         if (errno != EINTR)
2315           break;
2316       }
2317     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2318       MagickFalse;
2319   }
2320   file=close(file);
2321   if (file == -1)
2322     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2323   (void) RelinquishUniqueFileResource(filename);
2324   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2325   return(status);
2326 }
2327 \f
2328 /*
2329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2330 %                                                                             %
2331 %                                                                             %
2332 %                                                                             %
2333 %   I s B l o b E x e m p t                                                   %
2334 %                                                                             %
2335 %                                                                             %
2336 %                                                                             %
2337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2338 %
2339 %  IsBlobExempt() returns true if the blob is exempt.
2340 %
2341 %  The format of the IsBlobExempt method is:
2342 %
2343 %       MagickBooleanType IsBlobExempt(const Image *image)
2344 %
2345 %  A description of each parameter follows:
2346 %
2347 %    o image: the image.
2348 %
2349 */
2350 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2351 {
2352   assert(image != (const Image *) NULL);
2353   assert(image->signature == MagickCoreSignature);
2354   if (image->debug != MagickFalse)
2355     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2356   return(image->blob->exempt);
2357 }
2358 \f
2359 /*
2360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2361 %                                                                             %
2362 %                                                                             %
2363 %                                                                             %
2364 %   I s B l o b S e e k a b l e                                               %
2365 %                                                                             %
2366 %                                                                             %
2367 %                                                                             %
2368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2369 %
2370 %  IsBlobSeekable() returns true if the blob is seekable.
2371 %
2372 %  The format of the IsBlobSeekable method is:
2373 %
2374 %       MagickBooleanType IsBlobSeekable(const Image *image)
2375 %
2376 %  A description of each parameter follows:
2377 %
2378 %    o image: the image.
2379 %
2380 */
2381 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2382 {
2383   MagickBooleanType
2384     seekable;
2385
2386   assert(image != (const Image *) NULL);
2387   assert(image->signature == MagickCoreSignature);
2388   if (image->debug != MagickFalse)
2389     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2390   switch (image->blob->type)
2391   {
2392     case FileStream:
2393     case BlobStream:
2394     case ZipStream:
2395     {
2396       seekable=MagickTrue;
2397       break;
2398     }
2399     case UndefinedStream:
2400     case StandardStream:
2401     case BZipStream:
2402     case FifoStream:
2403     case PipeStream:
2404     default:
2405     {
2406       seekable=MagickFalse;
2407       break;
2408     }
2409     case UserStream:
2410     {
2411       if ((image->blob->user_info->seeker != (BlobSeeker) NULL) &&
2412           (image->blob->user_info->teller != (BlobTeller) NULL))
2413         seekable=MagickTrue;
2414       else
2415         seekable=MagickFalse;
2416       break;
2417     }
2418   }
2419   return(seekable);
2420 }
2421 \f
2422 /*
2423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2424 %                                                                             %
2425 %                                                                             %
2426 %                                                                             %
2427 %   I s B l o b T e m p o r a r y                                             %
2428 %                                                                             %
2429 %                                                                             %
2430 %                                                                             %
2431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2432 %
2433 %  IsBlobTemporary() returns true if the blob is temporary.
2434 %
2435 %  The format of the IsBlobTemporary method is:
2436 %
2437 %       MagickBooleanType IsBlobTemporary(const Image *image)
2438 %
2439 %  A description of each parameter follows:
2440 %
2441 %    o image: the image.
2442 %
2443 */
2444 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2445 {
2446   assert(image != (const Image *) NULL);
2447   assert(image->signature == MagickCoreSignature);
2448   if (image->debug != MagickFalse)
2449     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2450   return(image->blob->temporary);
2451 }
2452 \f
2453 /*
2454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2455 %                                                                             %
2456 %                                                                             %
2457 %                                                                             %
2458 +  M a p B l o b                                                              %
2459 %                                                                             %
2460 %                                                                             %
2461 %                                                                             %
2462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2463 %
2464 %  MapBlob() creates a mapping from a file to a binary large object.
2465 %
2466 %  The format of the MapBlob method is:
2467 %
2468 %      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2469 %        const size_t length)
2470 %
2471 %  A description of each parameter follows:
2472 %
2473 %    o file: map this file descriptor.
2474 %
2475 %    o mode: ReadMode, WriteMode, or IOMode.
2476 %
2477 %    o offset: starting at this offset within the file.
2478 %
2479 %    o length: the length of the mapping is returned in this pointer.
2480 %
2481 */
2482 MagickExport void *MapBlob(int file,const MapMode mode,
2483   const MagickOffsetType offset,const size_t length)
2484 {
2485 #if defined(MAGICKCORE_HAVE_MMAP)
2486   int
2487     flags,
2488     protection;
2489
2490   void
2491     *map;
2492
2493   /*
2494     Map file.
2495   */
2496   flags=0;
2497   if (file == -1)
2498 #if defined(MAP_ANONYMOUS)
2499     flags|=MAP_ANONYMOUS;
2500 #else
2501     return(NULL);
2502 #endif
2503   switch (mode)
2504   {
2505     case ReadMode:
2506     default:
2507     {
2508       protection=PROT_READ;
2509       flags|=MAP_PRIVATE;
2510       break;
2511     }
2512     case WriteMode:
2513     {
2514       protection=PROT_WRITE;
2515       flags|=MAP_SHARED;
2516       break;
2517     }
2518     case IOMode:
2519     {
2520       protection=PROT_READ | PROT_WRITE;
2521       flags|=MAP_SHARED;
2522       break;
2523     }
2524   }
2525 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2526   map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2527 #else
2528   map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
2529     offset);
2530   if (map == MAP_FAILED)
2531     map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2532 #endif
2533   if (map == MAP_FAILED)
2534     return(NULL);
2535   return(map);
2536 #else
2537   (void) file;
2538   (void) mode;
2539   (void) offset;
2540   (void) length;
2541   return(NULL);
2542 #endif
2543 }
2544 \f
2545 /*
2546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2547 %                                                                             %
2548 %                                                                             %
2549 %                                                                             %
2550 +  M S B O r d e r L o n g                                                    %
2551 %                                                                             %
2552 %                                                                             %
2553 %                                                                             %
2554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2555 %
2556 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
2557 %  most-significant byte first.
2558 %
2559 %  The format of the MSBOrderLong method is:
2560 %
2561 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
2562 %
2563 %  A description of each parameter follows.
2564 %
2565 %   o  buffer:  Specifies a pointer to a buffer of integers.
2566 %
2567 %   o  length:  Specifies the length of the buffer.
2568 %
2569 */
2570 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2571 {
2572   int
2573     c;
2574
2575   register unsigned char
2576     *p,
2577     *q;
2578
2579   assert(buffer != (unsigned char *) NULL);
2580   q=buffer+length;
2581   while (buffer < q)
2582   {
2583     p=buffer+3;
2584     c=(int) (*p);
2585     *p=(*buffer);
2586     *buffer++=(unsigned char) c;
2587     p=buffer+1;
2588     c=(int) (*p);
2589     *p=(*buffer);
2590     *buffer++=(unsigned char) c;
2591     buffer+=2;
2592   }
2593 }
2594 \f
2595 /*
2596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2597 %                                                                             %
2598 %                                                                             %
2599 %                                                                             %
2600 +  M S B O r d e r S h o r t                                                  %
2601 %                                                                             %
2602 %                                                                             %
2603 %                                                                             %
2604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2605 %
2606 %  MSBOrderShort() converts a least-significant byte first buffer of integers
2607 %  to most-significant byte first.
2608 %
2609 %  The format of the MSBOrderShort method is:
2610 %
2611 %      void MSBOrderShort(unsigned char *p,const size_t length)
2612 %
2613 %  A description of each parameter follows.
2614 %
2615 %   o  p:  Specifies a pointer to a buffer of integers.
2616 %
2617 %   o  length:  Specifies the length of the buffer.
2618 %
2619 */
2620 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2621 {
2622   int
2623     c;
2624
2625   register unsigned char
2626     *q;
2627
2628   assert(p != (unsigned char *) NULL);
2629   q=p+length;
2630   while (p < q)
2631   {
2632     c=(int) (*p);
2633     *p=(*(p+1));
2634     p++;
2635     *p++=(unsigned char) c;
2636   }
2637 }
2638 \f
2639 /*
2640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2641 %                                                                             %
2642 %                                                                             %
2643 %                                                                             %
2644 +   O p e n B l o b                                                           %
2645 %                                                                             %
2646 %                                                                             %
2647 %                                                                             %
2648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2649 %
2650 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
2651 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
2652 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2653 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
2654 %  from a system command.
2655 %
2656 %  The format of the OpenBlob method is:
2657 %
2658 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2659 %        const BlobMode mode,ExceptionInfo *exception)
2660 %
2661 %  A description of each parameter follows:
2662 %
2663 %    o image_info: the image info.
2664 %
2665 %    o image: the image.
2666 %
2667 %    o mode: the mode for opening the file.
2668 %
2669 */
2670
2671 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2672   Image *image)
2673 {
2674   const char
2675     *option;
2676
2677   int
2678     status;
2679
2680   size_t
2681     size;
2682
2683   size=16384;
2684   option=GetImageOption(image_info,"stream:buffer-size");
2685   if (option != (const char *) NULL)
2686     size=StringToUnsignedLong(option);
2687   status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2688     _IONBF : _IOFBF,size);
2689   return(status == 0 ? MagickTrue : MagickFalse);
2690 }
2691
2692 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2693   Image *image,const BlobMode mode,ExceptionInfo *exception)
2694 {
2695   char
2696     extension[MagickPathExtent],
2697     filename[MagickPathExtent];
2698
2699   const char
2700     *type;
2701
2702   MagickBooleanType
2703     status;
2704
2705   PolicyRights
2706     rights;
2707
2708   assert(image_info != (ImageInfo *) NULL);
2709   assert(image_info->signature == MagickCoreSignature);
2710   if (image_info->debug != MagickFalse)
2711     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2712       image_info->filename);
2713   assert(image != (Image *) NULL);
2714   assert(image->signature == MagickCoreSignature);
2715   if (image_info->blob != (void *) NULL)
2716     {
2717       if (image_info->stream != (StreamHandler) NULL)
2718         image->blob->stream=(StreamHandler) image_info->stream;
2719       AttachBlob(image->blob,image_info->blob,image_info->length);
2720       return(MagickTrue);
2721     }
2722   if (image_info->user_info != (UserBlobInfo *) NULL)
2723     {
2724       image->blob->type=UserStream;
2725       image->blob->user_info=image_info->user_info;
2726       return(MagickTrue);
2727     }
2728   (void) DetachBlob(image->blob);
2729   switch (mode)
2730   {
2731     default: type="r"; break;
2732     case ReadBlobMode: type="r"; break;
2733     case ReadBinaryBlobMode: type="rb"; break;
2734     case WriteBlobMode: type="w"; break;
2735     case WriteBinaryBlobMode: type="w+b"; break;
2736     case AppendBlobMode: type="a"; break;
2737     case AppendBinaryBlobMode: type="a+b"; break;
2738   }
2739   if (*type != 'r')
2740     image->blob->synchronize=image_info->synchronize;
2741   if (image_info->stream != (StreamHandler) NULL)
2742     {
2743       image->blob->stream=(StreamHandler) image_info->stream;
2744       if (*type == 'w')
2745         {
2746           image->blob->type=FifoStream;
2747           return(MagickTrue);
2748         }
2749     }
2750   /*
2751     Open image file.
2752   */
2753   *filename='\0';
2754   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2755   rights=ReadPolicyRights;
2756   if (*type == 'w')
2757     rights=WritePolicyRights;
2758   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2759     {
2760       errno=EPERM;
2761       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2762         "NotAuthorized","`%s'",filename);
2763       return(MagickFalse);
2764     }
2765   if ((LocaleCompare(filename,"-") == 0) ||
2766       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2767     {
2768       image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2769 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2770       if (strchr(type,'b') != (char *) NULL)
2771         setmode(fileno(image->blob->file_info.file),_O_BINARY);
2772 #endif
2773       image->blob->type=StandardStream;
2774       image->blob->exempt=MagickTrue;
2775       return(SetStreamBuffering(image_info,image));
2776     }
2777   if (LocaleNCompare(filename,"fd:",3) == 0)
2778     {
2779       char
2780         fileMode[MagickPathExtent];
2781
2782       *fileMode =(*type);
2783       fileMode[1]='\0';
2784       image->blob->file_info.file=fdopen(StringToLong(filename+3),fileMode);
2785 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2786       if (strchr(type,'b') != (char *) NULL)
2787         setmode(fileno(image->blob->file_info.file),_O_BINARY);
2788 #endif
2789       image->blob->type=StandardStream;
2790       image->blob->exempt=MagickTrue;
2791       return(SetStreamBuffering(image_info,image));
2792     }
2793 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
2794   if (*filename == '|')
2795     {
2796       char
2797         fileMode[MagickPathExtent],
2798         *sanitize_command;
2799
2800       /*
2801         Pipe image to or from a system command.
2802       */
2803 #if defined(SIGPIPE)
2804       if (*type == 'w')
2805         (void) signal(SIGPIPE,SIG_IGN);
2806 #endif
2807       *fileMode =(*type);
2808       fileMode[1]='\0';
2809       sanitize_command=SanitizeString(filename+1);
2810       image->blob->file_info.file=(FILE *) popen_utf8(sanitize_command,
2811         fileMode);
2812       sanitize_command=DestroyString(sanitize_command);
2813       if (image->blob->file_info.file == (FILE *) NULL)
2814         {
2815           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2816           return(MagickFalse);
2817         }
2818       image->blob->type=PipeStream;
2819       image->blob->exempt=MagickTrue;
2820       return(SetStreamBuffering(image_info,image));
2821     }
2822 #endif
2823   status=GetPathAttributes(filename,&image->blob->properties);
2824 #if defined(S_ISFIFO)
2825   if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
2826     {
2827       image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2828       if (image->blob->file_info.file == (FILE *) NULL)
2829         {
2830           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2831           return(MagickFalse);
2832         }
2833       image->blob->type=FileStream;
2834       image->blob->exempt=MagickTrue;
2835       return(SetStreamBuffering(image_info,image));
2836     }
2837 #endif
2838   GetPathComponent(image->filename,ExtensionPath,extension);
2839   if (*type == 'w')
2840     {
2841       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2842       if ((image_info->adjoin == MagickFalse) ||
2843           (strchr(filename,'%') != (char *) NULL))
2844         {
2845           /*
2846             Form filename for multi-part images.
2847           */
2848           (void) InterpretImageFilename(image_info,image,image->filename,(int)
2849             image->scene,filename,exception);
2850           if ((LocaleCompare(filename,image->filename) == 0) &&
2851               ((GetPreviousImageInList(image) != (Image *) NULL) ||
2852                (GetNextImageInList(image) != (Image *) NULL)))
2853             {
2854               char
2855                 path[MagickPathExtent];
2856
2857               GetPathComponent(image->filename,RootPath,path);
2858               if (*extension == '\0')
2859                 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
2860                   path,(double) image->scene);
2861               else
2862                 (void) FormatLocaleString(filename,MagickPathExtent,
2863                   "%s-%.20g.%s",path,(double) image->scene,extension);
2864             }
2865           (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2866 #if defined(macintosh)
2867           SetApplicationType(filename,image_info->magick,'8BIM');
2868 #endif
2869         }
2870     }
2871   if (image_info->file != (FILE *) NULL)
2872     {
2873       image->blob->file_info.file=image_info->file;
2874       image->blob->type=FileStream;
2875       image->blob->exempt=MagickTrue;
2876     }
2877   else
2878     if (*type == 'r')
2879       {
2880         image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2881         if (image->blob->file_info.file != (FILE *) NULL)
2882           {
2883             size_t
2884               count;
2885
2886             unsigned char
2887               magick[3];
2888
2889             image->blob->type=FileStream;
2890             (void) SetStreamBuffering(image_info,image);
2891             (void) ResetMagickMemory(magick,0,sizeof(magick));
2892             count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2893             (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
2894 #if defined(MAGICKCORE_POSIX_SUPPORT)
2895             (void) fflush(image->blob->file_info.file);
2896 #endif
2897             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2898                "  read %.20g magic header bytes",(double) count);
2899 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2900             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2901                 ((int) magick[2] == 0x08))
2902               {
2903                 if (image->blob->file_info.file != (FILE *) NULL)
2904                   (void) fclose(image->blob->file_info.file);
2905                 image->blob->file_info.file=(FILE *) NULL;
2906                 image->blob->file_info.gzfile=gzopen(filename,type);
2907                 if (image->blob->file_info.gzfile != (gzFile) NULL)
2908                   image->blob->type=ZipStream;
2909                }
2910 #endif
2911 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2912             if (strncmp((char *) magick,"BZh",3) == 0)
2913               {
2914                 if (image->blob->file_info.file != (FILE *) NULL)
2915                   (void) fclose(image->blob->file_info.file);
2916                 image->blob->file_info.file=(FILE *) NULL;
2917                 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2918                 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2919                   image->blob->type=BZipStream;
2920               }
2921 #endif
2922             if (image->blob->type == FileStream)
2923               {
2924                 const MagickInfo
2925                   *magick_info;
2926
2927                 ExceptionInfo
2928                   *sans_exception;
2929
2930                 size_t
2931                   length;
2932
2933                 sans_exception=AcquireExceptionInfo();
2934                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2935                 sans_exception=DestroyExceptionInfo(sans_exception);
2936                 length=(size_t) image->blob->properties.st_size;
2937                 if ((magick_info != (const MagickInfo *) NULL) &&
2938                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2939                     (length > MagickMaxBufferExtent) &&
2940                     (AcquireMagickResource(MapResource,length) != MagickFalse))
2941                   {
2942                     void
2943                       *blob;
2944
2945                     blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
2946                       length);
2947                     if (blob == (void *) NULL)
2948                       RelinquishMagickResource(MapResource,length);
2949                     else
2950                       {
2951                         /*
2952                           Format supports blobs-- use memory-mapped I/O.
2953                         */
2954                         if (image_info->file != (FILE *) NULL)
2955                           image->blob->exempt=MagickFalse;
2956                         else
2957                           {
2958                             (void) fclose(image->blob->file_info.file);
2959                             image->blob->file_info.file=(FILE *) NULL;
2960                           }
2961                         AttachBlob(image->blob,blob,length);
2962                         image->blob->mapped=MagickTrue;
2963                       }
2964                   }
2965               }
2966           }
2967         }
2968       else
2969 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2970         if ((LocaleCompare(extension,"Z") == 0) ||
2971             (LocaleCompare(extension,"gz") == 0) ||
2972             (LocaleCompare(extension,"wmz") == 0) ||
2973             (LocaleCompare(extension,"svgz") == 0))
2974           {
2975             if (mode == WriteBinaryBlobMode)
2976               type="wb";
2977             image->blob->file_info.gzfile=gzopen(filename,type);
2978             if (image->blob->file_info.gzfile != (gzFile) NULL)
2979               image->blob->type=ZipStream;
2980           }
2981         else
2982 #endif
2983 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2984           if (LocaleCompare(extension,"bz2") == 0)
2985             {
2986               image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
2987               if (image->blob->file_info.bzfile != (BZFILE *) NULL)
2988                 image->blob->type=BZipStream;
2989             }
2990           else
2991 #endif
2992             {
2993               image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2994               if (image->blob->file_info.file != (FILE *) NULL)
2995                 {
2996                   image->blob->type=FileStream;
2997                   (void) SetStreamBuffering(image_info,image);
2998                 }
2999        }
3000   image->blob->status=MagickFalse;
3001   if (image->blob->type != UndefinedStream)
3002     image->blob->size=GetBlobSize(image);
3003   else
3004     {
3005       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3006       return(MagickFalse);
3007     }
3008   return(MagickTrue);
3009 }
3010 \f
3011 /*
3012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3013 %                                                                             %
3014 %                                                                             %
3015 %                                                                             %
3016 +   P i n g B l o b                                                           %
3017 %                                                                             %
3018 %                                                                             %
3019 %                                                                             %
3020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3021 %
3022 %  PingBlob() returns all the attributes of an image or image sequence except
3023 %  for the pixels.  It is much faster and consumes far less memory than
3024 %  BlobToImage().  On failure, a NULL image is returned and exception
3025 %  describes the reason for the failure.
3026 %
3027 %  The format of the PingBlob method is:
3028 %
3029 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
3030 %        const size_t length,ExceptionInfo *exception)
3031 %
3032 %  A description of each parameter follows:
3033 %
3034 %    o image_info: the image info.
3035 %
3036 %    o blob: the address of a character stream in one of the image formats
3037 %      understood by ImageMagick.
3038 %
3039 %    o length: This size_t integer reflects the length in bytes of the blob.
3040 %
3041 %    o exception: return any errors or warnings in this structure.
3042 %
3043 */
3044
3045 #if defined(__cplusplus) || defined(c_plusplus)
3046 extern "C" {
3047 #endif
3048
3049 static size_t PingStream(const Image *magick_unused(image),
3050   const void *magick_unused(pixels),const size_t columns)
3051 {
3052   magick_unreferenced(image);
3053   magick_unreferenced(pixels);
3054   return(columns);
3055 }
3056
3057 #if defined(__cplusplus) || defined(c_plusplus)
3058 }
3059 #endif
3060
3061 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3062   const size_t length,ExceptionInfo *exception)
3063 {
3064   Image
3065     *image;
3066
3067   ImageInfo
3068     *ping_info;
3069
3070   assert(image_info != (ImageInfo *) NULL);
3071   assert(image_info->signature == MagickCoreSignature);
3072   if (image_info->debug != MagickFalse)
3073     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3074       image_info->filename);
3075   assert(exception != (ExceptionInfo *) NULL);
3076   if ((blob == (const void *) NULL) || (length == 0))
3077     {
3078       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3079         "UnrecognizedImageFormat","`%s'",image_info->magick);
3080       return((Image *) NULL);
3081     }
3082   ping_info=CloneImageInfo(image_info);
3083   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
3084   if (ping_info->blob == (const void *) NULL)
3085     {
3086       (void) ThrowMagickException(exception,GetMagickModule(),
3087         ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
3088       return((Image *) NULL);
3089     }
3090   (void) memcpy(ping_info->blob,blob,length);
3091   ping_info->length=length;
3092   ping_info->ping=MagickTrue;
3093   image=ReadStream(ping_info,&PingStream,exception);
3094   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
3095   ping_info=DestroyImageInfo(ping_info);
3096   return(image);
3097 }
3098 \f
3099 /*
3100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3101 %                                                                             %
3102 %                                                                             %
3103 %                                                                             %
3104 +  R e a d B l o b                                                            %
3105 %                                                                             %
3106 %                                                                             %
3107 %                                                                             %
3108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3109 %
3110 %  ReadBlob() reads data from the blob or image file and returns it.  It
3111 %  returns the number of bytes read. If length is zero, ReadBlob() returns
3112 %  zero and has no other results. If length is greater than SSIZE_MAX, the
3113 %  result is unspecified.
3114 %
3115 %  The format of the ReadBlob method is:
3116 %
3117 %      ssize_t ReadBlob(Image *image,const size_t length,void *data)
3118 %
3119 %  A description of each parameter follows:
3120 %
3121 %    o image: the image.
3122 %
3123 %    o length:  Specifies an integer representing the number of bytes to read
3124 %      from the file.
3125 %
3126 %    o data:  Specifies an area to place the information requested from the
3127 %      file.
3128 %
3129 */
3130 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3131 {
3132   int
3133     c;
3134
3135   register unsigned char
3136     *q;
3137
3138   ssize_t
3139     count;
3140
3141   assert(image != (Image *) NULL);
3142   assert(image->signature == MagickCoreSignature);
3143   assert(image->blob != (BlobInfo *) NULL);
3144   assert(image->blob->type != UndefinedStream);
3145   if (length == 0)
3146     return(0);
3147   assert(data != (void *) NULL);
3148   count=0;
3149   q=(unsigned char *) data;
3150   switch (image->blob->type)
3151   {
3152     case UndefinedStream:
3153       break;
3154     case StandardStream:
3155     case FileStream:
3156     case PipeStream:
3157     {
3158       switch (length)
3159       {
3160         default:
3161         {
3162           count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
3163           break;
3164         }
3165         case 4:
3166         {
3167           c=getc(image->blob->file_info.file);
3168           if (c == EOF)
3169             break;
3170           *q++=(unsigned char) c;
3171           count++;
3172         }
3173         case 3:
3174         {
3175           c=getc(image->blob->file_info.file);
3176           if (c == EOF)
3177             break;
3178           *q++=(unsigned char) c;
3179           count++;
3180         }
3181         case 2:
3182         {
3183           c=getc(image->blob->file_info.file);
3184           if (c == EOF)
3185             break;
3186           *q++=(unsigned char) c;
3187           count++;
3188         }
3189         case 1:
3190         {
3191           c=getc(image->blob->file_info.file);
3192           if (c == EOF)
3193             break;
3194           *q++=(unsigned char) c;
3195           count++;
3196         }
3197         case 0:
3198           break;
3199       }
3200       break;
3201     }
3202     case ZipStream:
3203     {
3204 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3205       switch (length)
3206       {
3207         default:
3208         {
3209           count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
3210             (unsigned int) length);
3211           break;
3212         }
3213         case 4:
3214         {
3215           c=gzgetc(image->blob->file_info.gzfile);
3216           if (c == EOF)
3217             break;
3218           *q++=(unsigned char) c;
3219           count++;
3220         }
3221         case 3:
3222         {
3223           c=gzgetc(image->blob->file_info.gzfile);
3224           if (c == EOF)
3225             break;
3226           *q++=(unsigned char) c;
3227           count++;
3228         }
3229         case 2:
3230         {
3231           c=gzgetc(image->blob->file_info.gzfile);
3232           if (c == EOF)
3233             break;
3234           *q++=(unsigned char) c;
3235           count++;
3236         }
3237         case 1:
3238         {
3239           c=gzgetc(image->blob->file_info.gzfile);
3240           if (c == EOF)
3241             break;
3242           *q++=(unsigned char) c;
3243           count++;
3244         }
3245         case 0:
3246           break;
3247       }
3248 #endif
3249       break;
3250     }
3251     case BZipStream:
3252     {
3253 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3254       count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
3255 #endif
3256       break;
3257     }
3258     case FifoStream:
3259       break;
3260     case BlobStream:
3261     {
3262       register const unsigned char
3263         *p;
3264
3265       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3266         {
3267           image->blob->eof=MagickTrue;
3268           break;
3269         }
3270       p=image->blob->data+image->blob->offset;
3271       count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
3272       image->blob->offset+=count;
3273       if (count != (ssize_t) length)
3274         image->blob->eof=MagickTrue;
3275       (void) memcpy(q,p,(size_t) count);
3276       break;
3277     }
3278     case UserStream:
3279     {
3280       count=image->blob->user_info->reader(q,length,
3281         image->blob->user_info->data);
3282       break;
3283     }
3284   }
3285   return(count);
3286 }
3287 \f
3288 /*
3289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3290 %                                                                             %
3291 %                                                                             %
3292 %                                                                             %
3293 +  R e a d B l o b B y t e                                                    %
3294 %                                                                             %
3295 %                                                                             %
3296 %                                                                             %
3297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3298 %
3299 %  ReadBlobByte() reads a single byte from the image file and returns it.
3300 %
3301 %  The format of the ReadBlobByte method is:
3302 %
3303 %      int ReadBlobByte(Image *image)
3304 %
3305 %  A description of each parameter follows.
3306 %
3307 %    o image: the image.
3308 %
3309 */
3310 MagickExport int ReadBlobByte(Image *image)
3311 {
3312   register const unsigned char
3313     *p;
3314
3315   ssize_t
3316     count;
3317
3318   unsigned char
3319     buffer[1];
3320
3321   assert(image != (Image *) NULL);
3322   assert(image->signature == MagickCoreSignature);
3323   p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3324   if (count != 1)
3325     return(EOF);
3326   return((int) (*p));
3327 }
3328 \f
3329 /*
3330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3331 %                                                                             %
3332 %                                                                             %
3333 %                                                                             %
3334 +  R e a d B l o b D o u b l e                                                %
3335 %                                                                             %
3336 %                                                                             %
3337 %                                                                             %
3338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3339 %
3340 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3341 %  specified by the endian member of the image structure.
3342 %
3343 %  The format of the ReadBlobDouble method is:
3344 %
3345 %      double ReadBlobDouble(Image *image)
3346 %
3347 %  A description of each parameter follows.
3348 %
3349 %    o image: the image.
3350 %
3351 */
3352 MagickExport double ReadBlobDouble(Image *image)
3353 {
3354   union
3355   {
3356     MagickSizeType
3357       unsigned_value;
3358
3359     double
3360       double_value;
3361   } quantum;
3362
3363   quantum.double_value=0.0;
3364   quantum.unsigned_value=ReadBlobLongLong(image);
3365   return(quantum.double_value);
3366 }
3367 \f
3368 /*
3369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3370 %                                                                             %
3371 %                                                                             %
3372 %                                                                             %
3373 +  R e a d B l o b F l o a t                                                  %
3374 %                                                                             %
3375 %                                                                             %
3376 %                                                                             %
3377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3378 %
3379 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3380 %  specified by the endian member of the image structure.
3381 %
3382 %  The format of the ReadBlobFloat method is:
3383 %
3384 %      float ReadBlobFloat(Image *image)
3385 %
3386 %  A description of each parameter follows.
3387 %
3388 %    o image: the image.
3389 %
3390 */
3391 MagickExport float ReadBlobFloat(Image *image)
3392 {
3393   union
3394   {
3395     unsigned int
3396       unsigned_value;
3397
3398     float
3399       float_value;
3400   } quantum;
3401
3402   quantum.float_value=0.0;
3403   quantum.unsigned_value=ReadBlobLong(image);
3404   return(quantum.float_value);
3405 }
3406 \f
3407 /*
3408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3409 %                                                                             %
3410 %                                                                             %
3411 %                                                                             %
3412 +  R e a d B l o b L o n g                                                    %
3413 %                                                                             %
3414 %                                                                             %
3415 %                                                                             %
3416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3417 %
3418 %  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3419 %  byte-order specified by the endian member of the image structure.
3420 %
3421 %  The format of the ReadBlobLong method is:
3422 %
3423 %      unsigned int ReadBlobLong(Image *image)
3424 %
3425 %  A description of each parameter follows.
3426 %
3427 %    o image: the image.
3428 %
3429 */
3430 MagickExport unsigned int ReadBlobLong(Image *image)
3431 {
3432   register const unsigned char
3433     *p;
3434
3435   ssize_t
3436     count;
3437
3438   unsigned char
3439     buffer[4];
3440
3441   unsigned int
3442     value;
3443
3444   assert(image != (Image *) NULL);
3445   assert(image->signature == MagickCoreSignature);
3446   *buffer='\0';
3447   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3448   if (count != 4)
3449     return(0UL);
3450   if (image->endian == LSBEndian)
3451     {
3452       value=(unsigned int) (*p++);
3453       value|=(unsigned int) (*p++) << 8;
3454       value|=(unsigned int) (*p++) << 16;
3455       value|=(unsigned int) (*p++) << 24;
3456       return(value & 0xffffffff);
3457     }
3458   value=(unsigned int) (*p++) << 24;
3459   value|=(unsigned int) (*p++) << 16;
3460   value|=(unsigned int) (*p++) << 8;
3461   value|=(unsigned int) (*p++);
3462   return(value & 0xffffffff);
3463 }
3464 \f
3465 /*
3466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3467 %                                                                             %
3468 %                                                                             %
3469 %                                                                             %
3470 +  R e a d B l o b L o n g L o n g                                            %
3471 %                                                                             %
3472 %                                                                             %
3473 %                                                                             %
3474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3475 %
3476 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3477 %  byte-order specified by the endian member of the image structure.
3478 %
3479 %  The format of the ReadBlobLongLong method is:
3480 %
3481 %      MagickSizeType ReadBlobLongLong(Image *image)
3482 %
3483 %  A description of each parameter follows.
3484 %
3485 %    o image: the image.
3486 %
3487 */
3488 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3489 {
3490   MagickSizeType
3491     value;
3492
3493   register const unsigned char
3494     *p;
3495
3496   ssize_t
3497     count;
3498
3499   unsigned char
3500     buffer[8];
3501
3502   assert(image != (Image *) NULL);
3503   assert(image->signature == MagickCoreSignature);
3504   *buffer='\0';
3505   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3506   if (count != 8)
3507     return(MagickULLConstant(0));
3508   if (image->endian == LSBEndian)
3509     {
3510       value=(MagickSizeType) (*p++);
3511       value|=(MagickSizeType) (*p++) << 8;
3512       value|=(MagickSizeType) (*p++) << 16;
3513       value|=(MagickSizeType) (*p++) << 24;
3514       value|=(MagickSizeType) (*p++) << 32;
3515       value|=(MagickSizeType) (*p++) << 40;
3516       value|=(MagickSizeType) (*p++) << 48;
3517       value|=(MagickSizeType) (*p++) << 56;
3518       return(value & MagickULLConstant(0xffffffffffffffff));
3519     }
3520   value=(MagickSizeType) (*p++) << 56;
3521   value|=(MagickSizeType) (*p++) << 48;
3522   value|=(MagickSizeType) (*p++) << 40;
3523   value|=(MagickSizeType) (*p++) << 32;
3524   value|=(MagickSizeType) (*p++) << 24;
3525   value|=(MagickSizeType) (*p++) << 16;
3526   value|=(MagickSizeType) (*p++) << 8;
3527   value|=(MagickSizeType) (*p++);
3528   return(value & MagickULLConstant(0xffffffffffffffff));
3529 }
3530 \f
3531 /*
3532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3533 %                                                                             %
3534 %                                                                             %
3535 %                                                                             %
3536 +  R e a d B l o b S h o r t                                                  %
3537 %                                                                             %
3538 %                                                                             %
3539 %                                                                             %
3540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3541 %
3542 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3543 %  specified by the endian member of the image structure.
3544 %
3545 %  The format of the ReadBlobShort method is:
3546 %
3547 %      unsigned short ReadBlobShort(Image *image)
3548 %
3549 %  A description of each parameter follows.
3550 %
3551 %    o image: the image.
3552 %
3553 */
3554 MagickExport unsigned short ReadBlobShort(Image *image)
3555 {
3556   register const unsigned char
3557     *p;
3558
3559   register unsigned short
3560     value;
3561
3562   ssize_t
3563     count;
3564
3565   unsigned char
3566     buffer[2];
3567
3568   assert(image != (Image *) NULL);
3569   assert(image->signature == MagickCoreSignature);
3570   *buffer='\0';
3571   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3572   if (count != 2)
3573     return((unsigned short) 0U);
3574   if (image->endian == LSBEndian)
3575     {
3576       value=(unsigned short) (*p++);
3577       value|=(unsigned short) (*p++) << 8;
3578       return(value);
3579     }
3580   value=(unsigned short) (*p++) << 8;
3581   value|=(unsigned short) (*p++);
3582   return(value);
3583 }
3584 \f
3585 /*
3586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3587 %                                                                             %
3588 %                                                                             %
3589 %                                                                             %
3590 +  R e a d B l o b L S B L o n g                                              %
3591 %                                                                             %
3592 %                                                                             %
3593 %                                                                             %
3594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3595 %
3596 %  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3597 %  least-significant byte first order.
3598 %
3599 %  The format of the ReadBlobLSBLong method is:
3600 %
3601 %      unsigned int ReadBlobLSBLong(Image *image)
3602 %
3603 %  A description of each parameter follows.
3604 %
3605 %    o image: the image.
3606 %
3607 */
3608 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3609 {
3610   register const unsigned char
3611     *p;
3612
3613   register unsigned int
3614     value;
3615
3616   ssize_t
3617     count;
3618
3619   unsigned char
3620     buffer[4];
3621
3622   assert(image != (Image *) NULL);
3623   assert(image->signature == MagickCoreSignature);
3624   *buffer='\0';
3625   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3626   if (count != 4)
3627     return(0U);
3628   value=(unsigned int) (*p++);
3629   value|=(unsigned int) (*p++) << 8;
3630   value|=(unsigned int) (*p++) << 16;
3631   value|=(unsigned int) (*p++) << 24;
3632   return(value & 0xffffffff);
3633 }
3634 \f
3635 /*
3636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3637 %                                                                             %
3638 %                                                                             %
3639 %                                                                             %
3640 +  R e a d B l o b L S B S i g n e d L o n g                                  %
3641 %                                                                             %
3642 %                                                                             %
3643 %                                                                             %
3644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3645 %
3646 %  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3647 %  least-significant byte first order.
3648 %
3649 %  The format of the ReadBlobLSBSignedLong method is:
3650 %
3651 %      signed int ReadBlobLSBSignedLong(Image *image)
3652 %
3653 %  A description of each parameter follows.
3654 %
3655 %    o image: the image.
3656 %
3657 */
3658 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
3659 {
3660   union
3661   {
3662     unsigned int
3663       unsigned_value;
3664
3665     signed int
3666       signed_value;
3667   } quantum;
3668
3669   quantum.unsigned_value=ReadBlobLSBLong(image);
3670   return(quantum.signed_value);
3671 }
3672 \f
3673 /*
3674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3675 %                                                                             %
3676 %                                                                             %
3677 %                                                                             %
3678 +  R e a d B l o b L S B S h o r t                                            %
3679 %                                                                             %
3680 %                                                                             %
3681 %                                                                             %
3682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3683 %
3684 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3685 %  least-significant byte first order.
3686 %
3687 %  The format of the ReadBlobLSBShort method is:
3688 %
3689 %      unsigned short ReadBlobLSBShort(Image *image)
3690 %
3691 %  A description of each parameter follows.
3692 %
3693 %    o image: the image.
3694 %
3695 */
3696 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3697 {
3698   register const unsigned char
3699     *p;
3700
3701   register unsigned short
3702     value;
3703
3704   ssize_t
3705     count;
3706
3707   unsigned char
3708     buffer[2];
3709
3710   assert(image != (Image *) NULL);
3711   assert(image->signature == MagickCoreSignature);
3712   *buffer='\0';
3713   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3714   if (count != 2)
3715     return((unsigned short) 0U);
3716   value=(unsigned int) (*p++);
3717   value|=(unsigned int) (*p++) << 8;
3718   return(value & 0xffff);
3719 }
3720 \f
3721 /*
3722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3723 %                                                                             %
3724 %                                                                             %
3725 %                                                                             %
3726 +  R e a d B l o b L S B S i g n e d S h o r t                                %
3727 %                                                                             %
3728 %                                                                             %
3729 %                                                                             %
3730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3731 %
3732 %  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
3733 %  least-significant byte-order.
3734 %
3735 %  The format of the ReadBlobLSBSignedShort method is:
3736 %
3737 %      signed short ReadBlobLSBSignedShort(Image *image)
3738 %
3739 %  A description of each parameter follows.
3740 %
3741 %    o image: the image.
3742 %
3743 */
3744 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
3745 {
3746   union
3747   {
3748     unsigned short
3749       unsigned_value;
3750
3751     signed short
3752       signed_value;
3753   } quantum;
3754
3755   quantum.unsigned_value=ReadBlobLSBShort(image);
3756   return(quantum.signed_value);
3757 }
3758 \f
3759 /*
3760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3761 %                                                                             %
3762 %                                                                             %
3763 %                                                                             %
3764 +  R e a d B l o b M S B L o n g                                              %
3765 %                                                                             %
3766 %                                                                             %
3767 %                                                                             %
3768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3769 %
3770 %  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
3771 %  most-significant byte first order.
3772 %
3773 %  The format of the ReadBlobMSBLong method is:
3774 %
3775 %      unsigned int ReadBlobMSBLong(Image *image)
3776 %
3777 %  A description of each parameter follows.
3778 %
3779 %    o image: the image.
3780 %
3781 */
3782 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3783 {
3784   register const unsigned char
3785     *p;
3786
3787   register unsigned int
3788     value;
3789
3790   ssize_t
3791     count;
3792
3793   unsigned char
3794     buffer[4];
3795
3796   assert(image != (Image *) NULL);
3797   assert(image->signature == MagickCoreSignature);
3798   *buffer='\0';
3799   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3800   if (count != 4)
3801     return(0UL);
3802   value=(unsigned int) (*p++) << 24;
3803   value|=(unsigned int) (*p++) << 16;
3804   value|=(unsigned int) (*p++) << 8;
3805   value|=(unsigned int) (*p++);
3806   return(value);
3807 }
3808 \f
3809 /*
3810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3811 %                                                                             %
3812 %                                                                             %
3813 %                                                                             %
3814 +  R e a d B l o b M S B L o n g L o n g                                      %
3815 %                                                                             %
3816 %                                                                             %
3817 %                                                                             %
3818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3819 %
3820 %  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
3821 %  in most-significant byte first order.
3822 %
3823 %  The format of the ReadBlobMSBLongLong method is:
3824 %
3825 %      unsigned int ReadBlobMSBLongLong(Image *image)
3826 %
3827 %  A description of each parameter follows.
3828 %
3829 %    o image: the image.
3830 %
3831 */
3832 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3833 {
3834   register const unsigned char
3835     *p;
3836
3837   register MagickSizeType
3838     value;
3839
3840   ssize_t
3841     count;
3842
3843   unsigned char
3844     buffer[8];
3845
3846   assert(image != (Image *) NULL);
3847   assert(image->signature == MagickCoreSignature);
3848   *buffer='\0';
3849   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3850   if (count != 8)
3851     return(MagickULLConstant(0));
3852   value=(MagickSizeType) (*p++) << 56;
3853   value|=(MagickSizeType) (*p++) << 48;
3854   value|=(MagickSizeType) (*p++) << 40;
3855   value|=(MagickSizeType) (*p++) << 32;
3856   value|=(MagickSizeType) (*p++) << 24;
3857   value|=(MagickSizeType) (*p++) << 16;
3858   value|=(MagickSizeType) (*p++) << 8;
3859   value|=(MagickSizeType) (*p++);
3860   return(value & MagickULLConstant(0xffffffffffffffff));
3861 }
3862 \f
3863 /*
3864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3865 %                                                                             %
3866 %                                                                             %
3867 %                                                                             %
3868 +  R e a d B l o b M S B S h o r t                                            %
3869 %                                                                             %
3870 %                                                                             %
3871 %                                                                             %
3872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3873 %
3874 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3875 %  most-significant byte first order.
3876 %
3877 %  The format of the ReadBlobMSBShort method is:
3878 %
3879 %      unsigned short ReadBlobMSBShort(Image *image)
3880 %
3881 %  A description of each parameter follows.
3882 %
3883 %    o image: the image.
3884 %
3885 */
3886 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3887 {
3888   register const unsigned char
3889     *p;
3890
3891   register unsigned short
3892     value;
3893
3894   ssize_t
3895     count;
3896
3897   unsigned char
3898     buffer[2];
3899
3900   assert(image != (Image *) NULL);
3901   assert(image->signature == MagickCoreSignature);
3902   *buffer='\0';
3903   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3904   if (count != 2)
3905     return((unsigned short) 0U);
3906   value=(unsigned short) (*p++) << 8;
3907   value|=(unsigned short) (*p++);
3908   return(value & 0xffff);
3909 }
3910 \f
3911 /*
3912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3913 %                                                                             %
3914 %                                                                             %
3915 %                                                                             %
3916 +  R e a d B l o b M S B S i g n e d L o n g                                  %
3917 %                                                                             %
3918 %                                                                             %
3919 %                                                                             %
3920 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3921 %
3922 %  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
3923 %  most-significant byte-order.
3924 %
3925 %  The format of the ReadBlobMSBSignedLong method is:
3926 %
3927 %      signed int ReadBlobMSBSignedLong(Image *image)
3928 %
3929 %  A description of each parameter follows.
3930 %
3931 %    o image: the image.
3932 %
3933 */
3934 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
3935 {
3936   union
3937   {
3938     unsigned int
3939       unsigned_value;
3940
3941     signed int
3942       signed_value;
3943   } quantum;
3944
3945   quantum.unsigned_value=ReadBlobMSBLong(image);
3946   return(quantum.signed_value);
3947 }
3948 \f
3949 /*
3950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3951 %                                                                             %
3952 %                                                                             %
3953 %                                                                             %
3954 +  R e a d B l o b M S B S i g n e d S h o r t                                %
3955 %                                                                             %
3956 %                                                                             %
3957 %                                                                             %
3958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3959 %
3960 %  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
3961 %  most-significant byte-order.
3962 %
3963 %  The format of the ReadBlobMSBSignedShort method is:
3964 %
3965 %      signed short ReadBlobMSBSignedShort(Image *image)
3966 %
3967 %  A description of each parameter follows.
3968 %
3969 %    o image: the image.
3970 %
3971 */
3972 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
3973 {
3974   union
3975   {
3976     unsigned short
3977       unsigned_value;
3978
3979     signed short
3980       signed_value;
3981   } quantum;
3982
3983   quantum.unsigned_value=ReadBlobMSBShort(image);
3984   return(quantum.signed_value);
3985 }
3986 \f
3987 /*
3988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3989 %                                                                             %
3990 %                                                                             %
3991 %                                                                             %
3992 +  R e a d B l o b S i g n e d L o n g                                        %
3993 %                                                                             %
3994 %                                                                             %
3995 %                                                                             %
3996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3997 %
3998 %  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
3999 %  byte-order specified by the endian member of the image structure.
4000 %
4001 %  The format of the ReadBlobSignedLong method is:
4002 %
4003 %      signed int ReadBlobSignedLong(Image *image)
4004 %
4005 %  A description of each parameter follows.
4006 %
4007 %    o image: the image.
4008 %
4009 */
4010 MagickExport signed int ReadBlobSignedLong(Image *image)
4011 {
4012   union
4013   {
4014     unsigned int
4015       unsigned_value;
4016
4017     signed int
4018       signed_value;
4019   } quantum;
4020
4021   quantum.unsigned_value=ReadBlobLong(image);
4022   return(quantum.signed_value);
4023 }
4024 \f
4025 /*
4026 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4027 %                                                                             %
4028 %                                                                             %
4029 %                                                                             %
4030 +  R e a d B l o b S i g n e d S h o r t                                      %
4031 %                                                                             %
4032 %                                                                             %
4033 %                                                                             %
4034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4035 %
4036 %  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4037 %  byte-order specified by the endian member of the image structure.
4038 %
4039 %  The format of the ReadBlobSignedShort method is:
4040 %
4041 %      signed short ReadBlobSignedShort(Image *image)
4042 %
4043 %  A description of each parameter follows.
4044 %
4045 %    o image: the image.
4046 %
4047 */
4048 MagickExport signed short ReadBlobSignedShort(Image *image)
4049 {
4050   union
4051   {
4052     unsigned short
4053       unsigned_value;
4054
4055     signed short
4056       signed_value;
4057   } quantum;
4058
4059   quantum.unsigned_value=ReadBlobShort(image);
4060   return(quantum.signed_value);
4061 }
4062 \f
4063 /*
4064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4065 %                                                                             %
4066 %                                                                             %
4067 %                                                                             %
4068 +  R e a d B l o b S t r e a m                                                %
4069 %                                                                             %
4070 %                                                                             %
4071 %                                                                             %
4072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4073 %
4074 %  ReadBlobStream() reads data from the blob or image file and returns it.  It
4075 %  returns a pointer to the data buffer you supply or to the image memory
4076 %  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4077 %  returns a count of zero and has no other results. If length is greater than
4078 %  SSIZE_MAX, the result is unspecified.
4079 %
4080 %  The format of the ReadBlobStream method is:
4081 %
4082 %      const void *ReadBlobStream(Image *image,const size_t length,void *data,
4083 %        ssize_t *count)
4084 %
4085 %  A description of each parameter follows:
4086 %
4087 %    o image: the image.
4088 %
4089 %    o length:  Specifies an integer representing the number of bytes to read
4090 %      from the file.
4091 %
4092 %    o count: returns the number of bytes read.
4093 %
4094 %    o data:  Specifies an area to place the information requested from the
4095 %      file.
4096 %
4097 */
4098 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
4099   void *data,ssize_t *count)
4100 {
4101   assert(image != (Image *) NULL);
4102   assert(image->signature == MagickCoreSignature);
4103   assert(image->blob != (BlobInfo *) NULL);
4104   assert(image->blob->type != UndefinedStream);
4105   assert(count != (ssize_t *) NULL);
4106   if (image->blob->type != BlobStream)
4107     {
4108       assert(data != NULL);
4109       *count=ReadBlob(image,length,(unsigned char *) data);
4110       return(data);
4111     }
4112   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4113     {
4114       *count=0;
4115       image->blob->eof=MagickTrue;
4116       return(data);
4117     }
4118   data=image->blob->data+image->blob->offset;
4119   *count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
4120   image->blob->offset+=(*count);
4121   if (*count != (ssize_t) length)
4122     image->blob->eof=MagickTrue;
4123   return(data);
4124 }
4125 \f
4126 /*
4127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4128 %                                                                             %
4129 %                                                                             %
4130 %                                                                             %
4131 +   R e a d B l o b S t r i n g                                               %
4132 %                                                                             %
4133 %                                                                             %
4134 %                                                                             %
4135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4136 %
4137 %  ReadBlobString() reads characters from a blob or file until a newline
4138 %  character is read or an end-of-file condition is encountered.
4139 %
4140 %  The format of the ReadBlobString method is:
4141 %
4142 %      char *ReadBlobString(Image *image,char *string)
4143 %
4144 %  A description of each parameter follows:
4145 %
4146 %    o image: the image.
4147 %
4148 %    o string: the address of a character buffer.
4149 %
4150 */
4151 MagickExport char *ReadBlobString(Image *image,char *string)
4152 {
4153   register const unsigned char
4154     *p;
4155
4156   register ssize_t
4157     i;
4158
4159   ssize_t
4160     count;
4161
4162   unsigned char
4163     buffer[1];
4164
4165   assert(image != (Image *) NULL);
4166   assert(image->signature == MagickCoreSignature);
4167   for (i=0; i < (MagickPathExtent-1L); i++)
4168   {
4169     p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
4170     if (count != 1)
4171       {
4172         if (i == 0)
4173           return((char *) NULL);
4174         break;
4175       }
4176     string[i]=(char) (*p);
4177     if ((string[i] == '\r') || (string[i] == '\n'))
4178       break;
4179   }
4180   if (string[i] == '\r')
4181     (void) ReadBlobStream(image,1,buffer,&count);
4182   string[i]='\0';
4183   return(string);
4184 }
4185 \f
4186 /*
4187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4188 %                                                                             %
4189 %                                                                             %
4190 %                                                                             %
4191 +   R e f e r e n c e B l o b                                                 %
4192 %                                                                             %
4193 %                                                                             %
4194 %                                                                             %
4195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4196 %
4197 %  ReferenceBlob() increments the reference count associated with the pixel
4198 %  blob returning a pointer to the blob.
4199 %
4200 %  The format of the ReferenceBlob method is:
4201 %
4202 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
4203 %
4204 %  A description of each parameter follows:
4205 %
4206 %    o blob_info: the blob_info.
4207 %
4208 */
4209 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4210 {
4211   assert(blob != (BlobInfo *) NULL);
4212   assert(blob->signature == MagickCoreSignature);
4213   if (blob->debug != MagickFalse)
4214     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4215   LockSemaphoreInfo(blob->semaphore);
4216   blob->reference_count++;
4217   UnlockSemaphoreInfo(blob->semaphore);
4218   return(blob);
4219 }
4220 \f
4221 /*
4222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4223 %                                                                             %
4224 %                                                                             %
4225 %                                                                             %
4226 +  S e e k B l o b                                                            %
4227 %                                                                             %
4228 %                                                                             %
4229 %                                                                             %
4230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4231 %
4232 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
4233 %  and returns the resulting offset.
4234 %
4235 %  The format of the SeekBlob method is:
4236 %
4237 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4238 %        const int whence)
4239 %
4240 %  A description of each parameter follows:
4241 %
4242 %    o image: the image.
4243 %
4244 %    o offset:  Specifies an integer representing the offset in bytes.
4245 %
4246 %    o whence:  Specifies an integer representing how the offset is
4247 %      treated relative to the beginning of the blob as follows:
4248 %
4249 %        SEEK_SET  Set position equal to offset bytes.
4250 %        SEEK_CUR  Set position to current location plus offset.
4251 %        SEEK_END  Set position to EOF plus offset.
4252 %
4253 */
4254 MagickExport MagickOffsetType SeekBlob(Image *image,
4255   const MagickOffsetType offset,const int whence)
4256 {
4257   assert(image != (Image *) NULL);
4258   assert(image->signature == MagickCoreSignature);
4259   if (image->debug != MagickFalse)
4260     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4261   assert(image->blob != (BlobInfo *) NULL);
4262   assert(image->blob->type != UndefinedStream);
4263   switch (image->blob->type)
4264   {
4265     case UndefinedStream:
4266       break;
4267     case StandardStream:
4268     case PipeStream:
4269       return(-1);
4270     case FileStream:
4271     {
4272       if ((offset < 0) && (whence == SEEK_SET))
4273         return(-1);
4274       if (fseek(image->blob->file_info.file,offset,whence) < 0)
4275         return(-1);
4276       image->blob->offset=TellBlob(image);
4277       break;
4278     }
4279     case ZipStream:
4280     {
4281 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4282       if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
4283         return(-1);
4284 #endif
4285       image->blob->offset=TellBlob(image);
4286       break;
4287     }
4288     case BZipStream:
4289       return(-1);
4290     case FifoStream:
4291       return(-1);
4292     case BlobStream:
4293     {
4294       switch (whence)
4295       {
4296         case SEEK_SET:
4297         default:
4298         {
4299           if (offset < 0)
4300             return(-1);
4301           image->blob->offset=offset;
4302           break;
4303         }
4304         case SEEK_CUR:
4305         {
4306           if ((image->blob->offset+offset) < 0)
4307             return(-1);
4308           image->blob->offset+=offset;
4309           break;
4310         }
4311         case SEEK_END:
4312         {
4313           if (((MagickOffsetType) image->blob->length+offset) < 0)
4314             return(-1);
4315           image->blob->offset=image->blob->length+offset;
4316           break;
4317         }
4318       }
4319       if (image->blob->offset < (MagickOffsetType)
4320           ((off_t) image->blob->length))
4321         {
4322           image->blob->eof=MagickFalse;
4323           break;
4324         }
4325       if (image->blob->offset < (MagickOffsetType)
4326           ((off_t) image->blob->extent))
4327         break;
4328       if (image->blob->mapped != MagickFalse)
4329         {
4330           image->blob->eof=MagickTrue;
4331           return(-1);
4332         }
4333       image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
4334       image->blob->quantum<<=1;
4335       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
4336         image->blob->extent+1,sizeof(*image->blob->data));
4337       (void) SyncBlob(image);
4338       if (image->blob->data == NULL)
4339         {
4340           (void) DetachBlob(image->blob);
4341           return(-1);
4342         }
4343       break;
4344     }
4345     case UserStream:
4346     {
4347       if (image->blob->user_info->seeker == (BlobSeeker) NULL)
4348         return(-1);
4349       image->blob->offset=image->blob->user_info->seeker(offset,whence,
4350         image->blob->user_info->data);
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->reader != (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       (blob_info->user_info == (UserBlobInfo *) NULL))
4789     {
4790       /*
4791         Native blob support for this image format or SetImageInfo changed the
4792         blob to a file.
4793       */
4794       image=ReadImage(blob_info,exception);
4795       if (image != (Image *) NULL)
4796         (void) CloseBlob(image);
4797     }
4798   else
4799     {
4800       char
4801         unique[MagickPathExtent];
4802
4803       int
4804         file;
4805
4806       ImageInfo
4807         *clone_info;
4808
4809       unsigned char
4810         *blob;
4811
4812       /*
4813         Write data to file on disk.
4814       */
4815       blob_info->user_info=(UserBlobInfo *) NULL;
4816       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
4817         sizeof(*blob));
4818       if (blob == (unsigned char *) NULL)
4819         {
4820           ThrowFileException(exception,BlobError,"UnableToReadBlob",
4821             image_info->filename);
4822           blob_info=DestroyImageInfo(blob_info);
4823           return((Image *) NULL);
4824         }
4825       file=AcquireUniqueFileResource(unique);
4826       if (file == -1)
4827         {
4828           ThrowFileException(exception,BlobError,"UnableToReadBlob",
4829             image_info->filename);
4830           blob=(unsigned char *) RelinquishMagickMemory(blob);
4831           blob_info=DestroyImageInfo(blob_info);
4832           return((Image *) NULL);
4833         }
4834       clone_info=CloneImageInfo(blob_info);
4835       blob_info->file=fdopen(file,"wb+");
4836       if (blob_info->file != (FILE *) NULL)
4837         {
4838           ssize_t
4839             count;
4840
4841           count=(ssize_t) MagickMaxBufferExtent;
4842           while (count == (ssize_t) MagickMaxBufferExtent)
4843           {
4844             count=user_info->reader(blob,MagickMaxBufferExtent,
4845               user_info->data);
4846             count=(ssize_t) write(file,(const char *) blob,count);
4847           }
4848           (void) fclose(blob_info->file);
4849           (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
4850             "%s:%s",blob_info->magick,unique);
4851           image=ReadImage(clone_info,exception);
4852           if (image != (Image *) NULL)
4853             {
4854               Image
4855                 *images;
4856
4857               /*
4858                 Restore original filenames and image format.
4859               */
4860               for (images=GetFirstImageInList(image); images != (Image *) NULL; )
4861               {
4862                 (void) CopyMagickString(images->filename,image_info->filename,
4863                   MagickPathExtent);
4864                 (void) CopyMagickString(images->magick_filename,
4865                   image_info->filename,MagickPathExtent);
4866                 (void) CopyMagickString(images->magick,magick_info->name,
4867                   MagickPathExtent);
4868                 (void) CloseBlob(images);
4869                 images=GetNextImageInList(images);
4870               }
4871             }
4872         }
4873       clone_info=DestroyImageInfo(clone_info);
4874       blob=(unsigned char *) RelinquishMagickMemory(blob);
4875       (void) RelinquishUniqueFileResource(unique);
4876     }
4877   blob_info=DestroyImageInfo(blob_info);
4878   return(image);
4879 }
4880 \f
4881 /*
4882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4883 %                                                                             %
4884 %                                                                             %
4885 %                                                                             %
4886 +  W r i t e B l o b                                                          %
4887 %                                                                             %
4888 %                                                                             %
4889 %                                                                             %
4890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4891 %
4892 %  WriteBlob() writes data to a blob or image file.  It returns the number of
4893 %  bytes written.
4894 %
4895 %  The format of the WriteBlob method is:
4896 %
4897 %      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
4898 %
4899 %  A description of each parameter follows:
4900 %
4901 %    o image: the image.
4902 %
4903 %    o length:  Specifies an integer representing the number of bytes to
4904 %      write to the file.
4905 %
4906 %    o data:  The address of the data to write to the blob or file.
4907 %
4908 */
4909 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4910   const void *data)
4911 {
4912   int
4913     c;
4914
4915   register const unsigned char
4916     *p;
4917
4918   ssize_t
4919     count;
4920
4921   assert(image != (Image *) NULL);
4922   assert(image->signature == MagickCoreSignature);
4923   assert(data != (const void *) NULL);
4924   assert(image->blob != (BlobInfo *) NULL);
4925   assert(image->blob->type != UndefinedStream);
4926   if (length == 0)
4927     return(0);
4928   count=0;
4929   p=(const unsigned char *) data;
4930   switch (image->blob->type)
4931   {
4932     case UndefinedStream:
4933       break;
4934     case StandardStream:
4935     case FileStream:
4936     case PipeStream:
4937     {
4938       switch (length)
4939       {
4940         default:
4941         {
4942           count=(ssize_t) fwrite((const char *) data,1,length,
4943             image->blob->file_info.file);
4944           break;
4945         }
4946         case 4:
4947         {
4948           c=putc((int) *p++,image->blob->file_info.file);
4949           if (c == EOF)
4950             break;
4951           count++;
4952         }
4953         case 3:
4954         {
4955           c=putc((int) *p++,image->blob->file_info.file);
4956           if (c == EOF)
4957             break;
4958           count++;
4959         }
4960         case 2:
4961         {
4962           c=putc((int) *p++,image->blob->file_info.file);
4963           if (c == EOF)
4964             break;
4965           count++;
4966         }
4967         case 1:
4968         {
4969           c=putc((int) *p++,image->blob->file_info.file);
4970           if (c == EOF)
4971             break;
4972           count++;
4973         }
4974         case 0:
4975           break;
4976       }
4977       break;
4978     }
4979     case ZipStream:
4980     {
4981 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4982       switch (length)
4983       {
4984         default:
4985         {
4986           count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
4987             (unsigned int) length);
4988           break;
4989         }
4990         case 4:
4991         {
4992           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
4993           if (c == EOF)
4994             break;
4995           count++;
4996         }
4997         case 3:
4998         {
4999           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5000           if (c == EOF)
5001             break;
5002           count++;
5003         }
5004         case 2:
5005         {
5006           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5007           if (c == EOF)
5008             break;
5009           count++;
5010         }
5011         case 1:
5012         {
5013           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5014           if (c == EOF)
5015             break;
5016           count++;
5017         }
5018         case 0:
5019           break;
5020       }
5021 #endif
5022       break;
5023     }
5024     case BZipStream:
5025     {
5026 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5027       count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
5028         (int) length);
5029 #endif
5030       break;
5031     }
5032     case FifoStream:
5033     {
5034       count=(ssize_t) image->blob->stream(image,data,length);
5035       break;
5036     }
5037     case BlobStream:
5038     {
5039       register unsigned char
5040         *q;
5041
5042       if ((image->blob->offset+(MagickOffsetType) length) >=
5043           (MagickOffsetType) image->blob->extent)
5044         {
5045           if (image->blob->mapped != MagickFalse)
5046             return(0);
5047           image->blob->extent+=length+image->blob->quantum;
5048           image->blob->quantum<<=1;
5049           image->blob->data=(unsigned char *) ResizeQuantumMemory(
5050             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
5051           (void) SyncBlob(image);
5052           if (image->blob->data == (unsigned char *) NULL)
5053             {
5054               (void) DetachBlob(image->blob);
5055               return(0);
5056             }
5057         }
5058       q=image->blob->data+image->blob->offset;
5059       (void) memcpy(q,p,length);
5060       image->blob->offset+=length;
5061       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
5062         image->blob->length=(size_t) image->blob->offset;
5063       count=(ssize_t) length;
5064       break;
5065     }
5066     case UserStream:
5067     {
5068       count=image->blob->user_info->writer((const unsigned char *) data,
5069         length,image->blob->user_info->data);
5070       break;
5071     }
5072   }
5073   return(count);
5074 }
5075 \f
5076 /*
5077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5078 %                                                                             %
5079 %                                                                             %
5080 %                                                                             %
5081 +  W r i t e B l o b B y t e                                                  %
5082 %                                                                             %
5083 %                                                                             %
5084 %                                                                             %
5085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5086 %
5087 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
5088 %  written (either 0 or 1);
5089 %
5090 %  The format of the WriteBlobByte method is:
5091 %
5092 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
5093 %
5094 %  A description of each parameter follows.
5095 %
5096 %    o image: the image.
5097 %
5098 %    o value: Specifies the value to write.
5099 %
5100 */
5101 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5102 {
5103   assert(image != (Image *) NULL);
5104   assert(image->signature == MagickCoreSignature);
5105   return(WriteBlobStream(image,1,&value));
5106 }
5107 \f
5108 /*
5109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5110 %                                                                             %
5111 %                                                                             %
5112 %                                                                             %
5113 +  W r i t e B l o b F l o a t                                                %
5114 %                                                                             %
5115 %                                                                             %
5116 %                                                                             %
5117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5118 %
5119 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5120 %  specified by the endian member of the image structure.
5121 %
5122 %  The format of the WriteBlobFloat method is:
5123 %
5124 %      ssize_t WriteBlobFloat(Image *image,const float value)
5125 %
5126 %  A description of each parameter follows.
5127 %
5128 %    o image: the image.
5129 %
5130 %    o value: Specifies the value to write.
5131 %
5132 */
5133 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5134 {
5135   union
5136   {
5137     unsigned int
5138       unsigned_value;
5139
5140     float
5141       float_value;
5142   } quantum;
5143
5144   quantum.unsigned_value=0U;
5145   quantum.float_value=value;
5146   return(WriteBlobLong(image,quantum.unsigned_value));
5147 }
5148 \f
5149 /*
5150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5151 %                                                                             %
5152 %                                                                             %
5153 %                                                                             %
5154 +  W r i t e B l o b L o n g                                                  %
5155 %                                                                             %
5156 %                                                                             %
5157 %                                                                             %
5158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5159 %
5160 %  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5161 %  byte-order specified by the endian member of the image structure.
5162 %
5163 %  The format of the WriteBlobLong method is:
5164 %
5165 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
5166 %
5167 %  A description of each parameter follows.
5168 %
5169 %    o image: the image.
5170 %
5171 %    o value: Specifies the value to write.
5172 %
5173 */
5174 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5175 {
5176   unsigned char
5177     buffer[4];
5178
5179   assert(image != (Image *) NULL);
5180   assert(image->signature == MagickCoreSignature);
5181   if (image->endian == LSBEndian)
5182     {
5183       buffer[0]=(unsigned char) value;
5184       buffer[1]=(unsigned char) (value >> 8);
5185       buffer[2]=(unsigned char) (value >> 16);
5186       buffer[3]=(unsigned char) (value >> 24);
5187       return(WriteBlobStream(image,4,buffer));
5188     }
5189   buffer[0]=(unsigned char) (value >> 24);
5190   buffer[1]=(unsigned char) (value >> 16);
5191   buffer[2]=(unsigned char) (value >> 8);
5192   buffer[3]=(unsigned char) value;
5193   return(WriteBlobStream(image,4,buffer));
5194 }
5195 \f
5196 /*
5197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5198 %                                                                             %
5199 %                                                                             %
5200 %                                                                             %
5201 +   W r i t e B l o b S h o r t                                               %
5202 %                                                                             %
5203 %                                                                             %
5204 %                                                                             %
5205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5206 %
5207 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
5208 %  byte-order specified by the endian member of the image structure.
5209 %
5210 %  The format of the WriteBlobShort method is:
5211 %
5212 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
5213 %
5214 %  A description of each parameter follows.
5215 %
5216 %    o image: the image.
5217 %
5218 %    o value:  Specifies the value to write.
5219 %
5220 */
5221 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5222 {
5223   unsigned char
5224     buffer[2];
5225
5226   assert(image != (Image *) NULL);
5227   assert(image->signature == MagickCoreSignature);
5228   if (image->endian == LSBEndian)
5229     {
5230       buffer[0]=(unsigned char) value;
5231       buffer[1]=(unsigned char) (value >> 8);
5232       return(WriteBlobStream(image,2,buffer));
5233     }
5234   buffer[0]=(unsigned char) (value >> 8);
5235   buffer[1]=(unsigned char) value;
5236   return(WriteBlobStream(image,2,buffer));
5237 }
5238 \f
5239 /*
5240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5241 %                                                                             %
5242 %                                                                             %
5243 %                                                                             %
5244 +  W r i t e B l o b L S B L o n g                                            %
5245 %                                                                             %
5246 %                                                                             %
5247 %                                                                             %
5248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5249 %
5250 %  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
5251 %  least-significant byte first order.
5252 %
5253 %  The format of the WriteBlobLSBLong method is:
5254 %
5255 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5256 %
5257 %  A description of each parameter follows.
5258 %
5259 %    o image: the image.
5260 %
5261 %    o value: Specifies the value to write.
5262 %
5263 */
5264 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5265 {
5266   unsigned char
5267     buffer[4];
5268
5269   assert(image != (Image *) NULL);
5270   assert(image->signature == MagickCoreSignature);
5271   buffer[0]=(unsigned char) value;
5272   buffer[1]=(unsigned char) (value >> 8);
5273   buffer[2]=(unsigned char) (value >> 16);
5274   buffer[3]=(unsigned char) (value >> 24);
5275   return(WriteBlobStream(image,4,buffer));
5276 }
5277 \f
5278 /*
5279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5280 %                                                                             %
5281 %                                                                             %
5282 %                                                                             %
5283 +   W r i t e B l o b L S B S h o r t                                         %
5284 %                                                                             %
5285 %                                                                             %
5286 %                                                                             %
5287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5288 %
5289 %  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
5290 %  least-significant byte first order.
5291 %
5292 %  The format of the WriteBlobLSBShort method is:
5293 %
5294 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5295 %
5296 %  A description of each parameter follows.
5297 %
5298 %    o image: the image.
5299 %
5300 %    o value:  Specifies the value to write.
5301 %
5302 */
5303 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5304 {
5305   unsigned char
5306     buffer[2];
5307
5308   assert(image != (Image *) NULL);
5309   assert(image->signature == MagickCoreSignature);
5310   buffer[0]=(unsigned char) value;
5311   buffer[1]=(unsigned char) (value >> 8);
5312   return(WriteBlobStream(image,2,buffer));
5313 }
5314 \f
5315 /*
5316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5317 %                                                                             %
5318 %                                                                             %
5319 %                                                                             %
5320 +  W r i t e B l o b L S B S i g n e d L o n g                                %
5321 %                                                                             %
5322 %                                                                             %
5323 %                                                                             %
5324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5325 %
5326 %  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
5327 %  least-significant byte first order.
5328 %
5329 %  The format of the WriteBlobLSBSignedLong method is:
5330 %
5331 %      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5332 %
5333 %  A description of each parameter follows.
5334 %
5335 %    o image: the image.
5336 %
5337 %    o value: Specifies the value to write.
5338 %
5339 */
5340 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5341 {
5342   union
5343   {
5344     unsigned int
5345       unsigned_value;
5346
5347     signed int
5348       signed_value;
5349   } quantum;
5350
5351   unsigned char
5352     buffer[4];
5353
5354   assert(image != (Image *) NULL);
5355   assert(image->signature == MagickCoreSignature);
5356   quantum.signed_value=value;
5357   buffer[0]=(unsigned char) quantum.unsigned_value;
5358   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5359   buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5360   buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5361   return(WriteBlobStream(image,4,buffer));
5362 }
5363 \f
5364 /*
5365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5366 %                                                                             %
5367 %                                                                             %
5368 %                                                                             %
5369 +   W r i t e B l o b L S B S i g n e d S h o r t                             %
5370 %                                                                             %
5371 %                                                                             %
5372 %                                                                             %
5373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5374 %
5375 %  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
5376 %  in least-significant byte first order.
5377 %
5378 %  The format of the WriteBlobLSBSignedShort method is:
5379 %
5380 %      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
5381 %
5382 %  A description of each parameter follows.
5383 %
5384 %    o image: the image.
5385 %
5386 %    o value:  Specifies the value to write.
5387 %
5388 */
5389 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
5390   const signed short value)
5391 {
5392   union
5393   {
5394     unsigned short
5395       unsigned_value;
5396
5397     signed short
5398       signed_value;
5399   } quantum;
5400
5401   unsigned char
5402     buffer[2];
5403
5404   assert(image != (Image *) NULL);
5405   assert(image->signature == MagickCoreSignature);
5406   quantum.signed_value=value;
5407   buffer[0]=(unsigned char) quantum.unsigned_value;
5408   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5409   return(WriteBlobStream(image,2,buffer));
5410 }
5411 \f
5412 /*
5413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5414 %                                                                             %
5415 %                                                                             %
5416 %                                                                             %
5417 +  W r i t e B l o b M S B L o n g                                            %
5418 %                                                                             %
5419 %                                                                             %
5420 %                                                                             %
5421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5422 %
5423 %  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
5424 %  most-significant byte first order.
5425 %
5426 %  The format of the WriteBlobMSBLong method is:
5427 %
5428 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5429 %
5430 %  A description of each parameter follows.
5431 %
5432 %    o value:  Specifies the value to write.
5433 %
5434 %    o image: the image.
5435 %
5436 */
5437 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5438 {
5439   unsigned char
5440     buffer[4];
5441
5442   assert(image != (Image *) NULL);
5443   assert(image->signature == MagickCoreSignature);
5444   buffer[0]=(unsigned char) (value >> 24);
5445   buffer[1]=(unsigned char) (value >> 16);
5446   buffer[2]=(unsigned char) (value >> 8);
5447   buffer[3]=(unsigned char) value;
5448   return(WriteBlobStream(image,4,buffer));
5449 }
5450 \f
5451 /*
5452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5453 %                                                                             %
5454 %                                                                             %
5455 %                                                                             %
5456 +  W r i t e B l o b M S B L o n g L o n g                                    %
5457 %                                                                             %
5458 %                                                                             %
5459 %                                                                             %
5460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5461 %
5462 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
5463 %  most-significant byte first order.
5464 %
5465 %  The format of the WriteBlobMSBLongLong method is:
5466 %
5467 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
5468 %
5469 %  A description of each parameter follows.
5470 %
5471 %    o value:  Specifies the value to write.
5472 %
5473 %    o image: the image.
5474 %
5475 */
5476 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
5477   const MagickSizeType value)
5478 {
5479   unsigned char
5480     buffer[8];
5481
5482   assert(image != (Image *) NULL);
5483   assert(image->signature == MagickCoreSignature);
5484   buffer[0]=(unsigned char) (value >> 56);
5485   buffer[1]=(unsigned char) (value >> 48);
5486   buffer[2]=(unsigned char) (value >> 40);
5487   buffer[3]=(unsigned char) (value >> 32);
5488   buffer[4]=(unsigned char) (value >> 24);
5489   buffer[5]=(unsigned char) (value >> 16);
5490   buffer[6]=(unsigned char) (value >> 8);
5491   buffer[7]=(unsigned char) value;
5492   return(WriteBlobStream(image,8,buffer));
5493 }
5494 \f
5495 /*
5496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5497 %                                                                             %
5498 %                                                                             %
5499 %                                                                             %
5500 +  W r i t e B l o b M S B S i g n e d L o n g                                %
5501 %                                                                             %
5502 %                                                                             %
5503 %                                                                             %
5504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5505 %
5506 %  WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
5507 %  most-significant byte first order.
5508 %
5509 %  The format of the WriteBlobMSBSignedLong method is:
5510 %
5511 %      ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5512 %
5513 %  A description of each parameter follows.
5514 %
5515 %    o image: the image.
5516 %
5517 %    o value: Specifies the value to write.
5518 %
5519 */
5520 MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5521 {
5522   union
5523   {
5524     unsigned int
5525       unsigned_value;
5526
5527     signed int
5528       signed_value;
5529   } quantum;
5530
5531   unsigned char
5532     buffer[4];
5533
5534   assert(image != (Image *) NULL);
5535   assert(image->signature == MagickCoreSignature);
5536   quantum.signed_value=value;
5537   buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5538   buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5539   buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5540   buffer[3]=(unsigned char) quantum.unsigned_value;
5541   return(WriteBlobStream(image,4,buffer));
5542 }
5543 \f
5544 /*
5545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5546 %                                                                             %
5547 %                                                                             %
5548 %                                                                             %
5549 +   W r i t e B l o b M S B S i g n e d S h o r t                             %
5550 %                                                                             %
5551 %                                                                             %
5552 %                                                                             %
5553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5554 %
5555 %  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5556 %  in most-significant byte first order.
5557 %
5558 %  The format of the WriteBlobMSBSignedShort method is:
5559 %
5560 %      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5561 %
5562 %  A description of each parameter follows.
5563 %
5564 %    o image: the image.
5565 %
5566 %    o value:  Specifies the value to write.
5567 %
5568 */
5569 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
5570   const signed short value)
5571 {
5572   union
5573   {
5574     unsigned short
5575       unsigned_value;
5576
5577     signed short
5578       signed_value;
5579   } quantum;
5580
5581   unsigned char
5582     buffer[2];
5583
5584   assert(image != (Image *) NULL);
5585   assert(image->signature == MagickCoreSignature);
5586   quantum.signed_value=value;
5587   buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5588   buffer[1]=(unsigned char) quantum.unsigned_value;
5589   return(WriteBlobStream(image,2,buffer));
5590 }
5591 \f
5592 /*
5593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5594 %                                                                             %
5595 %                                                                             %
5596 %                                                                             %
5597 +  W r i t e B l o b M S B S h o r t                                          %
5598 %                                                                             %
5599 %                                                                             %
5600 %                                                                             %
5601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5602 %
5603 %  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
5604 %  most-significant byte first order.
5605 %
5606 %  The format of the WriteBlobMSBShort method is:
5607 %
5608 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5609 %
5610 %  A description of each parameter follows.
5611 %
5612 %   o  value:  Specifies the value to write.
5613 %
5614 %   o  file:  Specifies the file to write the data to.
5615 %
5616 */
5617 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5618 {
5619   unsigned char
5620     buffer[2];
5621
5622   assert(image != (Image *) NULL);
5623   assert(image->signature == MagickCoreSignature);
5624   buffer[0]=(unsigned char) (value >> 8);
5625   buffer[1]=(unsigned char) value;
5626   return(WriteBlobStream(image,2,buffer));
5627 }
5628 \f
5629 /*
5630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5631 %                                                                             %
5632 %                                                                             %
5633 %                                                                             %
5634 +  W r i t e B l o b S t r i n g                                              %
5635 %                                                                             %
5636 %                                                                             %
5637 %                                                                             %
5638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5639 %
5640 %  WriteBlobString() write a string to a blob.  It returns the number of
5641 %  characters written.
5642 %
5643 %  The format of the WriteBlobString method is:
5644 %
5645 %      ssize_t WriteBlobString(Image *image,const char *string)
5646 %
5647 %  A description of each parameter follows.
5648 %
5649 %    o image: the image.
5650 %
5651 %    o string: Specifies the string to write.
5652 %
5653 */
5654 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
5655 {
5656   assert(image != (Image *) NULL);
5657   assert(image->signature == MagickCoreSignature);
5658   assert(string != (const char *) NULL);
5659   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
5660 }