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