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