]> granicus.if.org Git - imagemagick/blob - MagickCore/blob.c
Removed invalid assert.
[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-2017 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 %    https://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     synchronize,
133     status,
134     temporary;
135
136   StreamType
137     type;
138
139   FileInfo
140     file_info;
141
142   struct stat
143     properties;
144
145   StreamHandler
146     stream;
147
148   CustomStreamInfo
149     *custom_stream;
150
151   unsigned char
152     *data;
153
154   MagickBooleanType
155     debug;
156
157   SemaphoreInfo
158     *semaphore;
159
160   ssize_t
161     reference_count;
162
163   size_t
164     signature;
165 };
166
167 struct _CustomStreamInfo
168 {
169   CustomStreamHandler
170     reader,
171     writer;
172
173   CustomStreamSeeker
174     seeker;
175
176   CustomStreamTeller
177     teller;
178
179   void
180     *data;
181
182   size_t
183     signature;
184 };
185 \f
186 /*
187   Forward declarations.
188 */
189 static int
190   SyncBlob(Image *);
191 \f
192 /*
193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 %                                                                             %
195 %                                                                             %
196 %                                                                             %
197 +   A c q u i r e C u s t o m S t r e a m I n f o                             %
198 %                                                                             %
199 %                                                                             %
200 %                                                                             %
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202 %
203 %  AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
204 %
205 %  The format of the AcquireCustomStreamInfo method is:
206 %
207 %      CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
208 %
209 %  A description of each parameter follows:
210 %
211 %    o exception: return any errors or warnings in this structure.
212 %
213 */
214 MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
215   ExceptionInfo *exception)
216 {
217   CustomStreamInfo
218     *custom_stream;
219
220   custom_stream=(CustomStreamInfo *) AcquireMagickMemory(
221     sizeof(*custom_stream));
222   if (custom_stream == (CustomStreamInfo *) NULL)
223     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
224   (void) ResetMagickMemory(custom_stream,0,sizeof(*custom_stream));
225   custom_stream->signature=MagickCoreSignature;
226   return(custom_stream);
227 }
228 \f
229 /*
230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231 %                                                                             %
232 %                                                                             %
233 %                                                                             %
234 +   A t t a c h B l o b                                                       %
235 %                                                                             %
236 %                                                                             %
237 %                                                                             %
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 %
240 %  AttachBlob() attaches a blob to the BlobInfo structure.
241 %
242 %  The format of the AttachBlob method is:
243 %
244 %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
245 %
246 %  A description of each parameter follows:
247 %
248 %    o blob_info: Specifies a pointer to a BlobInfo structure.
249 %
250 %    o blob: the address of a character stream in one of the image formats
251 %      understood by ImageMagick.
252 %
253 %    o length: This size_t integer reflects the length in bytes of the blob.
254 %
255 */
256 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
257   const size_t length)
258 {
259   assert(blob_info != (BlobInfo *) NULL);
260   if (blob_info->debug != MagickFalse)
261     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
262   blob_info->length=length;
263   blob_info->extent=length;
264   blob_info->quantum=(size_t) MagickMaxBlobExtent;
265   blob_info->offset=0;
266   blob_info->type=BlobStream;
267   blob_info->file_info.file=(FILE *) NULL;
268   blob_info->data=(unsigned char *) blob;
269   blob_info->mapped=MagickFalse;
270 }
271 \f
272 /*
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 %                                                                             %
275 %                                                                             %
276 %                                                                             %
277 +   B l o b T o F i l e                                                       %
278 %                                                                             %
279 %                                                                             %
280 %                                                                             %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 %
283 %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
284 %  occurs otherwise MagickTrue.
285 %
286 %  The format of the BlobToFile method is:
287 %
288 %       MagickBooleanType BlobToFile(char *filename,const void *blob,
289 %         const size_t length,ExceptionInfo *exception)
290 %
291 %  A description of each parameter follows:
292 %
293 %    o filename: Write the blob to this file.
294 %
295 %    o blob: the address of a blob.
296 %
297 %    o length: This length in bytes of the blob.
298 %
299 %    o exception: return any errors or warnings in this structure.
300 %
301 */
302 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
303   const size_t length,ExceptionInfo *exception)
304 {
305   int
306     file;
307
308   register size_t
309     i;
310
311   ssize_t
312     count;
313
314   assert(filename != (const char *) NULL);
315   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
316   assert(blob != (const void *) NULL);
317   if (*filename == '\0')
318     file=AcquireUniqueFileResource(filename);
319   else
320     file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
321   if (file == -1)
322     {
323       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
324       return(MagickFalse);
325     }
326   for (i=0; i < length; i+=count)
327   {
328     count=write(file,(const char *) blob+i,MagickMin(length-i,SSIZE_MAX));
329     if (count <= 0)
330       {
331         count=0;
332         if (errno != EINTR)
333           break;
334       }
335   }
336   file=close(file);
337   if ((file == -1) || (i < length))
338     {
339       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
340       return(MagickFalse);
341     }
342   return(MagickTrue);
343 }
344 \f
345 /*
346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347 %                                                                             %
348 %                                                                             %
349 %                                                                             %
350 %   B l o b T o I m a g e                                                     %
351 %                                                                             %
352 %                                                                             %
353 %                                                                             %
354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355 %
356 %  BlobToImage() implements direct to memory image formats.  It returns the
357 %  blob as an image.
358 %
359 %  The format of the BlobToImage method is:
360 %
361 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
362 %        const size_t length,ExceptionInfo *exception)
363 %
364 %  A description of each parameter follows:
365 %
366 %    o image_info: the image info.
367 %
368 %    o blob: the address of a character stream in one of the image formats
369 %      understood by ImageMagick.
370 %
371 %    o length: This size_t integer reflects the length in bytes of the blob.
372 %
373 %    o exception: return any errors or warnings in this structure.
374 %
375 */
376 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
377   const size_t length,ExceptionInfo *exception)
378 {
379   const MagickInfo
380     *magick_info;
381
382   Image
383     *image;
384
385   ImageInfo
386     *blob_info,
387     *clone_info;
388
389   MagickBooleanType
390     status;
391
392   assert(image_info != (ImageInfo *) NULL);
393   assert(image_info->signature == MagickCoreSignature);
394   if (image_info->debug != MagickFalse)
395     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
396       image_info->filename);
397   assert(exception != (ExceptionInfo *) NULL);
398   if ((blob == (const void *) NULL) || (length == 0))
399     {
400       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
401         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
402       return((Image *) NULL);
403     }
404   blob_info=CloneImageInfo(image_info);
405   blob_info->blob=(void *) blob;
406   blob_info->length=length;
407   if (*blob_info->magick == '\0')
408     (void) SetImageInfo(blob_info,0,exception);
409   magick_info=GetMagickInfo(blob_info->magick,exception);
410   if (magick_info == (const MagickInfo *) NULL)
411     {
412       (void) ThrowMagickException(exception,GetMagickModule(),
413         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
414         blob_info->magick);
415       blob_info=DestroyImageInfo(blob_info);
416       return((Image *) NULL);
417     }
418   if (GetMagickBlobSupport(magick_info) != MagickFalse)
419     {
420       /*
421         Native blob support for this image format.
422       */
423       (void) CopyMagickString(blob_info->filename,image_info->filename,
424         MagickPathExtent);
425       (void) CopyMagickString(blob_info->magick,image_info->magick,
426         MagickPathExtent);
427       image=ReadImage(blob_info,exception);
428       if (image != (Image *) NULL)
429         (void) DetachBlob(image->blob);
430       blob_info=DestroyImageInfo(blob_info);
431       return(image);
432     }
433   /*
434     Write blob to a temporary file on disk.
435   */
436   blob_info->blob=(void *) NULL;
437   blob_info->length=0;
438   *blob_info->filename='\0';
439   status=BlobToFile(blob_info->filename,blob,length,exception);
440   if (status == MagickFalse)
441     {
442       (void) RelinquishUniqueFileResource(blob_info->filename);
443       blob_info=DestroyImageInfo(blob_info);
444       return((Image *) NULL);
445     }
446   clone_info=CloneImageInfo(blob_info);
447   (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
448     blob_info->magick,blob_info->filename);
449   image=ReadImage(clone_info,exception);
450   if (image != (Image *) NULL)
451     {
452       Image
453         *images;
454
455       /*
456         Restore original filenames and image format.
457       */
458       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
459       {
460         (void) CopyMagickString(images->filename,image_info->filename,
461           MagickPathExtent);
462         (void) CopyMagickString(images->magick_filename,image_info->filename,
463           MagickPathExtent);
464         (void) CopyMagickString(images->magick,magick_info->name,
465           MagickPathExtent);
466         images=GetNextImageInList(images);
467       }
468     }
469   clone_info=DestroyImageInfo(clone_info);
470   (void) RelinquishUniqueFileResource(blob_info->filename);
471   blob_info=DestroyImageInfo(blob_info);
472   return(image);
473 }
474 \f
475 /*
476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 %                                                                             %
478 %                                                                             %
479 %                                                                             %
480 +   C l o n e B l o b I n f o                                                 %
481 %                                                                             %
482 %                                                                             %
483 %                                                                             %
484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 %
486 %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
487 %  blob info is NULL, a new one.
488 %
489 %  The format of the CloneBlobInfo method is:
490 %
491 %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
492 %
493 %  A description of each parameter follows:
494 %
495 %    o blob_info: the blob info.
496 %
497 */
498 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
499 {
500   BlobInfo
501     *clone_info;
502
503   clone_info=(BlobInfo *) AcquireMagickMemory(sizeof(*clone_info));
504   if (clone_info == (BlobInfo *) NULL)
505     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
506   GetBlobInfo(clone_info);
507   if (blob_info == (BlobInfo *) NULL)
508     return(clone_info);
509   clone_info->length=blob_info->length;
510   clone_info->extent=blob_info->extent;
511   clone_info->synchronize=blob_info->synchronize;
512   clone_info->quantum=blob_info->quantum;
513   clone_info->mapped=blob_info->mapped;
514   clone_info->eof=blob_info->eof;
515   clone_info->offset=blob_info->offset;
516   clone_info->size=blob_info->size;
517   clone_info->exempt=blob_info->exempt;
518   clone_info->status=blob_info->status;
519   clone_info->temporary=blob_info->temporary;
520   clone_info->type=blob_info->type;
521   clone_info->file_info.file=blob_info->file_info.file;
522   clone_info->properties=blob_info->properties;
523   clone_info->stream=blob_info->stream;
524   clone_info->custom_stream=blob_info->custom_stream;
525   clone_info->data=blob_info->data;
526   clone_info->debug=IsEventLogging();
527   clone_info->reference_count=1;
528   return(clone_info);
529 }
530 \f
531 /*
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 %                                                                             %
534 %                                                                             %
535 %                                                                             %
536 +   C l o s e B l o b                                                         %
537 %                                                                             %
538 %                                                                             %
539 %                                                                             %
540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541 %
542 %  CloseBlob() closes a stream associated with the image.
543 %
544 %  The format of the CloseBlob method is:
545 %
546 %      MagickBooleanType CloseBlob(Image *image)
547 %
548 %  A description of each parameter follows:
549 %
550 %    o image: the image.
551 %
552 */
553 MagickExport MagickBooleanType CloseBlob(Image *image)
554 {
555   int
556     status;
557
558   /*
559     Close image file.
560   */
561   assert(image != (Image *) NULL);
562   assert(image->signature == MagickCoreSignature);
563   if (image->debug != MagickFalse)
564     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
565   assert(image->blob != (BlobInfo *) NULL);
566   if (image->blob->type == UndefinedStream)
567     return(MagickTrue);
568   status=SyncBlob(image);
569   switch (image->blob->type)
570   {
571     case UndefinedStream:
572     case StandardStream:
573       break;
574     case FileStream:
575     case PipeStream:
576     {
577       if (image->blob->synchronize != MagickFalse)
578         status=fsync(fileno(image->blob->file_info.file));
579       status=ferror(image->blob->file_info.file);
580       break;
581     }
582     case ZipStream:
583     {
584 #if defined(MAGICKCORE_ZLIB_DELEGATE)
585       (void) gzerror(image->blob->file_info.gzfile,&status);
586 #endif
587       break;
588     }
589     case BZipStream:
590     {
591 #if defined(MAGICKCORE_BZLIB_DELEGATE)
592       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
593 #endif
594       break;
595     }
596     case FifoStream:
597       break;
598     case BlobStream:
599     {
600       if ((image->blob->file_info.file != (FILE *) NULL) &&
601           (image->blob->synchronize != MagickFalse))
602         {
603           (void) fsync(fileno(image->blob->file_info.file));
604           status=ferror(image->blob->file_info.file);
605         }
606       break;
607     }
608     case CustomStream:
609       break;
610   }
611   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
612   image->blob->size=GetBlobSize(image);
613   image->extent=image->blob->size;
614   image->blob->eof=MagickFalse;
615   if (image->blob->exempt != MagickFalse)
616     {
617       image->blob->type=UndefinedStream;
618       return(image->blob->status);
619     }
620   switch (image->blob->type)
621   {
622     case UndefinedStream:
623     case StandardStream:
624       break;
625     case FileStream:
626     {
627       status=fclose(image->blob->file_info.file);
628       break;
629     }
630     case PipeStream:
631     {
632 #if defined(MAGICKCORE_HAVE_PCLOSE)
633       status=pclose(image->blob->file_info.file);
634 #endif
635       break;
636     }
637     case ZipStream:
638     {
639 #if defined(MAGICKCORE_ZLIB_DELEGATE)
640       status=gzclose(image->blob->file_info.gzfile);
641 #endif
642       break;
643     }
644     case BZipStream:
645     {
646 #if defined(MAGICKCORE_BZLIB_DELEGATE)
647       BZ2_bzclose(image->blob->file_info.bzfile);
648 #endif
649       break;
650     }
651     case FifoStream:
652       break;
653     case BlobStream:
654     {
655       if (image->blob->file_info.file != (FILE *) NULL)
656         status=fclose(image->blob->file_info.file);
657       break;
658     }
659     case CustomStream:
660       break;
661   }
662   (void) DetachBlob(image->blob);
663   image->blob->status=status < 0 ? MagickTrue : MagickFalse;
664   return(image->blob->status);
665 }
666 \f
667 /*
668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669 %                                                                             %
670 %                                                                             %
671 %                                                                             %
672 +   D e s t r o y B l o b                                                     %
673 %                                                                             %
674 %                                                                             %
675 %                                                                             %
676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677 %
678 %  DestroyBlob() deallocates memory associated with a blob.
679 %
680 %  The format of the DestroyBlob method is:
681 %
682 %      void DestroyBlob(Image *image)
683 %
684 %  A description of each parameter follows:
685 %
686 %    o image: the image.
687 %
688 */
689 MagickExport void DestroyBlob(Image *image)
690 {
691   MagickBooleanType
692     destroy;
693
694   assert(image != (Image *) NULL);
695   assert(image->signature == MagickCoreSignature);
696   if (image->debug != MagickFalse)
697     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
698   assert(image->blob != (BlobInfo *) NULL);
699   assert(image->blob->signature == MagickCoreSignature);
700   destroy=MagickFalse;
701   LockSemaphoreInfo(image->blob->semaphore);
702   image->blob->reference_count--;
703   assert(image->blob->reference_count >= 0);
704   if (image->blob->reference_count == 0)
705     destroy=MagickTrue;
706   UnlockSemaphoreInfo(image->blob->semaphore);
707   if (destroy == MagickFalse)
708     return;
709   (void) CloseBlob(image);
710   if (image->blob->mapped != MagickFalse)
711     {
712       (void) UnmapBlob(image->blob->data,image->blob->length);
713       RelinquishMagickResource(MapResource,image->blob->length);
714     }
715   if (image->blob->semaphore != (SemaphoreInfo *) NULL)
716     RelinquishSemaphoreInfo(&image->blob->semaphore);
717   image->blob->signature=(~MagickCoreSignature);
718   image->blob=(BlobInfo *) RelinquishMagickMemory(image->blob);
719 }
720 \f
721 /*
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 %                                                                             %
724 %                                                                             %
725 %                                                                             %
726 +   D e s t r o y C u s t o m S t r e a m I n f o                             %
727 %                                                                             %
728 %                                                                             %
729 %                                                                             %
730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731 %
732 %  DestroyCustomStreamInfo() destroys memory associated with the
733 %  CustomStreamInfo structure.
734 %
735 %  The format of the DestroyCustomStreamInfo method is:
736 %
737 %      CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
738 %
739 %  A description of each parameter follows:
740 %
741 %    o custom_stream: the custom stream info.
742 %
743 */
744 MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
745   CustomStreamInfo *custom_stream)
746 {
747   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
748   assert(custom_stream != (CustomStreamInfo *) NULL);
749   assert(custom_stream->signature == MagickCoreSignature);
750   custom_stream->signature=(~MagickCoreSignature);
751   custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
752   return(custom_stream);
753 }
754 \f
755 /*
756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
757 %                                                                             %
758 %                                                                             %
759 %                                                                             %
760 +   D e t a c h B l o b                                                       %
761 %                                                                             %
762 %                                                                             %
763 %                                                                             %
764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
765 %
766 %  DetachBlob() detaches a blob from the BlobInfo structure.
767 %
768 %  The format of the DetachBlob method is:
769 %
770 %      void *DetachBlob(BlobInfo *blob_info)
771 %
772 %  A description of each parameter follows:
773 %
774 %    o blob_info: Specifies a pointer to a BlobInfo structure.
775 %
776 */
777 MagickExport void *DetachBlob(BlobInfo *blob_info)
778 {
779   void
780     *data;
781
782   assert(blob_info != (BlobInfo *) NULL);
783   if (blob_info->debug != MagickFalse)
784     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
785   if (blob_info->mapped != MagickFalse)
786     {
787       (void) UnmapBlob(blob_info->data,blob_info->length);
788       blob_info->data=(unsigned char *) NULL;
789       RelinquishMagickResource(MapResource,blob_info->length);
790     }
791   blob_info->mapped=MagickFalse;
792   blob_info->length=0;
793   blob_info->offset=0;
794   blob_info->eof=MagickFalse;
795   blob_info->exempt=MagickFalse;
796   blob_info->type=UndefinedStream;
797   blob_info->file_info.file=(FILE *) NULL;
798   data=blob_info->data;
799   blob_info->data=(unsigned char *) NULL;
800   blob_info->stream=(StreamHandler) NULL;
801   blob_info->custom_stream=(CustomStreamInfo *) NULL;
802   return(data);
803 }
804 \f
805 /*
806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807 %                                                                             %
808 %                                                                             %
809 %                                                                             %
810 +   D i s a s s o c i a t e B l o b                                           %
811 %                                                                             %
812 %                                                                             %
813 %                                                                             %
814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815 %
816 %  DisassociateBlob() disassociates the image stream.  It checks if the
817 %  blob of the specified image is referenced by other images. If the reference
818 %  count is higher then 1 a new blob is assigned to the specified image.
819 %
820 %  The format of the DisassociateBlob method is:
821 %
822 %      void DisassociateBlob(const Image *image)
823 %
824 %  A description of each parameter follows:
825 %
826 %    o image: the image.
827 %
828 */
829 MagickExport void DisassociateBlob(Image *image)
830 {
831   BlobInfo
832     *blob;
833
834   MagickBooleanType
835     clone;
836
837   assert(image != (Image *) NULL);
838   assert(image->signature == MagickCoreSignature);
839   if (image->debug != MagickFalse)
840     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
841   assert(image->blob != (BlobInfo *) NULL);
842   assert(image->blob->signature == MagickCoreSignature);
843   clone=MagickFalse;
844   LockSemaphoreInfo(image->blob->semaphore);
845   assert(image->blob->reference_count >= 0);
846   if (image->blob->reference_count > 1)
847     clone=MagickTrue;
848   UnlockSemaphoreInfo(image->blob->semaphore);
849   if (clone == MagickFalse)
850     return;
851   blob=CloneBlobInfo(image->blob);
852   DestroyBlob(image);
853   image->blob=blob;
854 }
855 \f
856 /*
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858 %                                                                             %
859 %                                                                             %
860 %                                                                             %
861 +  D i s c a r d B l o b B y t e s                                            %
862 %                                                                             %
863 %                                                                             %
864 %                                                                             %
865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 %
867 %  DiscardBlobBytes() discards bytes in a blob.
868 %
869 %  The format of the DiscardBlobBytes method is:
870 %
871 %      MagickBooleanType DiscardBlobBytes(Image *image,
872 %        const MagickSizeType length)
873 %
874 %  A description of each parameter follows.
875 %
876 %    o image: the image.
877 %
878 %    o length:  the number of bytes to skip.
879 %
880 */
881 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
882   const MagickSizeType length)
883 {
884   register MagickOffsetType
885     i;
886
887   size_t
888     quantum;
889
890   ssize_t
891     count;
892
893   unsigned char
894     buffer[16384];
895
896   assert(image != (Image *) NULL);
897   assert(image->signature == MagickCoreSignature);
898   if (length != (MagickSizeType) ((MagickOffsetType) length))
899     return(MagickFalse);
900   count=0;
901   for (i=0; i < (MagickOffsetType) length; i+=count)
902   {
903     quantum=(size_t) MagickMin(length-i,sizeof(buffer));
904     (void) ReadBlobStream(image,quantum,buffer,&count);
905     if (count <= 0)
906       {
907         count=0;
908         if (errno != EINTR)
909           break;
910       }
911   }
912   return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
913 }
914 \f
915 /*
916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917 %                                                                             %
918 %                                                                             %
919 %                                                                             %
920 +   D u p l i c a t e s B l o b                                               %
921 %                                                                             %
922 %                                                                             %
923 %                                                                             %
924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
925 %
926 %  DuplicateBlob() duplicates a blob descriptor.
927 %
928 %  The format of the DuplicateBlob method is:
929 %
930 %      void DuplicateBlob(Image *image,const Image *duplicate)
931 %
932 %  A description of each parameter follows:
933 %
934 %    o image: the image.
935 %
936 %    o duplicate: the duplicate image.
937 %
938 */
939 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
940 {
941   assert(image != (Image *) NULL);
942   assert(image->signature == MagickCoreSignature);
943   if (image->debug != MagickFalse)
944     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
945   assert(duplicate != (Image *) NULL);
946   assert(duplicate->signature == MagickCoreSignature);
947   DestroyBlob(image);
948   image->blob=ReferenceBlob(duplicate->blob);
949 }
950 \f
951 /*
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %                                                                             %
954 %                                                                             %
955 %                                                                             %
956 +  E O F B l o b                                                              %
957 %                                                                             %
958 %                                                                             %
959 %                                                                             %
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961 %
962 %  EOFBlob() returns a non-zero value when EOF has been detected reading from
963 %  a blob or file.
964 %
965 %  The format of the EOFBlob method is:
966 %
967 %      int EOFBlob(const Image *image)
968 %
969 %  A description of each parameter follows:
970 %
971 %    o image: the image.
972 %
973 */
974 MagickExport int EOFBlob(const Image *image)
975 {
976   assert(image != (Image *) NULL);
977   assert(image->signature == MagickCoreSignature);
978   if (image->debug != MagickFalse)
979     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
980   assert(image->blob != (BlobInfo *) NULL);
981   assert(image->blob->type != UndefinedStream);
982   switch (image->blob->type)
983   {
984     case UndefinedStream:
985     case StandardStream:
986       break;
987     case FileStream:
988     case PipeStream:
989     {
990       image->blob->eof=feof(image->blob->file_info.file) != 0 ? MagickTrue :
991         MagickFalse;
992       break;
993     }
994     case ZipStream:
995     {
996       image->blob->eof=MagickFalse;
997       break;
998     }
999     case BZipStream:
1000     {
1001 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1002       int
1003         status;
1004
1005       status=0;
1006       (void) BZ2_bzerror(image->blob->file_info.bzfile,&status);
1007       image->blob->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
1008 #endif
1009       break;
1010     }
1011     case FifoStream:
1012     {
1013       image->blob->eof=MagickFalse;
1014       break;
1015     }
1016     case BlobStream:
1017       break;
1018     case CustomStream:
1019       break;
1020   }
1021   return((int) image->blob->eof);
1022 }
1023 \f
1024 /*
1025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 %                                                                             %
1027 %                                                                             %
1028 %                                                                             %
1029 %   F i l e T o B l o b                                                       %
1030 %                                                                             %
1031 %                                                                             %
1032 %                                                                             %
1033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 %
1035 %  FileToBlob() returns the contents of a file as a buffer terminated with
1036 %  the '\0' character.  The length of the buffer (not including the extra
1037 %  terminating '\0' character) is returned via the 'length' parameter.  Free
1038 %  the buffer with RelinquishMagickMemory().
1039 %
1040 %  The format of the FileToBlob method is:
1041 %
1042 %      void *FileToBlob(const char *filename,const size_t extent,
1043 %        size_t *length,ExceptionInfo *exception)
1044 %
1045 %  A description of each parameter follows:
1046 %
1047 %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
1048 %      an error occurs NULL is returned.
1049 %
1050 %    o filename: the filename.
1051 %
1052 %    o extent:  The maximum length of the blob.
1053 %
1054 %    o length: On return, this reflects the actual length of the blob.
1055 %
1056 %    o exception: return any errors or warnings in this structure.
1057 %
1058 */
1059 MagickExport void *FileToBlob(const char *filename,const size_t extent,
1060   size_t *length,ExceptionInfo *exception)
1061 {
1062   int
1063     file;
1064
1065   MagickOffsetType
1066     offset;
1067
1068   register size_t
1069     i;
1070
1071   ssize_t
1072     count;
1073
1074   unsigned char
1075     *blob;
1076
1077   void
1078     *map;
1079
1080   assert(filename != (const char *) NULL);
1081   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1082   assert(exception != (ExceptionInfo *) NULL);
1083   *length=0;
1084   file=fileno(stdin);
1085   if (LocaleCompare(filename,"-") != 0)
1086     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1087   if (file == -1)
1088     {
1089       ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1090       return(NULL);
1091     }
1092   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1093   count=0;
1094   if ((file == fileno(stdin)) || (offset < 0) ||
1095       (offset != (MagickOffsetType) ((ssize_t) offset)))
1096     {
1097       size_t
1098         quantum;
1099
1100       struct stat
1101         file_stats;
1102
1103       /*
1104         Stream is not seekable.
1105       */
1106       offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1107       quantum=(size_t) MagickMaxBufferExtent;
1108       if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1109         quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1110       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1111       for (i=0; blob != (unsigned char *) NULL; i+=count)
1112       {
1113         count=read(file,blob+i,quantum);
1114         if (count <= 0)
1115           {
1116             count=0;
1117             if (errno != EINTR)
1118               break;
1119           }
1120         if (~((size_t) i) < (quantum+1))
1121           {
1122             blob=(unsigned char *) RelinquishMagickMemory(blob);
1123             break;
1124           }
1125         blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1126           sizeof(*blob));
1127         if ((size_t) (i+count) >= extent)
1128           break;
1129       }
1130       if (LocaleCompare(filename,"-") != 0)
1131         file=close(file);
1132       if (blob == (unsigned char *) NULL)
1133         {
1134           (void) ThrowMagickException(exception,GetMagickModule(),
1135             ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1136           return(NULL);
1137         }
1138       if (file == -1)
1139         {
1140           blob=(unsigned char *) RelinquishMagickMemory(blob);
1141           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1142           return(NULL);
1143         }
1144       *length=(size_t) MagickMin(i+count,extent);
1145       blob[*length]='\0';
1146       return(blob);
1147     }
1148   *length=(size_t) MagickMin(offset,(MagickOffsetType)
1149     MagickMin(extent,SSIZE_MAX));
1150   blob=(unsigned char *) NULL;
1151   if (~(*length) >= (MagickPathExtent-1))
1152     blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1153       sizeof(*blob));
1154   if (blob == (unsigned char *) NULL)
1155     {
1156       file=close(file);
1157       (void) ThrowMagickException(exception,GetMagickModule(),
1158         ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1159       return(NULL);
1160     }
1161   map=MapBlob(file,ReadMode,0,*length);
1162   if (map != (unsigned char *) NULL)
1163     {
1164       (void) memcpy(blob,map,*length);
1165       (void) UnmapBlob(map,*length);
1166     }
1167   else
1168     {
1169       (void) lseek(file,0,SEEK_SET);
1170       for (i=0; i < *length; i+=count)
1171       {
1172         count=read(file,blob+i,(size_t) MagickMin(*length-i,SSIZE_MAX));
1173         if (count <= 0)
1174           {
1175             count=0;
1176             if (errno != EINTR)
1177               break;
1178           }
1179       }
1180       if (i < *length)
1181         {
1182           file=close(file)-1;
1183           blob=(unsigned char *) RelinquishMagickMemory(blob);
1184           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1185           return(NULL);
1186         }
1187     }
1188   blob[*length]='\0';
1189   if (LocaleCompare(filename,"-") != 0)
1190     file=close(file);
1191   if (file == -1)
1192     {
1193       blob=(unsigned char *) RelinquishMagickMemory(blob);
1194       ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1195     }
1196   return(blob);
1197 }
1198 \f
1199 /*
1200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201 %                                                                             %
1202 %                                                                             %
1203 %                                                                             %
1204 %   F i l e T o I m a g e                                                     %
1205 %                                                                             %
1206 %                                                                             %
1207 %                                                                             %
1208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209 %
1210 %  FileToImage() write the contents of a file to an image.
1211 %
1212 %  The format of the FileToImage method is:
1213 %
1214 %      MagickBooleanType FileToImage(Image *,const char *filename)
1215 %
1216 %  A description of each parameter follows:
1217 %
1218 %    o image: the image.
1219 %
1220 %    o filename: the filename.
1221 %
1222 */
1223
1224 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1225   const void *data)
1226 {
1227   MagickSizeType
1228     extent;
1229
1230   register unsigned char
1231     *q;
1232
1233   assert(image->blob != (BlobInfo *) NULL);
1234   assert(image->blob->type != UndefinedStream);
1235   assert(data != NULL);
1236   if (image->blob->type != BlobStream)
1237     return(WriteBlob(image,length,(const unsigned char *) data));
1238   extent=(MagickSizeType) (image->blob->offset+(MagickOffsetType) length);
1239   if (extent >= image->blob->extent)
1240     {
1241       extent=image->blob->extent+image->blob->quantum+length;
1242       image->blob->quantum<<=1;
1243       if (SetBlobExtent(image,extent) == MagickFalse)
1244         return(0);
1245     }
1246   q=image->blob->data+image->blob->offset;
1247   (void) memcpy(q,data,length);
1248   image->blob->offset+=length;
1249   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
1250     image->blob->length=(size_t) image->blob->offset;
1251   return((ssize_t) length);
1252 }
1253
1254 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1255   ExceptionInfo *exception)
1256 {
1257   int
1258     file;
1259
1260   size_t
1261     length,
1262     quantum;
1263
1264   ssize_t
1265     count;
1266
1267   struct stat
1268     file_stats;
1269
1270   unsigned char
1271     *blob;
1272
1273   assert(image != (const Image *) NULL);
1274   assert(image->signature == MagickCoreSignature);
1275   assert(filename != (const char *) NULL);
1276   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1277   file=fileno(stdin);
1278   if (LocaleCompare(filename,"-") != 0)
1279     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1280   if (file == -1)
1281     {
1282       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1283       return(MagickFalse);
1284     }
1285   quantum=(size_t) MagickMaxBufferExtent;
1286   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1287     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1288   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1289   if (blob == (unsigned char *) NULL)
1290     {
1291       file=close(file);
1292       ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1293         filename);
1294       return(MagickFalse);
1295     }
1296   for ( ; ; )
1297   {
1298     count=read(file,blob,quantum);
1299     if (count <= 0)
1300       {
1301         count=0;
1302         if (errno != EINTR)
1303           break;
1304       }
1305     length=(size_t) count;
1306     count=WriteBlobStream(image,length,blob);
1307     if (count != (ssize_t) length)
1308       {
1309         ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1310         break;
1311       }
1312   }
1313   file=close(file);
1314   if (file == -1)
1315     ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1316   blob=(unsigned char *) RelinquishMagickMemory(blob);
1317   return(MagickTrue);
1318 }
1319 \f
1320 /*
1321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1322 %                                                                             %
1323 %                                                                             %
1324 %                                                                             %
1325 +   G e t B l o b E r r o r                                                   %
1326 %                                                                             %
1327 %                                                                             %
1328 %                                                                             %
1329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1330 %
1331 %  GetBlobError() returns MagickTrue if the blob associated with the specified
1332 %  image encountered an error.
1333 %
1334 %  The format of the GetBlobError method is:
1335 %
1336 %       MagickBooleanType GetBlobError(const Image *image)
1337 %
1338 %  A description of each parameter follows:
1339 %
1340 %    o image: the image.
1341 %
1342 */
1343 MagickExport MagickBooleanType GetBlobError(const Image *image)
1344 {
1345   assert(image != (const Image *) NULL);
1346   assert(image->signature == MagickCoreSignature);
1347   if (image->debug != MagickFalse)
1348     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1349   return(image->blob->status);
1350 }
1351 \f
1352 /*
1353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1354 %                                                                             %
1355 %                                                                             %
1356 %                                                                             %
1357 +   G e t B l o b F i l e H a n d l e                                         %
1358 %                                                                             %
1359 %                                                                             %
1360 %                                                                             %
1361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1362 %
1363 %  GetBlobFileHandle() returns the file handle associated with the image blob.
1364 %
1365 %  The format of the GetBlobFile method is:
1366 %
1367 %      FILE *GetBlobFileHandle(const Image *image)
1368 %
1369 %  A description of each parameter follows:
1370 %
1371 %    o image: the image.
1372 %
1373 */
1374 MagickExport FILE *GetBlobFileHandle(const Image *image)
1375 {
1376   assert(image != (const Image *) NULL);
1377   assert(image->signature == MagickCoreSignature);
1378   return(image->blob->file_info.file);
1379 }
1380 \f
1381 /*
1382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1383 %                                                                             %
1384 %                                                                             %
1385 %                                                                             %
1386 +   G e t B l o b I n f o                                                     %
1387 %                                                                             %
1388 %                                                                             %
1389 %                                                                             %
1390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1391 %
1392 %  GetBlobInfo() initializes the BlobInfo structure.
1393 %
1394 %  The format of the GetBlobInfo method is:
1395 %
1396 %      void GetBlobInfo(BlobInfo *blob_info)
1397 %
1398 %  A description of each parameter follows:
1399 %
1400 %    o blob_info: Specifies a pointer to a BlobInfo structure.
1401 %
1402 */
1403 MagickExport void GetBlobInfo(BlobInfo *blob_info)
1404 {
1405   assert(blob_info != (BlobInfo *) NULL);
1406   (void) ResetMagickMemory(blob_info,0,sizeof(*blob_info));
1407   blob_info->type=UndefinedStream;
1408   blob_info->quantum=(size_t) MagickMaxBlobExtent;
1409   blob_info->properties.st_mtime=time((time_t *) NULL);
1410   blob_info->properties.st_ctime=time((time_t *) NULL);
1411   blob_info->debug=IsEventLogging();
1412   blob_info->reference_count=1;
1413   blob_info->semaphore=AcquireSemaphoreInfo();
1414   blob_info->signature=MagickCoreSignature;
1415 }
1416 \f
1417 /*
1418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1419 %                                                                             %
1420 %                                                                             %
1421 %                                                                             %
1422 %  G e t B l o b P r o p e r t i e s                                          %
1423 %                                                                             %
1424 %                                                                             %
1425 %                                                                             %
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1427 %
1428 %  GetBlobProperties() returns information about an image blob.
1429 %
1430 %  The format of the GetBlobProperties method is:
1431 %
1432 %      const struct stat *GetBlobProperties(const Image *image)
1433 %
1434 %  A description of each parameter follows:
1435 %
1436 %    o image: the image.
1437 %
1438 */
1439 MagickExport const struct stat *GetBlobProperties(const Image *image)
1440 {
1441   assert(image != (Image *) NULL);
1442   assert(image->signature == MagickCoreSignature);
1443   if (image->debug != MagickFalse)
1444     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1445   return(&image->blob->properties);
1446 }
1447 \f
1448 /*
1449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1450 %                                                                             %
1451 %                                                                             %
1452 %                                                                             %
1453 +  G e t B l o b S i z e                                                      %
1454 %                                                                             %
1455 %                                                                             %
1456 %                                                                             %
1457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1458 %
1459 %  GetBlobSize() returns the current length of the image file or blob; zero is
1460 %  returned if the size cannot be determined.
1461 %
1462 %  The format of the GetBlobSize method is:
1463 %
1464 %      MagickSizeType GetBlobSize(const Image *image)
1465 %
1466 %  A description of each parameter follows:
1467 %
1468 %    o image: the image.
1469 %
1470 */
1471 MagickExport MagickSizeType GetBlobSize(const Image *image)
1472 {
1473   MagickSizeType
1474     extent;
1475
1476   assert(image != (Image *) NULL);
1477   assert(image->signature == MagickCoreSignature);
1478   if (image->debug != MagickFalse)
1479     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1480   assert(image->blob != (BlobInfo *) NULL);
1481   extent=0;
1482   switch (image->blob->type)
1483   {
1484     case UndefinedStream:
1485     case StandardStream:
1486     {
1487       extent=image->blob->size;
1488       break;
1489     }
1490     case FileStream:
1491     {
1492       if (fstat(fileno(image->blob->file_info.file),&image->blob->properties) == 0)
1493         extent=(MagickSizeType) image->blob->properties.st_size;
1494       break;
1495     }
1496     case PipeStream:
1497     {
1498       extent=image->blob->size;
1499       break;
1500     }
1501     case ZipStream:
1502     case BZipStream:
1503     {
1504       MagickBooleanType
1505         status;
1506
1507       status=GetPathAttributes(image->filename,&image->blob->properties);
1508       if (status != MagickFalse)
1509         extent=(MagickSizeType) image->blob->properties.st_size;
1510       break;
1511     }
1512     case FifoStream:
1513       break;
1514     case BlobStream:
1515     {
1516       extent=(MagickSizeType) image->blob->length;
1517       break;
1518     }
1519     case CustomStream:
1520       break;
1521   }
1522   return(extent);
1523 }
1524 \f
1525 /*
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 %                                                                             %
1528 %                                                                             %
1529 %                                                                             %
1530 +   G e t B l o b S t r e a m D a t a                                         %
1531 %                                                                             %
1532 %                                                                             %
1533 %                                                                             %
1534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1535 %
1536 %  GetBlobStreamData() returns the stream data for the image.
1537 %
1538 %  The format of the GetBlobStreamData method is:
1539 %
1540 %      void *GetBlobStreamData(const Image *image)
1541 %
1542 %  A description of each parameter follows:
1543 %
1544 %    o image: the image.
1545 %
1546 */
1547 MagickExport void *GetBlobStreamData(const Image *image)
1548 {
1549   assert(image != (const Image *) NULL);
1550   assert(image->signature == MagickCoreSignature);
1551   return(image->blob->data);
1552 }
1553 \f
1554 /*
1555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556 %                                                                             %
1557 %                                                                             %
1558 %                                                                             %
1559 +   G e t B l o b S t r e a m H a n d l e r                                   %
1560 %                                                                             %
1561 %                                                                             %
1562 %                                                                             %
1563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1564 %
1565 %  GetBlobStreamHandler() returns the stream handler for the image.
1566 %
1567 %  The format of the GetBlobStreamHandler method is:
1568 %
1569 %      StreamHandler GetBlobStreamHandler(const Image *image)
1570 %
1571 %  A description of each parameter follows:
1572 %
1573 %    o image: the image.
1574 %
1575 */
1576 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1577 {
1578   assert(image != (const Image *) NULL);
1579   assert(image->signature == MagickCoreSignature);
1580   if (image->debug != MagickFalse)
1581     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1582   return(image->blob->stream);
1583 }
1584 \f
1585 /*
1586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1587 %                                                                             %
1588 %                                                                             %
1589 %                                                                             %
1590 %   I m a g e T o B l o b                                                     %
1591 %                                                                             %
1592 %                                                                             %
1593 %                                                                             %
1594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1595 %
1596 %  ImageToBlob() implements direct to memory image formats.  It returns the
1597 %  image as a formatted blob and its length.  The magick member of the Image
1598 %  structure determines the format of the returned blob (GIF, JPEG, PNG,
1599 %  etc.).  This method is the equivalent of WriteImage(), but writes the
1600 %  formatted "file" to a memory buffer rather than to an actual file.
1601 %
1602 %  The format of the ImageToBlob method is:
1603 %
1604 %      void *ImageToBlob(const ImageInfo *image_info,Image *image,
1605 %        size_t *length,ExceptionInfo *exception)
1606 %
1607 %  A description of each parameter follows:
1608 %
1609 %    o image_info: the image info.
1610 %
1611 %    o image: the image.
1612 %
1613 %    o length: return the actual length of the blob.
1614 %
1615 %    o exception: return any errors or warnings in this structure.
1616 %
1617 */
1618 MagickExport void *ImageToBlob(const ImageInfo *image_info,
1619   Image *image,size_t *length,ExceptionInfo *exception)
1620 {
1621   const MagickInfo
1622     *magick_info;
1623
1624   ImageInfo
1625     *blob_info;
1626
1627   MagickBooleanType
1628     status;
1629
1630   void
1631     *blob;
1632
1633   assert(image_info != (const ImageInfo *) NULL);
1634   assert(image_info->signature == MagickCoreSignature);
1635   if (image_info->debug != MagickFalse)
1636     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1637       image_info->filename);
1638   assert(image != (Image *) NULL);
1639   assert(image->signature == MagickCoreSignature);
1640   assert(exception != (ExceptionInfo *) NULL);
1641   *length=0;
1642   blob=(unsigned char *) NULL;
1643   blob_info=CloneImageInfo(image_info);
1644   blob_info->adjoin=MagickFalse;
1645   (void) SetImageInfo(blob_info,1,exception);
1646   if (*blob_info->magick != '\0')
1647     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1648   magick_info=GetMagickInfo(image->magick,exception);
1649   if (magick_info == (const MagickInfo *) NULL)
1650     {
1651       (void) ThrowMagickException(exception,GetMagickModule(),
1652         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
1653         image->magick);
1654       blob_info=DestroyImageInfo(blob_info);
1655       return(blob);
1656     }
1657   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
1658   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1659     {
1660       /*
1661         Native blob support for this image format.
1662       */
1663       blob_info->length=0;
1664       blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
1665         sizeof(unsigned char));
1666       if (blob_info->blob == NULL)
1667         (void) ThrowMagickException(exception,GetMagickModule(),
1668           ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
1669       else
1670         {
1671           (void) CloseBlob(image);
1672           image->blob->exempt=MagickTrue;
1673           *image->filename='\0';
1674           status=WriteImage(blob_info,image,exception);
1675           *length=image->blob->length;
1676           blob=DetachBlob(image->blob);
1677           if (status == MagickFalse)
1678             blob=RelinquishMagickMemory(blob);
1679           else
1680             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
1681         }
1682     }
1683   else
1684     {
1685       char
1686         unique[MagickPathExtent];
1687
1688       int
1689         file;
1690
1691       /*
1692         Write file to disk in blob image format.
1693       */
1694       file=AcquireUniqueFileResource(unique);
1695       if (file == -1)
1696         {
1697           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1698             image_info->filename);
1699         }
1700       else
1701         {
1702           blob_info->file=fdopen(file,"wb");
1703           if (blob_info->file != (FILE *) NULL)
1704             {
1705               (void) FormatLocaleString(image->filename,MagickPathExtent,
1706                 "%s:%s",image->magick,unique);
1707               status=WriteImage(blob_info,image,exception);
1708               (void) CloseBlob(image);
1709               (void) fclose(blob_info->file);
1710               if (status != MagickFalse)
1711                 blob=FileToBlob(unique,~0UL,length,exception);
1712             }
1713           (void) RelinquishUniqueFileResource(unique);
1714         }
1715     }
1716   blob_info=DestroyImageInfo(blob_info);
1717   return(blob);
1718 }
1719 \f
1720 /*
1721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1722 %                                                                             %
1723 %                                                                             %
1724 %                                                                             %
1725 +  I m a g e T o C u s t o m S t r e a m                                      %
1726 %                                                                             %
1727 %                                                                             %
1728 %                                                                             %
1729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1730 %
1731 %  ImageToCustomStream() is the equivalent of WriteImage(), but writes the
1732 %  formatted "file" to the custom stream rather than to an actual file.
1733 %
1734 %  The format of the ImageToCustomStream method is:
1735 %
1736 %      void ImageToCustomStream(const ImageInfo *image_info,Image *image,
1737 %        ExceptionInfo *exception)
1738 %
1739 %  A description of each parameter follows:
1740 %
1741 %    o image_info: the image info.
1742 %
1743 %    o image: the image.
1744 %
1745 %    o exception: return any errors or warnings in this structure.
1746 %
1747 */
1748 MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
1749   ExceptionInfo *exception)
1750 {
1751   const MagickInfo
1752     *magick_info;
1753
1754   ImageInfo
1755     *blob_info;
1756
1757   MagickBooleanType
1758     status;
1759
1760   assert(image_info != (const ImageInfo *) NULL);
1761   assert(image_info->signature == MagickCoreSignature);
1762   if (image_info->debug != MagickFalse)
1763     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1764       image_info->filename);
1765   assert(image != (Image *) NULL);
1766   assert(image->signature == MagickCoreSignature);
1767   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
1768   assert(image_info->custom_stream->signature == MagickCoreSignature);
1769   assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
1770   assert(exception != (ExceptionInfo *) NULL);
1771   blob_info=CloneImageInfo(image_info);
1772   blob_info->adjoin=MagickFalse;
1773   (void) SetImageInfo(blob_info,1,exception);
1774   if (*blob_info->magick != '\0')
1775     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
1776   magick_info=GetMagickInfo(image->magick,exception);
1777   if (magick_info == (const MagickInfo *) NULL)
1778     {
1779       (void) ThrowMagickException(exception,GetMagickModule(),
1780         MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
1781         image->magick);
1782       blob_info=DestroyImageInfo(blob_info);
1783       return;
1784     }
1785   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
1786   if (GetMagickBlobSupport(magick_info) != MagickFalse)
1787     {
1788       /*
1789         Native blob support for this image format.
1790       */
1791       (void) CloseBlob(image);
1792       *image->filename='\0';
1793       (void) WriteImage(blob_info,image,exception);
1794       (void) CloseBlob(image);
1795     }
1796   else
1797     {
1798       char
1799         unique[MagickPathExtent];
1800
1801       int
1802         file;
1803
1804       unsigned char
1805         *blob;
1806
1807       /*
1808         Write file to disk in blob image format.
1809       */
1810       blob_info->custom_stream=(CustomStreamInfo *) NULL;
1811       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
1812         sizeof(*blob));
1813       if (blob == (unsigned char *) NULL)
1814         {
1815           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1816             image_info->filename);
1817           blob_info=DestroyImageInfo(blob_info);
1818           return;
1819         }
1820       file=AcquireUniqueFileResource(unique);
1821       if (file == -1)
1822         {
1823           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1824             image_info->filename);
1825           blob=(unsigned char *) RelinquishMagickMemory(blob);
1826           blob_info=DestroyImageInfo(blob_info);
1827           return;
1828         }
1829       blob_info->file=fdopen(file,"wb+");
1830       if (blob_info->file != (FILE *) NULL)
1831         {
1832           ssize_t
1833             count;
1834
1835           (void) FormatLocaleString(image->filename,MagickPathExtent,
1836             "%s:%s",image->magick,unique);
1837           status=WriteImage(blob_info,image,exception);
1838           (void) CloseBlob(image);
1839           if (status != MagickFalse)
1840             {
1841               (void) fseek(blob_info->file,0,SEEK_SET);
1842               count=(ssize_t) MagickMaxBufferExtent;
1843               while (count == (ssize_t) MagickMaxBufferExtent)
1844               {
1845                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
1846                   blob_info->file);
1847                 image_info->custom_stream->writer(blob,count,
1848                   image_info->custom_stream->data);
1849               }
1850             }
1851           (void) fclose(blob_info->file);
1852         }
1853       blob=(unsigned char *) RelinquishMagickMemory(blob);
1854       (void) RelinquishUniqueFileResource(unique);
1855     }
1856   blob_info=DestroyImageInfo(blob_info);
1857 }
1858 \f
1859 /*
1860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1861 %                                                                             %
1862 %                                                                             %
1863 %                                                                             %
1864 %   I m a g e T o F i l e                                                     %
1865 %                                                                             %
1866 %                                                                             %
1867 %                                                                             %
1868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1869 %
1870 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
1871 %  occurs otherwise MagickTrue.
1872 %
1873 %  The format of the ImageToFile method is:
1874 %
1875 %       MagickBooleanType ImageToFile(Image *image,char *filename,
1876 %         ExceptionInfo *exception)
1877 %
1878 %  A description of each parameter follows:
1879 %
1880 %    o image: the image.
1881 %
1882 %    o filename: Write the image to this file.
1883 %
1884 %    o exception: return any errors or warnings in this structure.
1885 %
1886 */
1887 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1888   ExceptionInfo *exception)
1889 {
1890   int
1891     file;
1892
1893   register const unsigned char
1894     *p;
1895
1896   register size_t
1897     i;
1898
1899   size_t
1900     length,
1901     quantum;
1902
1903   ssize_t
1904     count;
1905
1906   struct stat
1907     file_stats;
1908
1909   unsigned char
1910     *buffer;
1911
1912   assert(image != (Image *) NULL);
1913   assert(image->signature == MagickCoreSignature);
1914   assert(image->blob != (BlobInfo *) NULL);
1915   assert(image->blob->type != UndefinedStream);
1916   if (image->debug != MagickFalse)
1917     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1918   assert(filename != (const char *) NULL);
1919   if (*filename == '\0')
1920     file=AcquireUniqueFileResource(filename);
1921   else
1922     if (LocaleCompare(filename,"-") == 0)
1923       file=fileno(stdout);
1924     else
1925       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1926   if (file == -1)
1927     {
1928       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1929       return(MagickFalse);
1930     }
1931   quantum=(size_t) MagickMaxBufferExtent;
1932   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1933     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1934   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1935   if (buffer == (unsigned char *) NULL)
1936     {
1937       file=close(file)-1;
1938       (void) ThrowMagickException(exception,GetMagickModule(),
1939         ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1940       return(MagickFalse);
1941     }
1942   length=0;
1943   p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1944   for (i=0; count > 0; )
1945   {
1946     length=(size_t) count;
1947     for (i=0; i < length; i+=count)
1948     {
1949       count=write(file,p+i,(size_t) (length-i));
1950       if (count <= 0)
1951         {
1952           count=0;
1953           if (errno != EINTR)
1954             break;
1955         }
1956     }
1957     if (i < length)
1958       break;
1959     p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1960   }
1961   if (LocaleCompare(filename,"-") != 0)
1962     file=close(file);
1963   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1964   if ((file == -1) || (i < length))
1965     {
1966       if (file != -1)
1967         file=close(file);
1968       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1969       return(MagickFalse);
1970     }
1971   return(MagickTrue);
1972 }
1973 \f
1974 /*
1975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1976 %                                                                             %
1977 %                                                                             %
1978 %                                                                             %
1979 %   I m a g e s T o B l o b                                                   %
1980 %                                                                             %
1981 %                                                                             %
1982 %                                                                             %
1983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1984 %
1985 %  ImagesToBlob() implements direct to memory image formats.  It returns the
1986 %  image sequence as a blob and its length.  The magick member of the ImageInfo
1987 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
1988 %
1989 %  Note, some image formats do not permit multiple images to the same image
1990 %  stream (e.g. JPEG).  in this instance, just the first image of the
1991 %  sequence is returned as a blob.
1992 %
1993 %  The format of the ImagesToBlob method is:
1994 %
1995 %      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
1996 %        size_t *length,ExceptionInfo *exception)
1997 %
1998 %  A description of each parameter follows:
1999 %
2000 %    o image_info: the image info.
2001 %
2002 %    o images: the image list.
2003 %
2004 %    o length: return the actual length of the blob.
2005 %
2006 %    o exception: return any errors or warnings in this structure.
2007 %
2008 */
2009 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2010   size_t *length,ExceptionInfo *exception)
2011 {
2012   const MagickInfo
2013     *magick_info;
2014
2015   ImageInfo
2016     *blob_info;
2017
2018   MagickBooleanType
2019     status;
2020
2021   void
2022     *blob;
2023
2024   assert(image_info != (const ImageInfo *) NULL);
2025   assert(image_info->signature == MagickCoreSignature);
2026   if (image_info->debug != MagickFalse)
2027     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2028       image_info->filename);
2029   assert(images != (Image *) NULL);
2030   assert(images->signature == MagickCoreSignature);
2031   assert(exception != (ExceptionInfo *) NULL);
2032   *length=0;
2033   blob=(unsigned char *) NULL;
2034   blob_info=CloneImageInfo(image_info);
2035   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2036     exception);
2037   if (*blob_info->magick != '\0')
2038     (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2039   magick_info=GetMagickInfo(images->magick,exception);
2040   if (magick_info == (const MagickInfo *) NULL)
2041     {
2042       (void) ThrowMagickException(exception,GetMagickModule(),
2043         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2044         images->magick);
2045       blob_info=DestroyImageInfo(blob_info);
2046       return(blob);
2047     }
2048   if (GetMagickAdjoin(magick_info) == MagickFalse)
2049     {
2050       blob_info=DestroyImageInfo(blob_info);
2051       return(ImageToBlob(image_info,images,length,exception));
2052     }
2053   (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2054   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2055     {
2056       /*
2057         Native blob support for this images format.
2058       */
2059       blob_info->length=0;
2060       blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2061         sizeof(unsigned char));
2062       if (blob_info->blob == (void *) NULL)
2063         (void) ThrowMagickException(exception,GetMagickModule(),
2064           ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2065       else
2066         {
2067           (void) CloseBlob(images);
2068           images->blob->exempt=MagickTrue;
2069           *images->filename='\0';
2070           status=WriteImages(blob_info,images,images->filename,exception);
2071           *length=images->blob->length;
2072           blob=DetachBlob(images->blob);
2073           if (status == MagickFalse)
2074             blob=RelinquishMagickMemory(blob);
2075           else
2076             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2077         }
2078     }
2079   else
2080     {
2081       char
2082         filename[MagickPathExtent],
2083         unique[MagickPathExtent];
2084
2085       int
2086         file;
2087
2088       /*
2089         Write file to disk in blob images format.
2090       */
2091       file=AcquireUniqueFileResource(unique);
2092       if (file == -1)
2093         {
2094           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2095             image_info->filename);
2096         }
2097       else
2098         {
2099           blob_info->file=fdopen(file,"wb");
2100           if (blob_info->file != (FILE *) NULL)
2101             {
2102               (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2103                 images->magick,unique);
2104               status=WriteImages(blob_info,images,filename,exception);
2105               (void) CloseBlob(images);
2106               (void) fclose(blob_info->file);
2107               if (status != MagickFalse)
2108                 blob=FileToBlob(unique,~0UL,length,exception);
2109             }
2110           (void) RelinquishUniqueFileResource(unique);
2111         }
2112     }
2113   blob_info=DestroyImageInfo(blob_info);
2114   return(blob);
2115 }
2116 \f
2117 /*
2118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2119 %                                                                             %
2120 %                                                                             %
2121 %                                                                             %
2122 +  I m a g e s T o C u s t o m B l o b                                        %
2123 %                                                                             %
2124 %                                                                             %
2125 %                                                                             %
2126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2127 %
2128 %  ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2129 %  formatted "file" to the custom stream rather than to an actual file.
2130 %
2131 %  The format of the ImageToCustomStream method is:
2132 %
2133 %      void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2134 %        ExceptionInfo *exception)
2135 %
2136 %  A description of each parameter follows:
2137 %
2138 %    o image_info: the image info.
2139 %
2140 %    o images: the image list.
2141 %
2142 %    o exception: return any errors or warnings in this structure.
2143 %
2144 */
2145 MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2146   Image *images,ExceptionInfo *exception)
2147 {
2148   const MagickInfo
2149     *magick_info;
2150
2151   ImageInfo
2152     *blob_info;
2153
2154   MagickBooleanType
2155     status;
2156
2157   assert(image_info != (const ImageInfo *) NULL);
2158   assert(image_info->signature == MagickCoreSignature);
2159   if (image_info->debug != MagickFalse)
2160     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2161       image_info->filename);
2162   assert(images != (Image *) NULL);
2163   assert(images->signature == MagickCoreSignature);
2164   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2165   assert(image_info->custom_stream->signature == MagickCoreSignature);
2166   assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
2167   assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2168   assert(exception != (ExceptionInfo *) NULL);
2169   blob_info=CloneImageInfo(image_info);
2170   (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
2171     exception);
2172   if (*blob_info->magick != '\0')
2173     (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2174   magick_info=GetMagickInfo(images->magick,exception);
2175   if (magick_info == (const MagickInfo *) NULL)
2176     {
2177       (void) ThrowMagickException(exception,GetMagickModule(),
2178         MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2179         images->magick);
2180       blob_info=DestroyImageInfo(blob_info);
2181       return;
2182     }
2183   (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2184   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2185     {
2186       /*
2187         Native blob support for this image format.
2188       */
2189       (void) CloseBlob(images);
2190       *images->filename='\0';
2191       (void) WriteImages(blob_info,images,images->filename,exception);
2192       (void) CloseBlob(images);
2193     }
2194   else
2195     {
2196       char
2197         filename[MagickPathExtent],
2198         unique[MagickPathExtent];
2199
2200       int
2201         file;
2202
2203       unsigned char
2204         *blob;
2205
2206       /*
2207         Write file to disk in blob image format.
2208       */
2209       blob_info->custom_stream=(CustomStreamInfo *) NULL;
2210       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2211         sizeof(*blob));
2212       if (blob == (unsigned char *) NULL)
2213         {
2214           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2215             image_info->filename);
2216           blob_info=DestroyImageInfo(blob_info);
2217           return;
2218         }
2219       file=AcquireUniqueFileResource(unique);
2220       if (file == -1)
2221         {
2222           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2223             image_info->filename);
2224           blob=(unsigned char *) RelinquishMagickMemory(blob);
2225           blob_info=DestroyImageInfo(blob_info);
2226           return;
2227         }
2228       blob_info->file=fdopen(file,"wb+");
2229       if (blob_info->file != (FILE *) NULL)
2230         {
2231           ssize_t
2232             count;
2233
2234           (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2235             images->magick,unique);
2236           status=WriteImages(blob_info,images,filename,exception);
2237           (void) CloseBlob(images);
2238           if (status != MagickFalse)
2239             {
2240               (void) fseek(blob_info->file,0,SEEK_SET);
2241               count=(ssize_t) MagickMaxBufferExtent;
2242               while (count == (ssize_t) MagickMaxBufferExtent)
2243               {
2244                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2245                   blob_info->file);
2246                 image_info->custom_stream->writer(blob,count,
2247                   image_info->custom_stream->data);
2248               }
2249             }
2250           (void) fclose(blob_info->file);
2251         }
2252       blob=(unsigned char *) RelinquishMagickMemory(blob);
2253       (void) RelinquishUniqueFileResource(unique);
2254     }
2255   blob_info=DestroyImageInfo(blob_info);
2256   return;
2257 }
2258 \f
2259 /*
2260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2261 %                                                                             %
2262 %                                                                             %
2263 %                                                                             %
2264 %   I n j e c t I m a g e B l o b                                             %
2265 %                                                                             %
2266 %                                                                             %
2267 %                                                                             %
2268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2269 %
2270 %  InjectImageBlob() injects the image with a copy of itself in the specified
2271 %  format (e.g. inject JPEG into a PDF image).
2272 %
2273 %  The format of the InjectImageBlob method is:
2274 %
2275 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2276 %        Image *image,Image *inject_image,const char *format,
2277 %        ExceptionInfo *exception)
2278 %
2279 %  A description of each parameter follows:
2280 %
2281 %    o image_info: the image info..
2282 %
2283 %    o image: the image.
2284 %
2285 %    o inject_image: inject into the image stream.
2286 %
2287 %    o format: the image format.
2288 %
2289 %    o exception: return any errors or warnings in this structure.
2290 %
2291 */
2292 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2293   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2294 {
2295   char
2296     filename[MagickPathExtent];
2297
2298   FILE
2299     *unique_file;
2300
2301   Image
2302     *byte_image;
2303
2304   ImageInfo
2305     *write_info;
2306
2307   int
2308     file;
2309
2310   MagickBooleanType
2311     status;
2312
2313   register ssize_t
2314     i;
2315
2316   size_t
2317     quantum;
2318
2319   ssize_t
2320     count;
2321
2322   struct stat
2323     file_stats;
2324
2325   unsigned char
2326     *buffer;
2327
2328   /*
2329     Write inject image to a temporary file.
2330   */
2331   assert(image_info != (ImageInfo *) NULL);
2332   assert(image_info->signature == MagickCoreSignature);
2333   assert(image != (Image *) NULL);
2334   assert(image->signature == MagickCoreSignature);
2335   if (image->debug != MagickFalse)
2336     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2337   assert(inject_image != (Image *) NULL);
2338   assert(inject_image->signature == MagickCoreSignature);
2339   assert(exception != (ExceptionInfo *) NULL);
2340   unique_file=(FILE *) NULL;
2341   file=AcquireUniqueFileResource(filename);
2342   if (file != -1)
2343     unique_file=fdopen(file,"wb");
2344   if ((file == -1) || (unique_file == (FILE *) NULL))
2345     {
2346       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2347       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2348         image->filename);
2349       return(MagickFalse);
2350     }
2351   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2352   if (byte_image == (Image *) NULL)
2353     {
2354       (void) fclose(unique_file);
2355       (void) RelinquishUniqueFileResource(filename);
2356       return(MagickFalse);
2357     }
2358   (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2359     format,filename);
2360   DestroyBlob(byte_image);
2361   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2362   write_info=CloneImageInfo(image_info);
2363   SetImageInfoFile(write_info,unique_file);
2364   status=WriteImage(write_info,byte_image,exception);
2365   write_info=DestroyImageInfo(write_info);
2366   byte_image=DestroyImage(byte_image);
2367   (void) fclose(unique_file);
2368   if (status == MagickFalse)
2369     {
2370       (void) RelinquishUniqueFileResource(filename);
2371       return(MagickFalse);
2372     }
2373   /*
2374     Inject into image stream.
2375   */
2376   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2377   if (file == -1)
2378     {
2379       (void) RelinquishUniqueFileResource(filename);
2380       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2381         image_info->filename);
2382       return(MagickFalse);
2383     }
2384   quantum=(size_t) MagickMaxBufferExtent;
2385   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2386     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2387   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2388   if (buffer == (unsigned char *) NULL)
2389     {
2390       (void) RelinquishUniqueFileResource(filename);
2391       file=close(file);
2392       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2393         image->filename);
2394     }
2395   for (i=0; ; i+=count)
2396   {
2397     count=read(file,buffer,quantum);
2398     if (count <= 0)
2399       {
2400         count=0;
2401         if (errno != EINTR)
2402           break;
2403       }
2404     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2405       MagickFalse;
2406   }
2407   file=close(file);
2408   if (file == -1)
2409     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2410   (void) RelinquishUniqueFileResource(filename);
2411   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2412   return(status);
2413 }
2414 \f
2415 /*
2416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2417 %                                                                             %
2418 %                                                                             %
2419 %                                                                             %
2420 %   I s B l o b E x e m p t                                                   %
2421 %                                                                             %
2422 %                                                                             %
2423 %                                                                             %
2424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2425 %
2426 %  IsBlobExempt() returns true if the blob is exempt.
2427 %
2428 %  The format of the IsBlobExempt method is:
2429 %
2430 %       MagickBooleanType IsBlobExempt(const Image *image)
2431 %
2432 %  A description of each parameter follows:
2433 %
2434 %    o image: the image.
2435 %
2436 */
2437 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2438 {
2439   assert(image != (const Image *) NULL);
2440   assert(image->signature == MagickCoreSignature);
2441   if (image->debug != MagickFalse)
2442     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2443   return(image->blob->exempt);
2444 }
2445 \f
2446 /*
2447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2448 %                                                                             %
2449 %                                                                             %
2450 %                                                                             %
2451 %   I s B l o b S e e k a b l e                                               %
2452 %                                                                             %
2453 %                                                                             %
2454 %                                                                             %
2455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2456 %
2457 %  IsBlobSeekable() returns true if the blob is seekable.
2458 %
2459 %  The format of the IsBlobSeekable method is:
2460 %
2461 %       MagickBooleanType IsBlobSeekable(const Image *image)
2462 %
2463 %  A description of each parameter follows:
2464 %
2465 %    o image: the image.
2466 %
2467 */
2468 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2469 {
2470   MagickBooleanType
2471     seekable;
2472
2473   assert(image != (const Image *) NULL);
2474   assert(image->signature == MagickCoreSignature);
2475   if (image->debug != MagickFalse)
2476     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2477   switch (image->blob->type)
2478   {
2479     case FileStream:
2480     case BlobStream:
2481     case ZipStream:
2482     {
2483       seekable=MagickTrue;
2484       break;
2485     }
2486     case UndefinedStream:
2487     case StandardStream:
2488     case BZipStream:
2489     case FifoStream:
2490     case PipeStream:
2491     default:
2492     {
2493       seekable=MagickFalse;
2494       break;
2495     }
2496     case CustomStream:
2497     {
2498       if ((image->blob->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
2499           (image->blob->custom_stream->teller != (CustomStreamTeller) NULL))
2500         seekable=MagickTrue;
2501       else
2502         seekable=MagickFalse;
2503       break;
2504     }
2505   }
2506   return(seekable);
2507 }
2508 \f
2509 /*
2510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2511 %                                                                             %
2512 %                                                                             %
2513 %                                                                             %
2514 %   I s B l o b T e m p o r a r y                                             %
2515 %                                                                             %
2516 %                                                                             %
2517 %                                                                             %
2518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2519 %
2520 %  IsBlobTemporary() returns true if the blob is temporary.
2521 %
2522 %  The format of the IsBlobTemporary method is:
2523 %
2524 %       MagickBooleanType IsBlobTemporary(const Image *image)
2525 %
2526 %  A description of each parameter follows:
2527 %
2528 %    o image: the image.
2529 %
2530 */
2531 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2532 {
2533   assert(image != (const Image *) NULL);
2534   assert(image->signature == MagickCoreSignature);
2535   if (image->debug != MagickFalse)
2536     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2537   return(image->blob->temporary);
2538 }
2539 \f
2540 /*
2541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2542 %                                                                             %
2543 %                                                                             %
2544 %                                                                             %
2545 +  M a p B l o b                                                              %
2546 %                                                                             %
2547 %                                                                             %
2548 %                                                                             %
2549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2550 %
2551 %  MapBlob() creates a mapping from a file to a binary large object.
2552 %
2553 %  The format of the MapBlob method is:
2554 %
2555 %      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2556 %        const size_t length)
2557 %
2558 %  A description of each parameter follows:
2559 %
2560 %    o file: map this file descriptor.
2561 %
2562 %    o mode: ReadMode, WriteMode, or IOMode.
2563 %
2564 %    o offset: starting at this offset within the file.
2565 %
2566 %    o length: the length of the mapping is returned in this pointer.
2567 %
2568 */
2569 MagickExport void *MapBlob(int file,const MapMode mode,
2570   const MagickOffsetType offset,const size_t length)
2571 {
2572 #if defined(MAGICKCORE_HAVE_MMAP)
2573   int
2574     flags,
2575     protection;
2576
2577   void
2578     *map;
2579
2580   /*
2581     Map file.
2582   */
2583   flags=0;
2584   if (file == -1)
2585 #if defined(MAP_ANONYMOUS)
2586     flags|=MAP_ANONYMOUS;
2587 #else
2588     return(NULL);
2589 #endif
2590   switch (mode)
2591   {
2592     case ReadMode:
2593     default:
2594     {
2595       protection=PROT_READ;
2596       flags|=MAP_PRIVATE;
2597       break;
2598     }
2599     case WriteMode:
2600     {
2601       protection=PROT_WRITE;
2602       flags|=MAP_SHARED;
2603       break;
2604     }
2605     case IOMode:
2606     {
2607       protection=PROT_READ | PROT_WRITE;
2608       flags|=MAP_SHARED;
2609       break;
2610     }
2611   }
2612 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2613   map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2614 #else
2615   map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
2616     offset);
2617   if (map == MAP_FAILED)
2618     map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2619 #endif
2620   if (map == MAP_FAILED)
2621     return(NULL);
2622   return(map);
2623 #else
2624   (void) file;
2625   (void) mode;
2626   (void) offset;
2627   (void) length;
2628   return(NULL);
2629 #endif
2630 }
2631 \f
2632 /*
2633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634 %                                                                             %
2635 %                                                                             %
2636 %                                                                             %
2637 +  M S B O r d e r L o n g                                                    %
2638 %                                                                             %
2639 %                                                                             %
2640 %                                                                             %
2641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642 %
2643 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
2644 %  most-significant byte first.
2645 %
2646 %  The format of the MSBOrderLong method is:
2647 %
2648 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
2649 %
2650 %  A description of each parameter follows.
2651 %
2652 %   o  buffer:  Specifies a pointer to a buffer of integers.
2653 %
2654 %   o  length:  Specifies the length of the buffer.
2655 %
2656 */
2657 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2658 {
2659   int
2660     c;
2661
2662   register unsigned char
2663     *p,
2664     *q;
2665
2666   assert(buffer != (unsigned char *) NULL);
2667   q=buffer+length;
2668   while (buffer < q)
2669   {
2670     p=buffer+3;
2671     c=(int) (*p);
2672     *p=(*buffer);
2673     *buffer++=(unsigned char) c;
2674     p=buffer+1;
2675     c=(int) (*p);
2676     *p=(*buffer);
2677     *buffer++=(unsigned char) c;
2678     buffer+=2;
2679   }
2680 }
2681 \f
2682 /*
2683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2684 %                                                                             %
2685 %                                                                             %
2686 %                                                                             %
2687 +  M S B O r d e r S h o r t                                                  %
2688 %                                                                             %
2689 %                                                                             %
2690 %                                                                             %
2691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2692 %
2693 %  MSBOrderShort() converts a least-significant byte first buffer of integers
2694 %  to most-significant byte first.
2695 %
2696 %  The format of the MSBOrderShort method is:
2697 %
2698 %      void MSBOrderShort(unsigned char *p,const size_t length)
2699 %
2700 %  A description of each parameter follows.
2701 %
2702 %   o  p:  Specifies a pointer to a buffer of integers.
2703 %
2704 %   o  length:  Specifies the length of the buffer.
2705 %
2706 */
2707 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2708 {
2709   int
2710     c;
2711
2712   register unsigned char
2713     *q;
2714
2715   assert(p != (unsigned char *) NULL);
2716   q=p+length;
2717   while (p < q)
2718   {
2719     c=(int) (*p);
2720     *p=(*(p+1));
2721     p++;
2722     *p++=(unsigned char) c;
2723   }
2724 }
2725 \f
2726 /*
2727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2728 %                                                                             %
2729 %                                                                             %
2730 %                                                                             %
2731 +   O p e n B l o b                                                           %
2732 %                                                                             %
2733 %                                                                             %
2734 %                                                                             %
2735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2736 %
2737 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
2738 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
2739 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2740 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
2741 %  from a system command.
2742 %
2743 %  The format of the OpenBlob method is:
2744 %
2745 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2746 %        const BlobMode mode,ExceptionInfo *exception)
2747 %
2748 %  A description of each parameter follows:
2749 %
2750 %    o image_info: the image info.
2751 %
2752 %    o image: the image.
2753 %
2754 %    o mode: the mode for opening the file.
2755 %
2756 */
2757
2758 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2759   Image *image)
2760 {
2761   const char
2762     *option;
2763
2764   int
2765     status;
2766
2767   size_t
2768     size;
2769
2770   size=16384;
2771   option=GetImageOption(image_info,"stream:buffer-size");
2772   if (option != (const char *) NULL)
2773     size=StringToUnsignedLong(option);
2774   status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2775     _IONBF : _IOFBF,size);
2776   return(status == 0 ? MagickTrue : MagickFalse);
2777 }
2778
2779 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2780   Image *image,const BlobMode mode,ExceptionInfo *exception)
2781 {
2782   char
2783     extension[MagickPathExtent],
2784     filename[MagickPathExtent];
2785
2786   const char
2787     *type;
2788
2789   MagickBooleanType
2790     status;
2791
2792   PolicyRights
2793     rights;
2794
2795   assert(image_info != (ImageInfo *) NULL);
2796   assert(image_info->signature == MagickCoreSignature);
2797   if (image_info->debug != MagickFalse)
2798     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2799       image_info->filename);
2800   assert(image != (Image *) NULL);
2801   assert(image->signature == MagickCoreSignature);
2802   if (image_info->blob != (void *) NULL)
2803     {
2804       if (image_info->stream != (StreamHandler) NULL)
2805         image->blob->stream=(StreamHandler) image_info->stream;
2806       AttachBlob(image->blob,image_info->blob,image_info->length);
2807       return(MagickTrue);
2808     }
2809   if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
2810       (*image->filename == '\0'))
2811     {
2812       image->blob->type=CustomStream;
2813       image->blob->custom_stream=image_info->custom_stream;
2814       return(MagickTrue);
2815     }
2816   (void) DetachBlob(image->blob);
2817   switch (mode)
2818   {
2819     default: type="r"; break;
2820     case ReadBlobMode: type="r"; break;
2821     case ReadBinaryBlobMode: type="rb"; break;
2822     case WriteBlobMode: type="w"; break;
2823     case WriteBinaryBlobMode: type="w+b"; break;
2824     case AppendBlobMode: type="a"; break;
2825     case AppendBinaryBlobMode: type="a+b"; break;
2826   }
2827   if (*type != 'r')
2828     image->blob->synchronize=image_info->synchronize;
2829   if (image_info->stream != (StreamHandler) NULL)
2830     {
2831       image->blob->stream=image_info->stream;
2832       if (*type == 'w')
2833         {
2834           image->blob->type=FifoStream;
2835           return(MagickTrue);
2836         }
2837     }
2838   /*
2839     Open image file.
2840   */
2841   *filename='\0';
2842   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2843   rights=ReadPolicyRights;
2844   if (*type == 'w')
2845     rights=WritePolicyRights;
2846   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2847     {
2848       errno=EPERM;
2849       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2850         "NotAuthorized","`%s'",filename);
2851       return(MagickFalse);
2852     }
2853   if ((LocaleCompare(filename,"-") == 0) ||
2854       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2855     {
2856       image->blob->file_info.file=(*type == 'r') ? stdin : stdout;
2857 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2858       if (strchr(type,'b') != (char *) NULL)
2859         setmode(fileno(image->blob->file_info.file),_O_BINARY);
2860 #endif
2861       image->blob->type=StandardStream;
2862       image->blob->exempt=MagickTrue;
2863       return(SetStreamBuffering(image_info,image));
2864     }
2865   if (LocaleNCompare(filename,"fd:",3) == 0)
2866     {
2867       char
2868         fileMode[MagickPathExtent];
2869
2870       *fileMode =(*type);
2871       fileMode[1]='\0';
2872       image->blob->file_info.file=fdopen(StringToLong(filename+3),fileMode);
2873 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2874       if (strchr(type,'b') != (char *) NULL)
2875         setmode(fileno(image->blob->file_info.file),_O_BINARY);
2876 #endif
2877       image->blob->type=StandardStream;
2878       image->blob->exempt=MagickTrue;
2879       return(SetStreamBuffering(image_info,image));
2880     }
2881 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
2882   if (*filename == '|')
2883     {
2884       char
2885         fileMode[MagickPathExtent],
2886         *sanitize_command;
2887
2888       /*
2889         Pipe image to or from a system command.
2890       */
2891 #if defined(SIGPIPE)
2892       if (*type == 'w')
2893         (void) signal(SIGPIPE,SIG_IGN);
2894 #endif
2895       *fileMode =(*type);
2896       fileMode[1]='\0';
2897       sanitize_command=SanitizeString(filename+1);
2898       image->blob->file_info.file=(FILE *) popen_utf8(sanitize_command,
2899         fileMode);
2900       sanitize_command=DestroyString(sanitize_command);
2901       if (image->blob->file_info.file == (FILE *) NULL)
2902         {
2903           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2904           return(MagickFalse);
2905         }
2906       image->blob->type=PipeStream;
2907       image->blob->exempt=MagickTrue;
2908       return(SetStreamBuffering(image_info,image));
2909     }
2910 #endif
2911   status=GetPathAttributes(filename,&image->blob->properties);
2912 #if defined(S_ISFIFO)
2913   if ((status != MagickFalse) && S_ISFIFO(image->blob->properties.st_mode))
2914     {
2915       image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2916       if (image->blob->file_info.file == (FILE *) NULL)
2917         {
2918           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2919           return(MagickFalse);
2920         }
2921       image->blob->type=FileStream;
2922       image->blob->exempt=MagickTrue;
2923       return(SetStreamBuffering(image_info,image));
2924     }
2925 #endif
2926   GetPathComponent(image->filename,ExtensionPath,extension);
2927   if (*type == 'w')
2928     {
2929       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2930       if ((image_info->adjoin == MagickFalse) ||
2931           (strchr(filename,'%') != (char *) NULL))
2932         {
2933           /*
2934             Form filename for multi-part images.
2935           */
2936           (void) InterpretImageFilename(image_info,image,image->filename,(int)
2937             image->scene,filename,exception);
2938           if ((LocaleCompare(filename,image->filename) == 0) &&
2939               ((GetPreviousImageInList(image) != (Image *) NULL) ||
2940                (GetNextImageInList(image) != (Image *) NULL)))
2941             {
2942               char
2943                 path[MagickPathExtent];
2944
2945               GetPathComponent(image->filename,RootPath,path);
2946               if (*extension == '\0')
2947                 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
2948                   path,(double) image->scene);
2949               else
2950                 (void) FormatLocaleString(filename,MagickPathExtent,
2951                   "%s-%.20g.%s",path,(double) image->scene,extension);
2952             }
2953           (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2954 #if defined(macintosh)
2955           SetApplicationType(filename,image_info->magick,'8BIM');
2956 #endif
2957         }
2958     }
2959   if (image_info->file != (FILE *) NULL)
2960     {
2961       image->blob->file_info.file=image_info->file;
2962       image->blob->type=FileStream;
2963       image->blob->exempt=MagickTrue;
2964     }
2965   else
2966     if (*type == 'r')
2967       {
2968         image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
2969         if (image->blob->file_info.file != (FILE *) NULL)
2970           {
2971             size_t
2972               count;
2973
2974             unsigned char
2975               magick[3];
2976
2977             image->blob->type=FileStream;
2978             (void) SetStreamBuffering(image_info,image);
2979             (void) ResetMagickMemory(magick,0,sizeof(magick));
2980             count=fread(magick,1,sizeof(magick),image->blob->file_info.file);
2981             (void) fseek(image->blob->file_info.file,-((off_t) count),SEEK_CUR);
2982 #if defined(MAGICKCORE_POSIX_SUPPORT)
2983             (void) fflush(image->blob->file_info.file);
2984 #endif
2985             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2986                "  read %.20g magic header bytes",(double) count);
2987 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2988             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2989                 ((int) magick[2] == 0x08))
2990               {
2991                 if (image->blob->file_info.file != (FILE *) NULL)
2992                   (void) fclose(image->blob->file_info.file);
2993                 image->blob->file_info.file=(FILE *) NULL;
2994                 image->blob->file_info.gzfile=gzopen(filename,type);
2995                 if (image->blob->file_info.gzfile != (gzFile) NULL)
2996                   image->blob->type=ZipStream;
2997                }
2998 #endif
2999 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3000             if (strncmp((char *) magick,"BZh",3) == 0)
3001               {
3002                 if (image->blob->file_info.file != (FILE *) NULL)
3003                   (void) fclose(image->blob->file_info.file);
3004                 image->blob->file_info.file=(FILE *) NULL;
3005                 image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
3006                 if (image->blob->file_info.bzfile != (BZFILE *) NULL)
3007                   image->blob->type=BZipStream;
3008               }
3009 #endif
3010             if (image->blob->type == FileStream)
3011               {
3012                 const MagickInfo
3013                   *magick_info;
3014
3015                 ExceptionInfo
3016                   *sans_exception;
3017
3018                 size_t
3019                   length;
3020
3021                 sans_exception=AcquireExceptionInfo();
3022                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3023                 sans_exception=DestroyExceptionInfo(sans_exception);
3024                 length=(size_t) image->blob->properties.st_size;
3025                 if ((magick_info != (const MagickInfo *) NULL) &&
3026                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3027                     (length > MagickMaxBufferExtent) &&
3028                     (AcquireMagickResource(MapResource,length) != MagickFalse))
3029                   {
3030                     void
3031                       *blob;
3032
3033                     blob=MapBlob(fileno(image->blob->file_info.file),ReadMode,0,
3034                       length);
3035                     if (blob == (void *) NULL)
3036                       RelinquishMagickResource(MapResource,length);
3037                     else
3038                       {
3039                         /*
3040                           Format supports blobs-- use memory-mapped I/O.
3041                         */
3042                         if (image_info->file != (FILE *) NULL)
3043                           image->blob->exempt=MagickFalse;
3044                         else
3045                           {
3046                             (void) fclose(image->blob->file_info.file);
3047                             image->blob->file_info.file=(FILE *) NULL;
3048                           }
3049                         AttachBlob(image->blob,blob,length);
3050                         image->blob->mapped=MagickTrue;
3051                       }
3052                   }
3053               }
3054           }
3055         }
3056       else
3057 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3058         if ((LocaleCompare(extension,"Z") == 0) ||
3059             (LocaleCompare(extension,"gz") == 0) ||
3060             (LocaleCompare(extension,"wmz") == 0) ||
3061             (LocaleCompare(extension,"svgz") == 0))
3062           {
3063             if (mode == WriteBinaryBlobMode)
3064               type="wb";
3065             image->blob->file_info.gzfile=gzopen(filename,type);
3066             if (image->blob->file_info.gzfile != (gzFile) NULL)
3067               image->blob->type=ZipStream;
3068           }
3069         else
3070 #endif
3071 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3072           if (LocaleCompare(extension,"bz2") == 0)
3073             {
3074               image->blob->file_info.bzfile=BZ2_bzopen(filename,type);
3075               if (image->blob->file_info.bzfile != (BZFILE *) NULL)
3076                 image->blob->type=BZipStream;
3077             }
3078           else
3079 #endif
3080             {
3081               image->blob->file_info.file=(FILE *) fopen_utf8(filename,type);
3082               if (image->blob->file_info.file != (FILE *) NULL)
3083                 {
3084                   image->blob->type=FileStream;
3085                   (void) SetStreamBuffering(image_info,image);
3086                 }
3087        }
3088   image->blob->status=MagickFalse;
3089   if (image->blob->type != UndefinedStream)
3090     image->blob->size=GetBlobSize(image);
3091   else
3092     {
3093       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3094       return(MagickFalse);
3095     }
3096   return(MagickTrue);
3097 }
3098 \f
3099 /*
3100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3101 %                                                                             %
3102 %                                                                             %
3103 %                                                                             %
3104 +   P i n g B l o b                                                           %
3105 %                                                                             %
3106 %                                                                             %
3107 %                                                                             %
3108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3109 %
3110 %  PingBlob() returns all the attributes of an image or image sequence except
3111 %  for the pixels.  It is much faster and consumes far less memory than
3112 %  BlobToImage().  On failure, a NULL image is returned and exception
3113 %  describes the reason for the failure.
3114 %
3115 %  The format of the PingBlob method is:
3116 %
3117 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
3118 %        const size_t length,ExceptionInfo *exception)
3119 %
3120 %  A description of each parameter follows:
3121 %
3122 %    o image_info: the image info.
3123 %
3124 %    o blob: the address of a character stream in one of the image formats
3125 %      understood by ImageMagick.
3126 %
3127 %    o length: This size_t integer reflects the length in bytes of the blob.
3128 %
3129 %    o exception: return any errors or warnings in this structure.
3130 %
3131 */
3132
3133 #if defined(__cplusplus) || defined(c_plusplus)
3134 extern "C" {
3135 #endif
3136
3137 static size_t PingStream(const Image *magick_unused(image),
3138   const void *magick_unused(pixels),const size_t columns)
3139 {
3140   magick_unreferenced(image);
3141   magick_unreferenced(pixels);
3142   return(columns);
3143 }
3144
3145 #if defined(__cplusplus) || defined(c_plusplus)
3146 }
3147 #endif
3148
3149 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3150   const size_t length,ExceptionInfo *exception)
3151 {
3152   Image
3153     *image;
3154
3155   ImageInfo
3156     *ping_info;
3157
3158   assert(image_info != (ImageInfo *) NULL);
3159   assert(image_info->signature == MagickCoreSignature);
3160   if (image_info->debug != MagickFalse)
3161     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3162       image_info->filename);
3163   assert(exception != (ExceptionInfo *) NULL);
3164   if ((blob == (const void *) NULL) || (length == 0))
3165     {
3166       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3167         "UnrecognizedImageFormat","`%s'",image_info->magick);
3168       return((Image *) NULL);
3169     }
3170   ping_info=CloneImageInfo(image_info);
3171   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
3172   if (ping_info->blob == (const void *) NULL)
3173     {
3174       (void) ThrowMagickException(exception,GetMagickModule(),
3175         ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
3176       return((Image *) NULL);
3177     }
3178   (void) memcpy(ping_info->blob,blob,length);
3179   ping_info->length=length;
3180   ping_info->ping=MagickTrue;
3181   image=ReadStream(ping_info,&PingStream,exception);
3182   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
3183   ping_info=DestroyImageInfo(ping_info);
3184   return(image);
3185 }
3186 \f
3187 /*
3188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3189 %                                                                             %
3190 %                                                                             %
3191 %                                                                             %
3192 +  R e a d B l o b                                                            %
3193 %                                                                             %
3194 %                                                                             %
3195 %                                                                             %
3196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3197 %
3198 %  ReadBlob() reads data from the blob or image file and returns it.  It
3199 %  returns the number of bytes read. If length is zero, ReadBlob() returns
3200 %  zero and has no other results. If length is greater than SSIZE_MAX, the
3201 %  result is unspecified.
3202 %
3203 %  The format of the ReadBlob method is:
3204 %
3205 %      ssize_t ReadBlob(Image *image,const size_t length,void *data)
3206 %
3207 %  A description of each parameter follows:
3208 %
3209 %    o image: the image.
3210 %
3211 %    o length:  Specifies an integer representing the number of bytes to read
3212 %      from the file.
3213 %
3214 %    o data:  Specifies an area to place the information requested from the
3215 %      file.
3216 %
3217 */
3218 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3219 {
3220   int
3221     c;
3222
3223   register unsigned char
3224     *q;
3225
3226   ssize_t
3227     count;
3228
3229   assert(image != (Image *) NULL);
3230   assert(image->signature == MagickCoreSignature);
3231   assert(image->blob != (BlobInfo *) NULL);
3232   assert(image->blob->type != UndefinedStream);
3233   if (length == 0)
3234     return(0);
3235   assert(data != (void *) NULL);
3236   count=0;
3237   q=(unsigned char *) data;
3238   switch (image->blob->type)
3239   {
3240     case UndefinedStream:
3241       break;
3242     case StandardStream:
3243     case FileStream:
3244     case PipeStream:
3245     {
3246       switch (length)
3247       {
3248         default:
3249         {
3250           count=(ssize_t) fread(q,1,length,image->blob->file_info.file);
3251           break;
3252         }
3253         case 4:
3254         {
3255           c=getc(image->blob->file_info.file);
3256           if (c == EOF)
3257             break;
3258           *q++=(unsigned char) c;
3259           count++;
3260         }
3261         case 3:
3262         {
3263           c=getc(image->blob->file_info.file);
3264           if (c == EOF)
3265             break;
3266           *q++=(unsigned char) c;
3267           count++;
3268         }
3269         case 2:
3270         {
3271           c=getc(image->blob->file_info.file);
3272           if (c == EOF)
3273             break;
3274           *q++=(unsigned char) c;
3275           count++;
3276         }
3277         case 1:
3278         {
3279           c=getc(image->blob->file_info.file);
3280           if (c == EOF)
3281             break;
3282           *q++=(unsigned char) c;
3283           count++;
3284         }
3285         case 0:
3286           break;
3287       }
3288       break;
3289     }
3290     case ZipStream:
3291     {
3292 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3293       switch (length)
3294       {
3295         default:
3296         {
3297           count=(ssize_t) gzread(image->blob->file_info.gzfile,q,
3298             (unsigned int) length);
3299           break;
3300         }
3301         case 4:
3302         {
3303           c=gzgetc(image->blob->file_info.gzfile);
3304           if (c == EOF)
3305             break;
3306           *q++=(unsigned char) c;
3307           count++;
3308         }
3309         case 3:
3310         {
3311           c=gzgetc(image->blob->file_info.gzfile);
3312           if (c == EOF)
3313             break;
3314           *q++=(unsigned char) c;
3315           count++;
3316         }
3317         case 2:
3318         {
3319           c=gzgetc(image->blob->file_info.gzfile);
3320           if (c == EOF)
3321             break;
3322           *q++=(unsigned char) c;
3323           count++;
3324         }
3325         case 1:
3326         {
3327           c=gzgetc(image->blob->file_info.gzfile);
3328           if (c == EOF)
3329             break;
3330           *q++=(unsigned char) c;
3331           count++;
3332         }
3333         case 0:
3334           break;
3335       }
3336 #endif
3337       break;
3338     }
3339     case BZipStream:
3340     {
3341 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3342       count=(ssize_t) BZ2_bzread(image->blob->file_info.bzfile,q,(int) length);
3343 #endif
3344       break;
3345     }
3346     case FifoStream:
3347       break;
3348     case BlobStream:
3349     {
3350       register const unsigned char
3351         *p;
3352
3353       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
3354         {
3355           image->blob->eof=MagickTrue;
3356           break;
3357         }
3358       p=image->blob->data+image->blob->offset;
3359       count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
3360       image->blob->offset+=count;
3361       if (count != (ssize_t) length)
3362         image->blob->eof=MagickTrue;
3363       (void) memcpy(q,p,(size_t) count);
3364       break;
3365     }
3366     case CustomStream:
3367     {
3368       count=image->blob->custom_stream->reader(q,length,
3369         image->blob->custom_stream->data);
3370       break;
3371     }
3372   }
3373   return(count);
3374 }
3375 \f
3376 /*
3377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3378 %                                                                             %
3379 %                                                                             %
3380 %                                                                             %
3381 +  R e a d B l o b B y t e                                                    %
3382 %                                                                             %
3383 %                                                                             %
3384 %                                                                             %
3385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3386 %
3387 %  ReadBlobByte() reads a single byte from the image file and returns it.
3388 %
3389 %  The format of the ReadBlobByte method is:
3390 %
3391 %      int ReadBlobByte(Image *image)
3392 %
3393 %  A description of each parameter follows.
3394 %
3395 %    o image: the image.
3396 %
3397 */
3398 MagickExport int ReadBlobByte(Image *image)
3399 {
3400   register const unsigned char
3401     *p;
3402
3403   ssize_t
3404     count;
3405
3406   unsigned char
3407     buffer[1];
3408
3409   assert(image != (Image *) NULL);
3410   assert(image->signature == MagickCoreSignature);
3411   p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3412   if (count != 1)
3413     return(EOF);
3414   return((int) (*p));
3415 }
3416 \f
3417 /*
3418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3419 %                                                                             %
3420 %                                                                             %
3421 %                                                                             %
3422 +  R e a d B l o b D o u b l e                                                %
3423 %                                                                             %
3424 %                                                                             %
3425 %                                                                             %
3426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3427 %
3428 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3429 %  specified by the endian member of the image structure.
3430 %
3431 %  The format of the ReadBlobDouble method is:
3432 %
3433 %      double ReadBlobDouble(Image *image)
3434 %
3435 %  A description of each parameter follows.
3436 %
3437 %    o image: the image.
3438 %
3439 */
3440 MagickExport double ReadBlobDouble(Image *image)
3441 {
3442   union
3443   {
3444     MagickSizeType
3445       unsigned_value;
3446
3447     double
3448       double_value;
3449   } quantum;
3450
3451   quantum.double_value=0.0;
3452   quantum.unsigned_value=ReadBlobLongLong(image);
3453   return(quantum.double_value);
3454 }
3455 \f
3456 /*
3457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3458 %                                                                             %
3459 %                                                                             %
3460 %                                                                             %
3461 +  R e a d B l o b F l o a t                                                  %
3462 %                                                                             %
3463 %                                                                             %
3464 %                                                                             %
3465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3466 %
3467 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3468 %  specified by the endian member of the image structure.
3469 %
3470 %  The format of the ReadBlobFloat method is:
3471 %
3472 %      float ReadBlobFloat(Image *image)
3473 %
3474 %  A description of each parameter follows.
3475 %
3476 %    o image: the image.
3477 %
3478 */
3479 MagickExport float ReadBlobFloat(Image *image)
3480 {
3481   union
3482   {
3483     unsigned int
3484       unsigned_value;
3485
3486     float
3487       float_value;
3488   } quantum;
3489
3490   quantum.float_value=0.0;
3491   quantum.unsigned_value=ReadBlobLong(image);
3492   return(quantum.float_value);
3493 }
3494 \f
3495 /*
3496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3497 %                                                                             %
3498 %                                                                             %
3499 %                                                                             %
3500 +  R e a d B l o b L o n g                                                    %
3501 %                                                                             %
3502 %                                                                             %
3503 %                                                                             %
3504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3505 %
3506 %  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3507 %  byte-order specified by the endian member of the image structure.
3508 %
3509 %  The format of the ReadBlobLong method is:
3510 %
3511 %      unsigned int ReadBlobLong(Image *image)
3512 %
3513 %  A description of each parameter follows.
3514 %
3515 %    o image: the image.
3516 %
3517 */
3518 MagickExport unsigned int ReadBlobLong(Image *image)
3519 {
3520   register const unsigned char
3521     *p;
3522
3523   ssize_t
3524     count;
3525
3526   unsigned char
3527     buffer[4];
3528
3529   unsigned int
3530     value;
3531
3532   assert(image != (Image *) NULL);
3533   assert(image->signature == MagickCoreSignature);
3534   *buffer='\0';
3535   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3536   if (count != 4)
3537     return(0UL);
3538   if (image->endian == LSBEndian)
3539     {
3540       value=(unsigned int) (*p++);
3541       value|=(unsigned int) (*p++) << 8;
3542       value|=(unsigned int) (*p++) << 16;
3543       value|=(unsigned int) (*p++) << 24;
3544       return(value & 0xffffffff);
3545     }
3546   value=(unsigned int) (*p++) << 24;
3547   value|=(unsigned int) (*p++) << 16;
3548   value|=(unsigned int) (*p++) << 8;
3549   value|=(unsigned int) (*p++);
3550   return(value & 0xffffffff);
3551 }
3552 \f
3553 /*
3554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3555 %                                                                             %
3556 %                                                                             %
3557 %                                                                             %
3558 +  R e a d B l o b L o n g L o n g                                            %
3559 %                                                                             %
3560 %                                                                             %
3561 %                                                                             %
3562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3563 %
3564 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3565 %  byte-order specified by the endian member of the image structure.
3566 %
3567 %  The format of the ReadBlobLongLong method is:
3568 %
3569 %      MagickSizeType ReadBlobLongLong(Image *image)
3570 %
3571 %  A description of each parameter follows.
3572 %
3573 %    o image: the image.
3574 %
3575 */
3576 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3577 {
3578   MagickSizeType
3579     value;
3580
3581   register const unsigned char
3582     *p;
3583
3584   ssize_t
3585     count;
3586
3587   unsigned char
3588     buffer[8];
3589
3590   assert(image != (Image *) NULL);
3591   assert(image->signature == MagickCoreSignature);
3592   *buffer='\0';
3593   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3594   if (count != 8)
3595     return(MagickULLConstant(0));
3596   if (image->endian == LSBEndian)
3597     {
3598       value=(MagickSizeType) (*p++);
3599       value|=(MagickSizeType) (*p++) << 8;
3600       value|=(MagickSizeType) (*p++) << 16;
3601       value|=(MagickSizeType) (*p++) << 24;
3602       value|=(MagickSizeType) (*p++) << 32;
3603       value|=(MagickSizeType) (*p++) << 40;
3604       value|=(MagickSizeType) (*p++) << 48;
3605       value|=(MagickSizeType) (*p++) << 56;
3606       return(value & MagickULLConstant(0xffffffffffffffff));
3607     }
3608   value=(MagickSizeType) (*p++) << 56;
3609   value|=(MagickSizeType) (*p++) << 48;
3610   value|=(MagickSizeType) (*p++) << 40;
3611   value|=(MagickSizeType) (*p++) << 32;
3612   value|=(MagickSizeType) (*p++) << 24;
3613   value|=(MagickSizeType) (*p++) << 16;
3614   value|=(MagickSizeType) (*p++) << 8;
3615   value|=(MagickSizeType) (*p++);
3616   return(value & MagickULLConstant(0xffffffffffffffff));
3617 }
3618 \f
3619 /*
3620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3621 %                                                                             %
3622 %                                                                             %
3623 %                                                                             %
3624 +  R e a d B l o b S h o r t                                                  %
3625 %                                                                             %
3626 %                                                                             %
3627 %                                                                             %
3628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3629 %
3630 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3631 %  specified by the endian member of the image structure.
3632 %
3633 %  The format of the ReadBlobShort method is:
3634 %
3635 %      unsigned short ReadBlobShort(Image *image)
3636 %
3637 %  A description of each parameter follows.
3638 %
3639 %    o image: the image.
3640 %
3641 */
3642 MagickExport unsigned short ReadBlobShort(Image *image)
3643 {
3644   register const unsigned char
3645     *p;
3646
3647   register unsigned short
3648     value;
3649
3650   ssize_t
3651     count;
3652
3653   unsigned char
3654     buffer[2];
3655
3656   assert(image != (Image *) NULL);
3657   assert(image->signature == MagickCoreSignature);
3658   *buffer='\0';
3659   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3660   if (count != 2)
3661     return((unsigned short) 0U);
3662   if (image->endian == LSBEndian)
3663     {
3664       value=(unsigned short) (*p++);
3665       value|=(unsigned short) (*p++) << 8;
3666       return(value);
3667     }
3668   value=(unsigned short) (*p++) << 8;
3669   value|=(unsigned short) (*p++);
3670   return(value);
3671 }
3672 \f
3673 /*
3674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3675 %                                                                             %
3676 %                                                                             %
3677 %                                                                             %
3678 +  R e a d B l o b L S B L o n g                                              %
3679 %                                                                             %
3680 %                                                                             %
3681 %                                                                             %
3682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3683 %
3684 %  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3685 %  least-significant byte first order.
3686 %
3687 %  The format of the ReadBlobLSBLong method is:
3688 %
3689 %      unsigned int ReadBlobLSBLong(Image *image)
3690 %
3691 %  A description of each parameter follows.
3692 %
3693 %    o image: the image.
3694 %
3695 */
3696 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3697 {
3698   register const unsigned char
3699     *p;
3700
3701   register unsigned int
3702     value;
3703
3704   ssize_t
3705     count;
3706
3707   unsigned char
3708     buffer[4];
3709
3710   assert(image != (Image *) NULL);
3711   assert(image->signature == MagickCoreSignature);
3712   *buffer='\0';
3713   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3714   if (count != 4)
3715     return(0U);
3716   value=(unsigned int) (*p++);
3717   value|=(unsigned int) (*p++) << 8;
3718   value|=(unsigned int) (*p++) << 16;
3719   value|=(unsigned int) (*p++) << 24;
3720   return(value & 0xffffffff);
3721 }
3722 \f
3723 /*
3724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3725 %                                                                             %
3726 %                                                                             %
3727 %                                                                             %
3728 +  R e a d B l o b L S B S i g n e d L o n g                                  %
3729 %                                                                             %
3730 %                                                                             %
3731 %                                                                             %
3732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3733 %
3734 %  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3735 %  least-significant byte first order.
3736 %
3737 %  The format of the ReadBlobLSBSignedLong method is:
3738 %
3739 %      signed int ReadBlobLSBSignedLong(Image *image)
3740 %
3741 %  A description of each parameter follows.
3742 %
3743 %    o image: the image.
3744 %
3745 */
3746 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
3747 {
3748   union
3749   {
3750     unsigned int
3751       unsigned_value;
3752
3753     signed int
3754       signed_value;
3755   } quantum;
3756
3757   quantum.unsigned_value=ReadBlobLSBLong(image);
3758   return(quantum.signed_value);
3759 }
3760 \f
3761 /*
3762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3763 %                                                                             %
3764 %                                                                             %
3765 %                                                                             %
3766 +  R e a d B l o b L S B S h o r t                                            %
3767 %                                                                             %
3768 %                                                                             %
3769 %                                                                             %
3770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3771 %
3772 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3773 %  least-significant byte first order.
3774 %
3775 %  The format of the ReadBlobLSBShort method is:
3776 %
3777 %      unsigned short ReadBlobLSBShort(Image *image)
3778 %
3779 %  A description of each parameter follows.
3780 %
3781 %    o image: the image.
3782 %
3783 */
3784 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3785 {
3786   register const unsigned char
3787     *p;
3788
3789   register unsigned short
3790     value;
3791
3792   ssize_t
3793     count;
3794
3795   unsigned char
3796     buffer[2];
3797
3798   assert(image != (Image *) NULL);
3799   assert(image->signature == MagickCoreSignature);
3800   *buffer='\0';
3801   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3802   if (count != 2)
3803     return((unsigned short) 0U);
3804   value=(unsigned int) (*p++);
3805   value|=(unsigned int) (*p++) << 8;
3806   return(value & 0xffff);
3807 }
3808 \f
3809 /*
3810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3811 %                                                                             %
3812 %                                                                             %
3813 %                                                                             %
3814 +  R e a d B l o b L S B S i g n e d S h o r t                                %
3815 %                                                                             %
3816 %                                                                             %
3817 %                                                                             %
3818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3819 %
3820 %  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
3821 %  least-significant byte-order.
3822 %
3823 %  The format of the ReadBlobLSBSignedShort method is:
3824 %
3825 %      signed short ReadBlobLSBSignedShort(Image *image)
3826 %
3827 %  A description of each parameter follows.
3828 %
3829 %    o image: the image.
3830 %
3831 */
3832 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
3833 {
3834   union
3835   {
3836     unsigned short
3837       unsigned_value;
3838
3839     signed short
3840       signed_value;
3841   } quantum;
3842
3843   quantum.unsigned_value=ReadBlobLSBShort(image);
3844   return(quantum.signed_value);
3845 }
3846 \f
3847 /*
3848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3849 %                                                                             %
3850 %                                                                             %
3851 %                                                                             %
3852 +  R e a d B l o b M S B L o n g                                              %
3853 %                                                                             %
3854 %                                                                             %
3855 %                                                                             %
3856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3857 %
3858 %  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
3859 %  most-significant byte first order.
3860 %
3861 %  The format of the ReadBlobMSBLong method is:
3862 %
3863 %      unsigned int ReadBlobMSBLong(Image *image)
3864 %
3865 %  A description of each parameter follows.
3866 %
3867 %    o image: the image.
3868 %
3869 */
3870 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3871 {
3872   register const unsigned char
3873     *p;
3874
3875   register unsigned int
3876     value;
3877
3878   ssize_t
3879     count;
3880
3881   unsigned char
3882     buffer[4];
3883
3884   assert(image != (Image *) NULL);
3885   assert(image->signature == MagickCoreSignature);
3886   *buffer='\0';
3887   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3888   if (count != 4)
3889     return(0UL);
3890   value=(unsigned int) (*p++) << 24;
3891   value|=(unsigned int) (*p++) << 16;
3892   value|=(unsigned int) (*p++) << 8;
3893   value|=(unsigned int) (*p++);
3894   return(value);
3895 }
3896 \f
3897 /*
3898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3899 %                                                                             %
3900 %                                                                             %
3901 %                                                                             %
3902 +  R e a d B l o b M S B L o n g L o n g                                      %
3903 %                                                                             %
3904 %                                                                             %
3905 %                                                                             %
3906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3907 %
3908 %  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
3909 %  in most-significant byte first order.
3910 %
3911 %  The format of the ReadBlobMSBLongLong method is:
3912 %
3913 %      unsigned int ReadBlobMSBLongLong(Image *image)
3914 %
3915 %  A description of each parameter follows.
3916 %
3917 %    o image: the image.
3918 %
3919 */
3920 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3921 {
3922   register const unsigned char
3923     *p;
3924
3925   register MagickSizeType
3926     value;
3927
3928   ssize_t
3929     count;
3930
3931   unsigned char
3932     buffer[8];
3933
3934   assert(image != (Image *) NULL);
3935   assert(image->signature == MagickCoreSignature);
3936   *buffer='\0';
3937   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3938   if (count != 8)
3939     return(MagickULLConstant(0));
3940   value=(MagickSizeType) (*p++) << 56;
3941   value|=(MagickSizeType) (*p++) << 48;
3942   value|=(MagickSizeType) (*p++) << 40;
3943   value|=(MagickSizeType) (*p++) << 32;
3944   value|=(MagickSizeType) (*p++) << 24;
3945   value|=(MagickSizeType) (*p++) << 16;
3946   value|=(MagickSizeType) (*p++) << 8;
3947   value|=(MagickSizeType) (*p++);
3948   return(value & MagickULLConstant(0xffffffffffffffff));
3949 }
3950 \f
3951 /*
3952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3953 %                                                                             %
3954 %                                                                             %
3955 %                                                                             %
3956 +  R e a d B l o b M S B S h o r t                                            %
3957 %                                                                             %
3958 %                                                                             %
3959 %                                                                             %
3960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3961 %
3962 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3963 %  most-significant byte first order.
3964 %
3965 %  The format of the ReadBlobMSBShort method is:
3966 %
3967 %      unsigned short ReadBlobMSBShort(Image *image)
3968 %
3969 %  A description of each parameter follows.
3970 %
3971 %    o image: the image.
3972 %
3973 */
3974 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3975 {
3976   register const unsigned char
3977     *p;
3978
3979   register unsigned short
3980     value;
3981
3982   ssize_t
3983     count;
3984
3985   unsigned char
3986     buffer[2];
3987
3988   assert(image != (Image *) NULL);
3989   assert(image->signature == MagickCoreSignature);
3990   *buffer='\0';
3991   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3992   if (count != 2)
3993     return((unsigned short) 0U);
3994   value=(unsigned short) (*p++) << 8;
3995   value|=(unsigned short) (*p++);
3996   return(value & 0xffff);
3997 }
3998 \f
3999 /*
4000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4001 %                                                                             %
4002 %                                                                             %
4003 %                                                                             %
4004 +  R e a d B l o b M S B S i g n e d L o n g                                  %
4005 %                                                                             %
4006 %                                                                             %
4007 %                                                                             %
4008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4009 %
4010 %  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4011 %  most-significant byte-order.
4012 %
4013 %  The format of the ReadBlobMSBSignedLong method is:
4014 %
4015 %      signed int ReadBlobMSBSignedLong(Image *image)
4016 %
4017 %  A description of each parameter follows.
4018 %
4019 %    o image: the image.
4020 %
4021 */
4022 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4023 {
4024   union
4025   {
4026     unsigned int
4027       unsigned_value;
4028
4029     signed int
4030       signed_value;
4031   } quantum;
4032
4033   quantum.unsigned_value=ReadBlobMSBLong(image);
4034   return(quantum.signed_value);
4035 }
4036 \f
4037 /*
4038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4039 %                                                                             %
4040 %                                                                             %
4041 %                                                                             %
4042 +  R e a d B l o b M S B S i g n e d S h o r t                                %
4043 %                                                                             %
4044 %                                                                             %
4045 %                                                                             %
4046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4047 %
4048 %  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4049 %  most-significant byte-order.
4050 %
4051 %  The format of the ReadBlobMSBSignedShort method is:
4052 %
4053 %      signed short ReadBlobMSBSignedShort(Image *image)
4054 %
4055 %  A description of each parameter follows.
4056 %
4057 %    o image: the image.
4058 %
4059 */
4060 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4061 {
4062   union
4063   {
4064     unsigned short
4065       unsigned_value;
4066
4067     signed short
4068       signed_value;
4069   } quantum;
4070
4071   quantum.unsigned_value=ReadBlobMSBShort(image);
4072   return(quantum.signed_value);
4073 }
4074 \f
4075 /*
4076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4077 %                                                                             %
4078 %                                                                             %
4079 %                                                                             %
4080 +  R e a d B l o b S i g n e d L o n g                                        %
4081 %                                                                             %
4082 %                                                                             %
4083 %                                                                             %
4084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4085 %
4086 %  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4087 %  byte-order specified by the endian member of the image structure.
4088 %
4089 %  The format of the ReadBlobSignedLong method is:
4090 %
4091 %      signed int ReadBlobSignedLong(Image *image)
4092 %
4093 %  A description of each parameter follows.
4094 %
4095 %    o image: the image.
4096 %
4097 */
4098 MagickExport signed int ReadBlobSignedLong(Image *image)
4099 {
4100   union
4101   {
4102     unsigned int
4103       unsigned_value;
4104
4105     signed int
4106       signed_value;
4107   } quantum;
4108
4109   quantum.unsigned_value=ReadBlobLong(image);
4110   return(quantum.signed_value);
4111 }
4112 \f
4113 /*
4114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4115 %                                                                             %
4116 %                                                                             %
4117 %                                                                             %
4118 +  R e a d B l o b S i g n e d S h o r t                                      %
4119 %                                                                             %
4120 %                                                                             %
4121 %                                                                             %
4122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4123 %
4124 %  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4125 %  byte-order specified by the endian member of the image structure.
4126 %
4127 %  The format of the ReadBlobSignedShort method is:
4128 %
4129 %      signed short ReadBlobSignedShort(Image *image)
4130 %
4131 %  A description of each parameter follows.
4132 %
4133 %    o image: the image.
4134 %
4135 */
4136 MagickExport signed short ReadBlobSignedShort(Image *image)
4137 {
4138   union
4139   {
4140     unsigned short
4141       unsigned_value;
4142
4143     signed short
4144       signed_value;
4145   } quantum;
4146
4147   quantum.unsigned_value=ReadBlobShort(image);
4148   return(quantum.signed_value);
4149 }
4150 \f
4151 /*
4152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4153 %                                                                             %
4154 %                                                                             %
4155 %                                                                             %
4156 +  R e a d B l o b S t r e a m                                                %
4157 %                                                                             %
4158 %                                                                             %
4159 %                                                                             %
4160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4161 %
4162 %  ReadBlobStream() reads data from the blob or image file and returns it.  It
4163 %  returns a pointer to the data buffer you supply or to the image memory
4164 %  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4165 %  returns a count of zero and has no other results. If length is greater than
4166 %  SSIZE_MAX, the result is unspecified.
4167 %
4168 %  The format of the ReadBlobStream method is:
4169 %
4170 %      const void *ReadBlobStream(Image *image,const size_t length,void *data,
4171 %        ssize_t *count)
4172 %
4173 %  A description of each parameter follows:
4174 %
4175 %    o image: the image.
4176 %
4177 %    o length:  Specifies an integer representing the number of bytes to read
4178 %      from the file.
4179 %
4180 %    o count: returns the number of bytes read.
4181 %
4182 %    o data:  Specifies an area to place the information requested from the
4183 %      file.
4184 %
4185 */
4186 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
4187   void *data,ssize_t *count)
4188 {
4189   assert(image != (Image *) NULL);
4190   assert(image->signature == MagickCoreSignature);
4191   assert(image->blob != (BlobInfo *) NULL);
4192   assert(image->blob->type != UndefinedStream);
4193   assert(count != (ssize_t *) NULL);
4194   if (image->blob->type != BlobStream)
4195     {
4196       assert(data != NULL);
4197       *count=ReadBlob(image,length,(unsigned char *) data);
4198       return(data);
4199     }
4200   if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4201     {
4202       *count=0;
4203       image->blob->eof=MagickTrue;
4204       return(data);
4205     }
4206   data=image->blob->data+image->blob->offset;
4207   *count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
4208   image->blob->offset+=(*count);
4209   if (*count != (ssize_t) length)
4210     image->blob->eof=MagickTrue;
4211   return(data);
4212 }
4213 \f
4214 /*
4215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4216 %                                                                             %
4217 %                                                                             %
4218 %                                                                             %
4219 +   R e a d B l o b S t r i n g                                               %
4220 %                                                                             %
4221 %                                                                             %
4222 %                                                                             %
4223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4224 %
4225 %  ReadBlobString() reads characters from a blob or file until a newline
4226 %  character is read or an end-of-file condition is encountered.
4227 %
4228 %  The format of the ReadBlobString method is:
4229 %
4230 %      char *ReadBlobString(Image *image,char *string)
4231 %
4232 %  A description of each parameter follows:
4233 %
4234 %    o image: the image.
4235 %
4236 %    o string: the address of a character buffer.
4237 %
4238 */
4239 MagickExport char *ReadBlobString(Image *image,char *string)
4240 {
4241   register const unsigned char
4242     *p;
4243
4244   register ssize_t
4245     i;
4246
4247   ssize_t
4248     count;
4249
4250   unsigned char
4251     buffer[1];
4252
4253   assert(image != (Image *) NULL);
4254   assert(image->signature == MagickCoreSignature);
4255   for (i=0; i < (MagickPathExtent-1L); i++)
4256   {
4257     p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
4258     if (count != 1)
4259       {
4260         if (i == 0)
4261           return((char *) NULL);
4262         break;
4263       }
4264     string[i]=(char) (*p);
4265     if ((string[i] == '\r') || (string[i] == '\n'))
4266       break;
4267   }
4268   if (string[i] == '\r')
4269     (void) ReadBlobStream(image,1,buffer,&count);
4270   string[i]='\0';
4271   return(string);
4272 }
4273 \f
4274 /*
4275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4276 %                                                                             %
4277 %                                                                             %
4278 %                                                                             %
4279 +   R e f e r e n c e B l o b                                                 %
4280 %                                                                             %
4281 %                                                                             %
4282 %                                                                             %
4283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4284 %
4285 %  ReferenceBlob() increments the reference count associated with the pixel
4286 %  blob returning a pointer to the blob.
4287 %
4288 %  The format of the ReferenceBlob method is:
4289 %
4290 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
4291 %
4292 %  A description of each parameter follows:
4293 %
4294 %    o blob_info: the blob_info.
4295 %
4296 */
4297 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4298 {
4299   assert(blob != (BlobInfo *) NULL);
4300   assert(blob->signature == MagickCoreSignature);
4301   if (blob->debug != MagickFalse)
4302     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4303   LockSemaphoreInfo(blob->semaphore);
4304   blob->reference_count++;
4305   UnlockSemaphoreInfo(blob->semaphore);
4306   return(blob);
4307 }
4308 \f
4309 /*
4310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4311 %                                                                             %
4312 %                                                                             %
4313 %                                                                             %
4314 +  S e e k B l o b                                                            %
4315 %                                                                             %
4316 %                                                                             %
4317 %                                                                             %
4318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4319 %
4320 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
4321 %  and returns the resulting offset.
4322 %
4323 %  The format of the SeekBlob method is:
4324 %
4325 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4326 %        const int whence)
4327 %
4328 %  A description of each parameter follows:
4329 %
4330 %    o image: the image.
4331 %
4332 %    o offset:  Specifies an integer representing the offset in bytes.
4333 %
4334 %    o whence:  Specifies an integer representing how the offset is
4335 %      treated relative to the beginning of the blob as follows:
4336 %
4337 %        SEEK_SET  Set position equal to offset bytes.
4338 %        SEEK_CUR  Set position to current location plus offset.
4339 %        SEEK_END  Set position to EOF plus offset.
4340 %
4341 */
4342 MagickExport MagickOffsetType SeekBlob(Image *image,
4343   const MagickOffsetType offset,const int whence)
4344 {
4345   assert(image != (Image *) NULL);
4346   assert(image->signature == MagickCoreSignature);
4347   if (image->debug != MagickFalse)
4348     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4349   assert(image->blob != (BlobInfo *) NULL);
4350   assert(image->blob->type != UndefinedStream);
4351   switch (image->blob->type)
4352   {
4353     case UndefinedStream:
4354       break;
4355     case StandardStream:
4356     case PipeStream:
4357       return(-1);
4358     case FileStream:
4359     {
4360       if ((offset < 0) && (whence == SEEK_SET))
4361         return(-1);
4362       if (fseek(image->blob->file_info.file,offset,whence) < 0)
4363         return(-1);
4364       image->blob->offset=TellBlob(image);
4365       break;
4366     }
4367     case ZipStream:
4368     {
4369 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4370       if (gzseek(image->blob->file_info.gzfile,(off_t) offset,whence) < 0)
4371         return(-1);
4372 #endif
4373       image->blob->offset=TellBlob(image);
4374       break;
4375     }
4376     case BZipStream:
4377       return(-1);
4378     case FifoStream:
4379       return(-1);
4380     case BlobStream:
4381     {
4382       switch (whence)
4383       {
4384         case SEEK_SET:
4385         default:
4386         {
4387           if (offset < 0)
4388             return(-1);
4389           image->blob->offset=offset;
4390           break;
4391         }
4392         case SEEK_CUR:
4393         {
4394           if ((image->blob->offset+offset) < 0)
4395             return(-1);
4396           image->blob->offset+=offset;
4397           break;
4398         }
4399         case SEEK_END:
4400         {
4401           if (((MagickOffsetType) image->blob->length+offset) < 0)
4402             return(-1);
4403           image->blob->offset=image->blob->length+offset;
4404           break;
4405         }
4406       }
4407       if (image->blob->offset < (MagickOffsetType)
4408           ((off_t) image->blob->length))
4409         {
4410           image->blob->eof=MagickFalse;
4411           break;
4412         }
4413       if (image->blob->offset < (MagickOffsetType)
4414           ((off_t) image->blob->extent))
4415         break;
4416       if (image->blob->mapped != MagickFalse)
4417         {
4418           image->blob->eof=MagickTrue;
4419           return(-1);
4420         }
4421       image->blob->extent=(size_t) (image->blob->offset+image->blob->quantum);
4422       image->blob->quantum<<=1;
4423       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
4424         image->blob->extent+1,sizeof(*image->blob->data));
4425       (void) SyncBlob(image);
4426       if (image->blob->data == NULL)
4427         {
4428           (void) DetachBlob(image->blob);
4429           return(-1);
4430         }
4431       break;
4432     }
4433     case CustomStream:
4434     {
4435       if (image->blob->custom_stream->seeker == (CustomStreamSeeker) NULL)
4436         return(-1);
4437       image->blob->offset=image->blob->custom_stream->seeker(offset,whence,
4438         image->blob->custom_stream->data);
4439       break;
4440     }
4441   }
4442   return(image->blob->offset);
4443 }
4444 \f
4445 /*
4446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4447 %                                                                             %
4448 %                                                                             %
4449 %                                                                             %
4450 +   S e t B l o b E x e m p t                                                 %
4451 %                                                                             %
4452 %                                                                             %
4453 %                                                                             %
4454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4455 %
4456 %  SetBlobExempt() sets the blob exempt status.
4457 %
4458 %  The format of the SetBlobExempt method is:
4459 %
4460 %      MagickBooleanType SetBlobExempt(const Image *image,
4461 %        const MagickBooleanType exempt)
4462 %
4463 %  A description of each parameter follows:
4464 %
4465 %    o image: the image.
4466 %
4467 %    o exempt: Set to true if this blob is exempt from being closed.
4468 %
4469 */
4470 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4471 {
4472   assert(image != (const Image *) NULL);
4473   assert(image->signature == MagickCoreSignature);
4474   if (image->debug != MagickFalse)
4475     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4476   image->blob->exempt=exempt;
4477 }
4478 \f
4479 /*
4480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4481 %                                                                             %
4482 %                                                                             %
4483 %                                                                             %
4484 +  S e t B l o b E x t e n t                                                  %
4485 %                                                                             %
4486 %                                                                             %
4487 %                                                                             %
4488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4489 %
4490 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
4491 %  method is successful, subsequent writes to bytes in the specified range are
4492 %  guaranteed not to fail.
4493 %
4494 %  The format of the SetBlobExtent method is:
4495 %
4496 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
4497 %
4498 %  A description of each parameter follows:
4499 %
4500 %    o image: the image.
4501 %
4502 %    o extent:  the blob maximum extent.
4503 %
4504 */
4505 MagickExport MagickBooleanType SetBlobExtent(Image *image,
4506   const MagickSizeType extent)
4507 {
4508   assert(image != (Image *) NULL);
4509   assert(image->signature == MagickCoreSignature);
4510   if (image->debug != MagickFalse)
4511     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4512   assert(image->blob != (BlobInfo *) NULL);
4513   assert(image->blob->type != UndefinedStream);
4514   switch (image->blob->type)
4515   {
4516     case UndefinedStream:
4517       break;
4518     case StandardStream:
4519       return(MagickFalse);
4520     case FileStream:
4521     {
4522       MagickOffsetType
4523         offset;
4524
4525       ssize_t
4526         count;
4527
4528       if (extent != (MagickSizeType) ((off_t) extent))
4529         return(MagickFalse);
4530       offset=SeekBlob(image,0,SEEK_END);
4531       if (offset < 0)
4532         return(MagickFalse);
4533       if ((MagickSizeType) offset >= extent)
4534         break;
4535       offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4536       if (offset < 0)
4537         break;
4538       count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4539         image->blob->file_info.file);
4540 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4541       if (image->blob->synchronize != MagickFalse)
4542         {
4543           int
4544             file;
4545
4546           file=fileno(image->blob->file_info.file);
4547           if ((file == -1) || (offset < 0))
4548             return(MagickFalse);
4549           (void) posix_fallocate(file,offset,extent-offset);
4550         }
4551 #endif
4552       offset=SeekBlob(image,offset,SEEK_SET);
4553       if (count != 1)
4554         return(MagickFalse);
4555       break;
4556     }
4557     case PipeStream:
4558     case ZipStream:
4559       return(MagickFalse);
4560     case BZipStream:
4561       return(MagickFalse);
4562     case FifoStream:
4563       return(MagickFalse);
4564     case BlobStream:
4565     {
4566       if (extent != (MagickSizeType) ((size_t) extent))
4567         return(MagickFalse);
4568       if (image->blob->mapped != MagickFalse)
4569         {
4570           MagickOffsetType
4571             offset;
4572
4573           ssize_t
4574             count;
4575
4576           (void) UnmapBlob(image->blob->data,image->blob->length);
4577           RelinquishMagickResource(MapResource,image->blob->length);
4578           if (extent != (MagickSizeType) ((off_t) extent))
4579             return(MagickFalse);
4580           offset=SeekBlob(image,0,SEEK_END);
4581           if (offset < 0)
4582             return(MagickFalse);
4583           if ((MagickSizeType) offset >= extent)
4584             break;
4585           offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4586           count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4587             image->blob->file_info.file);
4588 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4589           if (image->blob->synchronize != MagickFalse)
4590             {
4591               int
4592                 file;
4593
4594               file=fileno(image->blob->file_info.file);
4595               if ((file == -1) || (offset < 0))
4596                 return(MagickFalse);
4597               (void) posix_fallocate(file,offset,extent-offset);
4598             }
4599 #endif
4600           offset=SeekBlob(image,offset,SEEK_SET);
4601           if (count != 1)
4602             return(MagickFalse);
4603           (void) AcquireMagickResource(MapResource,extent);
4604           image->blob->data=(unsigned char*) MapBlob(fileno(
4605             image->blob->file_info.file),WriteMode,0,(size_t) extent);
4606           image->blob->extent=(size_t) extent;
4607           image->blob->length=(size_t) extent;
4608           (void) SyncBlob(image);
4609           break;
4610         }
4611       image->blob->extent=(size_t) extent;
4612       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
4613         image->blob->extent+1,sizeof(*image->blob->data));
4614       (void) SyncBlob(image);
4615       if (image->blob->data == (unsigned char *) NULL)
4616         {
4617           (void) DetachBlob(image->blob);
4618           return(MagickFalse);
4619         }
4620       break;
4621     }
4622     case CustomStream:
4623       break;
4624   }
4625   return(MagickTrue);
4626 }
4627 \f
4628 /*
4629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4630 %                                                                             %
4631 %                                                                             %
4632 %                                                                             %
4633 +  S e t C u s t o m S t r e a m D a t a                                      %
4634 %                                                                             %
4635 %                                                                             %
4636 %                                                                             %
4637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4638 %
4639 %  SetCustomStreamData() sets the stream info data member.
4640 %
4641 %  The format of the SetCustomStreamData method is:
4642 %
4643 %      void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
4644 %
4645 %  A description of each parameter follows:
4646 %
4647 %    o custom_stream: your custom stream.
4648 %
4649 %    o void: your data.
4650 %
4651 */
4652 MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
4653   void *data)
4654 {
4655   assert(custom_stream != (CustomStreamInfo *) NULL);
4656   assert(custom_stream->signature == MagickCoreSignature);
4657   custom_stream->data=data;
4658 }
4659 \f
4660 /*
4661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4662 %                                                                             %
4663 %                                                                             %
4664 %                                                                             %
4665 +  S e t C u s t o m S t r e a m R e a d e r                                  %
4666 %                                                                             %
4667 %                                                                             %
4668 %                                                                             %
4669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4670 %
4671 %  SetCustomStreamReader() sets the stream info reader member.
4672 %
4673 %  The format of the SetCustomStreamReader method is:
4674 %
4675 %      void SetCustomStreamReader(CustomStreamInfo *custom_stream,
4676 %        CustomStreamHandler reader)
4677 %
4678 %  A description of each parameter follows:
4679 %
4680 %    o custom_stream: your custom stream.
4681 %
4682 %    o reader: your custom stream reader.
4683 %
4684 */
4685 MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
4686   CustomStreamHandler reader)
4687 {
4688   assert(custom_stream != (CustomStreamInfo *) NULL);
4689   assert(custom_stream->signature == MagickCoreSignature);
4690   custom_stream->reader=reader;
4691 }
4692 \f
4693 /*
4694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4695 %                                                                             %
4696 %                                                                             %
4697 %                                                                             %
4698 +  S e t C u s t o m S t r e a m S e e k e r                                  %
4699 %                                                                             %
4700 %                                                                             %
4701 %                                                                             %
4702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4703 %
4704 %  SetCustomStreamSeeker() sets the stream info seeker member.
4705 %
4706 %  The format of the SetCustomStreamReader method is:
4707 %
4708 %      void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
4709 %        CustomStreamSeeker seeker)
4710 %
4711 %  A description of each parameter follows:
4712 %
4713 %    o custom_stream: your custom stream.
4714 %
4715 %    o seeker: your custom stream seeker.
4716 %
4717 */
4718 MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
4719   CustomStreamSeeker seeker)
4720 {
4721   assert(custom_stream != (CustomStreamInfo *) NULL);
4722   assert(custom_stream->signature == MagickCoreSignature);
4723   custom_stream->seeker=seeker;
4724 }
4725 \f
4726 /*
4727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4728 %                                                                             %
4729 %                                                                             %
4730 %                                                                             %
4731 +  S e t C u s t o m S t r e a m T e l l e r                                  %
4732 %                                                                             %
4733 %                                                                             %
4734 %                                                                             %
4735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4736 %
4737 %  SetCustomStreamTeller() sets the stream info teller member.
4738 %
4739 %  The format of the SetCustomStreamTeller method is:
4740 %
4741 %      void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
4742 %        CustomStreamTeller *teller)
4743 %
4744 %  A description of each parameter follows:
4745 %
4746 %    o custom_stream: your custom stream.
4747 %
4748 %    o teller: your custom stream teller.
4749 %
4750 */
4751 MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
4752   CustomStreamTeller teller)
4753 {
4754   assert(custom_stream != (CustomStreamInfo *) NULL);
4755   assert(custom_stream->signature == MagickCoreSignature);
4756   custom_stream->teller=teller;
4757 }
4758 \f
4759 /*
4760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4761 %                                                                             %
4762 %                                                                             %
4763 %                                                                             %
4764 +  S e t C u s t o m S t r e a m W r i t e r                                  %
4765 %                                                                             %
4766 %                                                                             %
4767 %                                                                             %
4768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4769 %
4770 %  SetCustomStreamWriter() sets the stream info writer member.
4771 %
4772 %  The format of the SetCustomStreamWriter method is:
4773 %
4774 %      void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
4775 %        CustomStreamHandler *writer)
4776 %
4777 %  A description of each parameter follows:
4778 %
4779 %    o custom_stream: your custom stream.
4780 %
4781 %    o writer: your custom stream writer.
4782 %
4783 */
4784 MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
4785   CustomStreamHandler writer)
4786 {
4787   assert(custom_stream != (CustomStreamInfo *) NULL);
4788   assert(custom_stream->signature == MagickCoreSignature);
4789   custom_stream->writer=writer;
4790 }
4791 \f
4792 /*
4793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4794 %                                                                             %
4795 %                                                                             %
4796 %                                                                             %
4797 +  S y n c B l o b                                                            %
4798 %                                                                             %
4799 %                                                                             %
4800 %                                                                             %
4801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4802 %
4803 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
4804 %  attributes if it is an blob.
4805 %
4806 %  The format of the SyncBlob method is:
4807 %
4808 %      int SyncBlob(Image *image)
4809 %
4810 %  A description of each parameter follows:
4811 %
4812 %    o image: the image.
4813 %
4814 */
4815 static int SyncBlob(Image *image)
4816 {
4817   int
4818     status;
4819
4820   assert(image != (Image *) NULL);
4821   assert(image->signature == MagickCoreSignature);
4822   if (image->debug != MagickFalse)
4823     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4824   assert(image->blob != (BlobInfo *) NULL);
4825   assert(image->blob->type != UndefinedStream);
4826   status=0;
4827   switch (image->blob->type)
4828   {
4829     case UndefinedStream:
4830     case StandardStream:
4831       break;
4832     case FileStream:
4833     case PipeStream:
4834     {
4835       status=fflush(image->blob->file_info.file);
4836       break;
4837     }
4838     case ZipStream:
4839     {
4840 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4841       status=gzflush(image->blob->file_info.gzfile,Z_SYNC_FLUSH);
4842 #endif
4843       break;
4844     }
4845     case BZipStream:
4846     {
4847 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4848       status=BZ2_bzflush(image->blob->file_info.bzfile);
4849 #endif
4850       break;
4851     }
4852     case FifoStream:
4853       break;
4854     case BlobStream:
4855       break;
4856     case CustomStream:
4857       break;
4858   }
4859   return(status);
4860 }
4861 \f
4862 /*
4863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4864 %                                                                             %
4865 %                                                                             %
4866 %                                                                             %
4867 +  T e l l B l o b                                                            %
4868 %                                                                             %
4869 %                                                                             %
4870 %                                                                             %
4871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4872 %
4873 %  TellBlob() obtains the current value of the blob or file position.
4874 %
4875 %  The format of the TellBlob method is:
4876 %
4877 %      MagickOffsetType TellBlob(const Image *image)
4878 %
4879 %  A description of each parameter follows:
4880 %
4881 %    o image: the image.
4882 %
4883 */
4884 MagickExport MagickOffsetType TellBlob(const Image *image)
4885 {
4886   MagickOffsetType
4887     offset;
4888
4889   assert(image != (Image *) NULL);
4890   assert(image->signature == MagickCoreSignature);
4891   if (image->debug != MagickFalse)
4892     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4893   assert(image->blob != (BlobInfo *) NULL);
4894   assert(image->blob->type != UndefinedStream);
4895   offset=(-1);
4896   switch (image->blob->type)
4897   {
4898     case UndefinedStream:
4899     case StandardStream:
4900       break;
4901     case FileStream:
4902     {
4903       offset=ftell(image->blob->file_info.file);
4904       break;
4905     }
4906     case PipeStream:
4907       break;
4908     case ZipStream:
4909     {
4910 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4911       offset=(MagickOffsetType) gztell(image->blob->file_info.gzfile);
4912 #endif
4913       break;
4914     }
4915     case BZipStream:
4916       break;
4917     case FifoStream:
4918       break;
4919     case BlobStream:
4920     {
4921       offset=image->blob->offset;
4922       break;
4923     }
4924     case CustomStream:
4925     {
4926       if (image->blob->custom_stream->teller != (CustomStreamTeller) NULL)
4927         offset=image->blob->custom_stream->teller(image->blob->custom_stream->data);
4928       break;
4929     }
4930   }
4931   return(offset);
4932 }
4933 \f
4934 /*
4935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4936 %                                                                             %
4937 %                                                                             %
4938 %                                                                             %
4939 +  U n m a p B l o b                                                          %
4940 %                                                                             %
4941 %                                                                             %
4942 %                                                                             %
4943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4944 %
4945 %  UnmapBlob() deallocates the binary large object previously allocated with
4946 %  the MapBlob method.
4947 %
4948 %  The format of the UnmapBlob method is:
4949 %
4950 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
4951 %
4952 %  A description of each parameter follows:
4953 %
4954 %    o map: the address  of the binary large object.
4955 %
4956 %    o length: the length of the binary large object.
4957 %
4958 */
4959 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4960 {
4961 #if defined(MAGICKCORE_HAVE_MMAP)
4962   int
4963     status;
4964
4965   status=munmap(map,length);
4966   return(status == -1 ? MagickFalse : MagickTrue);
4967 #else
4968   (void) map;
4969   (void) length;
4970   return(MagickFalse);
4971 #endif
4972 }
4973 \f
4974 /*
4975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4976 %                                                                             %
4977 %                                                                             %
4978 %                                                                             %
4979 %   C u s t o m S t r e a m T o I m a g e                                     %
4980 %                                                                             %
4981 %                                                                             %
4982 %                                                                             %
4983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4984 %
4985 %  CustomStreamToImage() is the equivalent of ReadImage(), but reads the
4986 %  formatted "file" from the suplied method rather than to an actual file.
4987 %
4988 %  The format of the CustomStreamToImage method is:
4989 %
4990 %      Image *CustomStreamToImage(const ImageInfo *image_info,
4991 %         ExceptionInfo *exception)
4992 %
4993 %  A description of each parameter follows:
4994 %
4995 %    o image_info: the image info.
4996 %
4997 %    o exception: return any errors or warnings in this structure.
4998 %
4999 */
5000 MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
5001   ExceptionInfo *exception)
5002 {
5003   const MagickInfo
5004     *magick_info;
5005
5006   Image
5007     *image;
5008
5009   ImageInfo
5010     *blob_info;
5011
5012   assert(image_info != (ImageInfo *) NULL);
5013   assert(image_info->signature == MagickCoreSignature);
5014   if (image_info->debug != MagickFalse)
5015     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
5016       image_info->filename);
5017   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
5018   assert(image_info->custom_stream->signature == MagickCoreSignature);
5019   assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
5020   assert(exception != (ExceptionInfo *) NULL);
5021   blob_info=CloneImageInfo(image_info);
5022   if (*blob_info->magick == '\0')
5023     (void) SetImageInfo(blob_info,0,exception);
5024   magick_info=GetMagickInfo(blob_info->magick,exception);
5025   if (magick_info == (const MagickInfo *) NULL)
5026     {
5027       (void) ThrowMagickException(exception,GetMagickModule(),
5028         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
5029         blob_info->magick);
5030       blob_info=DestroyImageInfo(blob_info);
5031       return((Image *) NULL);
5032     }
5033   image=(Image *) NULL;
5034   if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
5035       (blob_info->custom_stream == (CustomStreamInfo *) NULL))
5036     {
5037       /*
5038         Native blob support for this image format or SetImageInfo changed the
5039         blob to a file.
5040       */
5041       image=ReadImage(blob_info,exception);
5042       if (image != (Image *) NULL)
5043         (void) CloseBlob(image);
5044     }
5045   else
5046     {
5047       char
5048         unique[MagickPathExtent];
5049
5050       int
5051         file;
5052
5053       ImageInfo
5054         *clone_info;
5055
5056       unsigned char
5057         *blob;
5058
5059       /*
5060         Write data to file on disk.
5061       */
5062       blob_info->custom_stream=(CustomStreamInfo *) NULL;
5063       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
5064         sizeof(*blob));
5065       if (blob == (unsigned char *) NULL)
5066         {
5067           ThrowFileException(exception,BlobError,"UnableToReadBlob",
5068             image_info->filename);
5069           blob_info=DestroyImageInfo(blob_info);
5070           return((Image *) NULL);
5071         }
5072       file=AcquireUniqueFileResource(unique);
5073       if (file == -1)
5074         {
5075           ThrowFileException(exception,BlobError,"UnableToReadBlob",
5076             image_info->filename);
5077           blob=(unsigned char *) RelinquishMagickMemory(blob);
5078           blob_info=DestroyImageInfo(blob_info);
5079           return((Image *) NULL);
5080         }
5081       clone_info=CloneImageInfo(blob_info);
5082       blob_info->file=fdopen(file,"wb+");
5083       if (blob_info->file != (FILE *) NULL)
5084         {
5085           ssize_t
5086             count;
5087
5088           count=(ssize_t) MagickMaxBufferExtent;
5089           while (count == (ssize_t) MagickMaxBufferExtent)
5090           {
5091             count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
5092               image_info->custom_stream->data);
5093             count=(ssize_t) write(file,(const char *) blob,count);
5094           }
5095           (void) fclose(blob_info->file);
5096           (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
5097             "%s:%s",blob_info->magick,unique);
5098           image=ReadImage(clone_info,exception);
5099           if (image != (Image *) NULL)
5100             {
5101               Image
5102                 *images;
5103
5104               /*
5105                 Restore original filenames and image format.
5106               */
5107               for (images=GetFirstImageInList(image); images != (Image *) NULL; )
5108               {
5109                 (void) CopyMagickString(images->filename,image_info->filename,
5110                   MagickPathExtent);
5111                 (void) CopyMagickString(images->magick_filename,
5112                   image_info->filename,MagickPathExtent);
5113                 (void) CopyMagickString(images->magick,magick_info->name,
5114                   MagickPathExtent);
5115                 (void) CloseBlob(images);
5116                 images=GetNextImageInList(images);
5117               }
5118             }
5119         }
5120       clone_info=DestroyImageInfo(clone_info);
5121       blob=(unsigned char *) RelinquishMagickMemory(blob);
5122       (void) RelinquishUniqueFileResource(unique);
5123     }
5124   blob_info=DestroyImageInfo(blob_info);
5125   return(image);
5126 }
5127 \f
5128 /*
5129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5130 %                                                                             %
5131 %                                                                             %
5132 %                                                                             %
5133 +  W r i t e B l o b                                                          %
5134 %                                                                             %
5135 %                                                                             %
5136 %                                                                             %
5137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5138 %
5139 %  WriteBlob() writes data to a blob or image file.  It returns the number of
5140 %  bytes written.
5141 %
5142 %  The format of the WriteBlob method is:
5143 %
5144 %      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5145 %
5146 %  A description of each parameter follows:
5147 %
5148 %    o image: the image.
5149 %
5150 %    o length:  Specifies an integer representing the number of bytes to
5151 %      write to the file.
5152 %
5153 %    o data:  The address of the data to write to the blob or file.
5154 %
5155 */
5156 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5157   const void *data)
5158 {
5159   int
5160     c;
5161
5162   register const unsigned char
5163     *p;
5164
5165   ssize_t
5166     count;
5167
5168   assert(image != (Image *) NULL);
5169   assert(image->signature == MagickCoreSignature);
5170   assert(data != (const void *) NULL);
5171   assert(image->blob != (BlobInfo *) NULL);
5172   assert(image->blob->type != UndefinedStream);
5173   if (length == 0)
5174     return(0);
5175   count=0;
5176   p=(const unsigned char *) data;
5177   switch (image->blob->type)
5178   {
5179     case UndefinedStream:
5180       break;
5181     case StandardStream:
5182     case FileStream:
5183     case PipeStream:
5184     {
5185       switch (length)
5186       {
5187         default:
5188         {
5189           count=(ssize_t) fwrite((const char *) data,1,length,
5190             image->blob->file_info.file);
5191           break;
5192         }
5193         case 4:
5194         {
5195           c=putc((int) *p++,image->blob->file_info.file);
5196           if (c == EOF)
5197             break;
5198           count++;
5199         }
5200         case 3:
5201         {
5202           c=putc((int) *p++,image->blob->file_info.file);
5203           if (c == EOF)
5204             break;
5205           count++;
5206         }
5207         case 2:
5208         {
5209           c=putc((int) *p++,image->blob->file_info.file);
5210           if (c == EOF)
5211             break;
5212           count++;
5213         }
5214         case 1:
5215         {
5216           c=putc((int) *p++,image->blob->file_info.file);
5217           if (c == EOF)
5218             break;
5219           count++;
5220         }
5221         case 0:
5222           break;
5223       }
5224       break;
5225     }
5226     case ZipStream:
5227     {
5228 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5229       switch (length)
5230       {
5231         default:
5232         {
5233           count=(ssize_t) gzwrite(image->blob->file_info.gzfile,(void *) data,
5234             (unsigned int) length);
5235           break;
5236         }
5237         case 4:
5238         {
5239           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5240           if (c == EOF)
5241             break;
5242           count++;
5243         }
5244         case 3:
5245         {
5246           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5247           if (c == EOF)
5248             break;
5249           count++;
5250         }
5251         case 2:
5252         {
5253           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5254           if (c == EOF)
5255             break;
5256           count++;
5257         }
5258         case 1:
5259         {
5260           c=gzputc(image->blob->file_info.gzfile,(int) *p++);
5261           if (c == EOF)
5262             break;
5263           count++;
5264         }
5265         case 0:
5266           break;
5267       }
5268 #endif
5269       break;
5270     }
5271     case BZipStream:
5272     {
5273 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5274       count=(ssize_t) BZ2_bzwrite(image->blob->file_info.bzfile,(void *) data,
5275         (int) length);
5276 #endif
5277       break;
5278     }
5279     case FifoStream:
5280     {
5281       count=(ssize_t) image->blob->stream(image,data,length);
5282       break;
5283     }
5284     case BlobStream:
5285     {
5286       register unsigned char
5287         *q;
5288
5289       if ((image->blob->offset+(MagickOffsetType) length) >=
5290           (MagickOffsetType) image->blob->extent)
5291         {
5292           if (image->blob->mapped != MagickFalse)
5293             return(0);
5294           image->blob->extent+=length+image->blob->quantum;
5295           image->blob->quantum<<=1;
5296           image->blob->data=(unsigned char *) ResizeQuantumMemory(
5297             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
5298           (void) SyncBlob(image);
5299           if (image->blob->data == (unsigned char *) NULL)
5300             {
5301               (void) DetachBlob(image->blob);
5302               return(0);
5303             }
5304         }
5305       q=image->blob->data+image->blob->offset;
5306       (void) memcpy(q,p,length);
5307       image->blob->offset+=length;
5308       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
5309         image->blob->length=(size_t) image->blob->offset;
5310       count=(ssize_t) length;
5311       break;
5312     }
5313     case CustomStream:
5314     {
5315       count=image->blob->custom_stream->writer((const unsigned char *) data,
5316         length,image->blob->custom_stream->data);
5317       break;
5318     }
5319   }
5320   return(count);
5321 }
5322 \f
5323 /*
5324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5325 %                                                                             %
5326 %                                                                             %
5327 %                                                                             %
5328 +  W r i t e B l o b B y t e                                                  %
5329 %                                                                             %
5330 %                                                                             %
5331 %                                                                             %
5332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5333 %
5334 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
5335 %  written (either 0 or 1);
5336 %
5337 %  The format of the WriteBlobByte method is:
5338 %
5339 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
5340 %
5341 %  A description of each parameter follows.
5342 %
5343 %    o image: the image.
5344 %
5345 %    o value: Specifies the value to write.
5346 %
5347 */
5348 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5349 {
5350   assert(image != (Image *) NULL);
5351   assert(image->signature == MagickCoreSignature);
5352   return(WriteBlobStream(image,1,&value));
5353 }
5354 \f
5355 /*
5356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5357 %                                                                             %
5358 %                                                                             %
5359 %                                                                             %
5360 +  W r i t e B l o b F l o a t                                                %
5361 %                                                                             %
5362 %                                                                             %
5363 %                                                                             %
5364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5365 %
5366 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5367 %  specified by the endian member of the image structure.
5368 %
5369 %  The format of the WriteBlobFloat method is:
5370 %
5371 %      ssize_t WriteBlobFloat(Image *image,const float value)
5372 %
5373 %  A description of each parameter follows.
5374 %
5375 %    o image: the image.
5376 %
5377 %    o value: Specifies the value to write.
5378 %
5379 */
5380 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5381 {
5382   union
5383   {
5384     unsigned int
5385       unsigned_value;
5386
5387     float
5388       float_value;
5389   } quantum;
5390
5391   quantum.unsigned_value=0U;
5392   quantum.float_value=value;
5393   return(WriteBlobLong(image,quantum.unsigned_value));
5394 }
5395 \f
5396 /*
5397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5398 %                                                                             %
5399 %                                                                             %
5400 %                                                                             %
5401 +  W r i t e B l o b L o n g                                                  %
5402 %                                                                             %
5403 %                                                                             %
5404 %                                                                             %
5405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5406 %
5407 %  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5408 %  byte-order specified by the endian member of the image structure.
5409 %
5410 %  The format of the WriteBlobLong method is:
5411 %
5412 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
5413 %
5414 %  A description of each parameter follows.
5415 %
5416 %    o image: the image.
5417 %
5418 %    o value: Specifies the value to write.
5419 %
5420 */
5421 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5422 {
5423   unsigned char
5424     buffer[4];
5425
5426   assert(image != (Image *) NULL);
5427   assert(image->signature == MagickCoreSignature);
5428   if (image->endian == LSBEndian)
5429     {
5430       buffer[0]=(unsigned char) value;
5431       buffer[1]=(unsigned char) (value >> 8);
5432       buffer[2]=(unsigned char) (value >> 16);
5433       buffer[3]=(unsigned char) (value >> 24);
5434       return(WriteBlobStream(image,4,buffer));
5435     }
5436   buffer[0]=(unsigned char) (value >> 24);
5437   buffer[1]=(unsigned char) (value >> 16);
5438   buffer[2]=(unsigned char) (value >> 8);
5439   buffer[3]=(unsigned char) value;
5440   return(WriteBlobStream(image,4,buffer));
5441 }
5442 \f
5443 /*
5444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5445 %                                                                             %
5446 %                                                                             %
5447 %                                                                             %
5448 +   W r i t e B l o b S h o r t                                               %
5449 %                                                                             %
5450 %                                                                             %
5451 %                                                                             %
5452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5453 %
5454 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
5455 %  byte-order specified by the endian member of the image structure.
5456 %
5457 %  The format of the WriteBlobShort method is:
5458 %
5459 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
5460 %
5461 %  A description of each parameter follows.
5462 %
5463 %    o image: the image.
5464 %
5465 %    o value:  Specifies the value to write.
5466 %
5467 */
5468 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5469 {
5470   unsigned char
5471     buffer[2];
5472
5473   assert(image != (Image *) NULL);
5474   assert(image->signature == MagickCoreSignature);
5475   if (image->endian == LSBEndian)
5476     {
5477       buffer[0]=(unsigned char) value;
5478       buffer[1]=(unsigned char) (value >> 8);
5479       return(WriteBlobStream(image,2,buffer));
5480     }
5481   buffer[0]=(unsigned char) (value >> 8);
5482   buffer[1]=(unsigned char) value;
5483   return(WriteBlobStream(image,2,buffer));
5484 }
5485 \f
5486 /*
5487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5488 %                                                                             %
5489 %                                                                             %
5490 %                                                                             %
5491 +  W r i t e B l o b L S B L o n g                                            %
5492 %                                                                             %
5493 %                                                                             %
5494 %                                                                             %
5495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5496 %
5497 %  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
5498 %  least-significant byte first order.
5499 %
5500 %  The format of the WriteBlobLSBLong method is:
5501 %
5502 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5503 %
5504 %  A description of each parameter follows.
5505 %
5506 %    o image: the image.
5507 %
5508 %    o value: Specifies the value to write.
5509 %
5510 */
5511 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5512 {
5513   unsigned char
5514     buffer[4];
5515
5516   assert(image != (Image *) NULL);
5517   assert(image->signature == MagickCoreSignature);
5518   buffer[0]=(unsigned char) value;
5519   buffer[1]=(unsigned char) (value >> 8);
5520   buffer[2]=(unsigned char) (value >> 16);
5521   buffer[3]=(unsigned char) (value >> 24);
5522   return(WriteBlobStream(image,4,buffer));
5523 }
5524 \f
5525 /*
5526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5527 %                                                                             %
5528 %                                                                             %
5529 %                                                                             %
5530 +   W r i t e B l o b L S B S h o r t                                         %
5531 %                                                                             %
5532 %                                                                             %
5533 %                                                                             %
5534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5535 %
5536 %  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
5537 %  least-significant byte first order.
5538 %
5539 %  The format of the WriteBlobLSBShort method is:
5540 %
5541 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5542 %
5543 %  A description of each parameter follows.
5544 %
5545 %    o image: the image.
5546 %
5547 %    o value:  Specifies the value to write.
5548 %
5549 */
5550 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5551 {
5552   unsigned char
5553     buffer[2];
5554
5555   assert(image != (Image *) NULL);
5556   assert(image->signature == MagickCoreSignature);
5557   buffer[0]=(unsigned char) value;
5558   buffer[1]=(unsigned char) (value >> 8);
5559   return(WriteBlobStream(image,2,buffer));
5560 }
5561 \f
5562 /*
5563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5564 %                                                                             %
5565 %                                                                             %
5566 %                                                                             %
5567 +  W r i t e B l o b L S B S i g n e d L o n g                                %
5568 %                                                                             %
5569 %                                                                             %
5570 %                                                                             %
5571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5572 %
5573 %  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
5574 %  least-significant byte first order.
5575 %
5576 %  The format of the WriteBlobLSBSignedLong method is:
5577 %
5578 %      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5579 %
5580 %  A description of each parameter follows.
5581 %
5582 %    o image: the image.
5583 %
5584 %    o value: Specifies the value to write.
5585 %
5586 */
5587 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5588 {
5589   union
5590   {
5591     unsigned int
5592       unsigned_value;
5593
5594     signed int
5595       signed_value;
5596   } quantum;
5597
5598   unsigned char
5599     buffer[4];
5600
5601   assert(image != (Image *) NULL);
5602   assert(image->signature == MagickCoreSignature);
5603   quantum.signed_value=value;
5604   buffer[0]=(unsigned char) quantum.unsigned_value;
5605   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5606   buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5607   buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5608   return(WriteBlobStream(image,4,buffer));
5609 }
5610 \f
5611 /*
5612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5613 %                                                                             %
5614 %                                                                             %
5615 %                                                                             %
5616 +   W r i t e B l o b L S B S i g n e d S h o r t                             %
5617 %                                                                             %
5618 %                                                                             %
5619 %                                                                             %
5620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5621 %
5622 %  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
5623 %  in least-significant byte first order.
5624 %
5625 %  The format of the WriteBlobLSBSignedShort method is:
5626 %
5627 %      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
5628 %
5629 %  A description of each parameter follows.
5630 %
5631 %    o image: the image.
5632 %
5633 %    o value:  Specifies the value to write.
5634 %
5635 */
5636 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
5637   const signed short value)
5638 {
5639   union
5640   {
5641     unsigned short
5642       unsigned_value;
5643
5644     signed short
5645       signed_value;
5646   } quantum;
5647
5648   unsigned char
5649     buffer[2];
5650
5651   assert(image != (Image *) NULL);
5652   assert(image->signature == MagickCoreSignature);
5653   quantum.signed_value=value;
5654   buffer[0]=(unsigned char) quantum.unsigned_value;
5655   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5656   return(WriteBlobStream(image,2,buffer));
5657 }
5658 \f
5659 /*
5660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5661 %                                                                             %
5662 %                                                                             %
5663 %                                                                             %
5664 +  W r i t e B l o b M S B L o n g                                            %
5665 %                                                                             %
5666 %                                                                             %
5667 %                                                                             %
5668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5669 %
5670 %  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
5671 %  most-significant byte first order.
5672 %
5673 %  The format of the WriteBlobMSBLong method is:
5674 %
5675 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5676 %
5677 %  A description of each parameter follows.
5678 %
5679 %    o value:  Specifies the value to write.
5680 %
5681 %    o image: the image.
5682 %
5683 */
5684 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5685 {
5686   unsigned char
5687     buffer[4];
5688
5689   assert(image != (Image *) NULL);
5690   assert(image->signature == MagickCoreSignature);
5691   buffer[0]=(unsigned char) (value >> 24);
5692   buffer[1]=(unsigned char) (value >> 16);
5693   buffer[2]=(unsigned char) (value >> 8);
5694   buffer[3]=(unsigned char) value;
5695   return(WriteBlobStream(image,4,buffer));
5696 }
5697 \f
5698 /*
5699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5700 %                                                                             %
5701 %                                                                             %
5702 %                                                                             %
5703 +  W r i t e B l o b M S B L o n g L o n g                                    %
5704 %                                                                             %
5705 %                                                                             %
5706 %                                                                             %
5707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5708 %
5709 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
5710 %  most-significant byte first order.
5711 %
5712 %  The format of the WriteBlobMSBLongLong method is:
5713 %
5714 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
5715 %
5716 %  A description of each parameter follows.
5717 %
5718 %    o value:  Specifies the value to write.
5719 %
5720 %    o image: the image.
5721 %
5722 */
5723 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
5724   const MagickSizeType value)
5725 {
5726   unsigned char
5727     buffer[8];
5728
5729   assert(image != (Image *) NULL);
5730   assert(image->signature == MagickCoreSignature);
5731   buffer[0]=(unsigned char) (value >> 56);
5732   buffer[1]=(unsigned char) (value >> 48);
5733   buffer[2]=(unsigned char) (value >> 40);
5734   buffer[3]=(unsigned char) (value >> 32);
5735   buffer[4]=(unsigned char) (value >> 24);
5736   buffer[5]=(unsigned char) (value >> 16);
5737   buffer[6]=(unsigned char) (value >> 8);
5738   buffer[7]=(unsigned char) value;
5739   return(WriteBlobStream(image,8,buffer));
5740 }
5741 \f
5742 /*
5743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5744 %                                                                             %
5745 %                                                                             %
5746 %                                                                             %
5747 +  W r i t e B l o b M S B S i g n e d L o n g                                %
5748 %                                                                             %
5749 %                                                                             %
5750 %                                                                             %
5751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5752 %
5753 %  WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
5754 %  most-significant byte first order.
5755 %
5756 %  The format of the WriteBlobMSBSignedLong method is:
5757 %
5758 %      ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5759 %
5760 %  A description of each parameter follows.
5761 %
5762 %    o image: the image.
5763 %
5764 %    o value: Specifies the value to write.
5765 %
5766 */
5767 MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5768 {
5769   union
5770   {
5771     unsigned int
5772       unsigned_value;
5773
5774     signed int
5775       signed_value;
5776   } quantum;
5777
5778   unsigned char
5779     buffer[4];
5780
5781   assert(image != (Image *) NULL);
5782   assert(image->signature == MagickCoreSignature);
5783   quantum.signed_value=value;
5784   buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5785   buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5786   buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5787   buffer[3]=(unsigned char) quantum.unsigned_value;
5788   return(WriteBlobStream(image,4,buffer));
5789 }
5790 \f
5791 /*
5792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5793 %                                                                             %
5794 %                                                                             %
5795 %                                                                             %
5796 +   W r i t e B l o b M S B S i g n e d S h o r t                             %
5797 %                                                                             %
5798 %                                                                             %
5799 %                                                                             %
5800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5801 %
5802 %  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5803 %  in most-significant byte first order.
5804 %
5805 %  The format of the WriteBlobMSBSignedShort method is:
5806 %
5807 %      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5808 %
5809 %  A description of each parameter follows.
5810 %
5811 %    o image: the image.
5812 %
5813 %    o value:  Specifies the value to write.
5814 %
5815 */
5816 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
5817   const signed short value)
5818 {
5819   union
5820   {
5821     unsigned short
5822       unsigned_value;
5823
5824     signed short
5825       signed_value;
5826   } quantum;
5827
5828   unsigned char
5829     buffer[2];
5830
5831   assert(image != (Image *) NULL);
5832   assert(image->signature == MagickCoreSignature);
5833   quantum.signed_value=value;
5834   buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5835   buffer[1]=(unsigned char) quantum.unsigned_value;
5836   return(WriteBlobStream(image,2,buffer));
5837 }
5838 \f
5839 /*
5840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5841 %                                                                             %
5842 %                                                                             %
5843 %                                                                             %
5844 +  W r i t e B l o b M S B S h o r t                                          %
5845 %                                                                             %
5846 %                                                                             %
5847 %                                                                             %
5848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5849 %
5850 %  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
5851 %  most-significant byte first order.
5852 %
5853 %  The format of the WriteBlobMSBShort method is:
5854 %
5855 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5856 %
5857 %  A description of each parameter follows.
5858 %
5859 %   o  value:  Specifies the value to write.
5860 %
5861 %   o  file:  Specifies the file to write the data to.
5862 %
5863 */
5864 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5865 {
5866   unsigned char
5867     buffer[2];
5868
5869   assert(image != (Image *) NULL);
5870   assert(image->signature == MagickCoreSignature);
5871   buffer[0]=(unsigned char) (value >> 8);
5872   buffer[1]=(unsigned char) value;
5873   return(WriteBlobStream(image,2,buffer));
5874 }
5875 \f
5876 /*
5877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5878 %                                                                             %
5879 %                                                                             %
5880 %                                                                             %
5881 +  W r i t e B l o b S t r i n g                                              %
5882 %                                                                             %
5883 %                                                                             %
5884 %                                                                             %
5885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5886 %
5887 %  WriteBlobString() write a string to a blob.  It returns the number of
5888 %  characters written.
5889 %
5890 %  The format of the WriteBlobString method is:
5891 %
5892 %      ssize_t WriteBlobString(Image *image,const char *string)
5893 %
5894 %  A description of each parameter follows.
5895 %
5896 %    o image: the image.
5897 %
5898 %    o string: Specifies the string to write.
5899 %
5900 */
5901 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
5902 {
5903   assert(image != (Image *) NULL);
5904   assert(image->signature == MagickCoreSignature);
5905   assert(string != (const char *) NULL);
5906   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
5907 }