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