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