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