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