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