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