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