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