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