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