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