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