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