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