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