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