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