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