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