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