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