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