]> 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   switch (image->blob->type)
2036   {
2037     case FileStream:
2038     case BlobStream:
2039     case ZipStream:
2040     {
2041       seekable=MagickTrue;
2042       break;
2043     }
2044     default:
2045     {
2046       seekable=MagickFalse;
2047       break;
2048     }
2049   }
2050   return(seekable);
2051 }
2052 \f
2053 /*
2054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2055 %                                                                             %
2056 %                                                                             %
2057 %                                                                             %
2058 +   I s B l o b T e m p o r a r y                                             %
2059 %                                                                             %
2060 %                                                                             %
2061 %                                                                             %
2062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2063 %
2064 %  IsBlobTemporary() returns true if the blob is temporary.
2065 %
2066 %  The format of the IsBlobTemporary method is:
2067 %
2068 %       MagickBooleanType IsBlobTemporary(const Image *image)
2069 %
2070 %  A description of each parameter follows:
2071 %
2072 %    o image: the image.
2073 %
2074 */
2075 MagickPrivate MagickBooleanType IsBlobTemporary(const Image *image)
2076 {
2077   assert(image != (const Image *) NULL);
2078   assert(image->signature == MagickSignature);
2079   if (image->debug != MagickFalse)
2080     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2081   return(image->blob->temporary);
2082 }
2083 \f
2084 /*
2085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086 %                                                                             %
2087 %                                                                             %
2088 %                                                                             %
2089 +  M a p B l o b                                                              %
2090 %                                                                             %
2091 %                                                                             %
2092 %                                                                             %
2093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2094 %
2095 %  MapBlob() creates a mapping from a file to a binary large object.
2096 %
2097 %  The format of the MapBlob method is:
2098 %
2099 %      unsigned char *MapBlob(int file,const MapMode mode,
2100 %        const MagickOffsetType offset,const size_t length)
2101 %
2102 %  A description of each parameter follows:
2103 %
2104 %    o file: map this file descriptor.
2105 %
2106 %    o mode: ReadMode, WriteMode, or IOMode.
2107 %
2108 %    o offset: starting at this offset within the file.
2109 %
2110 %    o length: the length of the mapping is returned in this pointer.
2111 %
2112 */
2113 MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2114   const MagickOffsetType offset,const size_t length)
2115 {
2116 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
2117   int
2118     flags,
2119     protection;
2120
2121   unsigned char
2122     *map;
2123
2124   /*
2125     Map file.
2126   */
2127   flags=0;
2128   if (file == -1)
2129 #if defined(MAP_ANONYMOUS)
2130     flags|=MAP_ANONYMOUS;
2131 #else
2132     return((unsigned char *) NULL);
2133 #endif
2134   switch (mode)
2135   {
2136     case ReadMode:
2137     default:
2138     {
2139       protection=PROT_READ;
2140       flags|=MAP_PRIVATE;
2141       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2142         (off_t) offset);
2143       break;
2144     }
2145     case WriteMode:
2146     {
2147       protection=PROT_WRITE;
2148       flags|=MAP_SHARED;
2149       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2150         (off_t) offset);
2151 #if defined(MAGICKCORE_HAVE_POSIX_MADVISE)
2152       (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL |
2153         POSIX_MADV_WILLNEED);
2154 #endif
2155       break;
2156     }
2157     case IOMode:
2158     {
2159       protection=PROT_READ | PROT_WRITE;
2160       flags|=MAP_SHARED;
2161       map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2162         (off_t) offset);
2163       break;
2164     }
2165   }
2166   if (map == (unsigned char *) MAP_FAILED)
2167     return((unsigned char *) NULL);
2168   return(map);
2169 #else
2170   (void) file;
2171   (void) mode;
2172   (void) offset;
2173   (void) length;
2174   return((unsigned char *) NULL);
2175 #endif
2176 }
2177 \f
2178 /*
2179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2180 %                                                                             %
2181 %                                                                             %
2182 %                                                                             %
2183 +  M S B O r d e r L o n g                                                    %
2184 %                                                                             %
2185 %                                                                             %
2186 %                                                                             %
2187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2188 %
2189 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
2190 %  most-significant byte first.
2191 %
2192 %  The format of the MSBOrderLong method is:
2193 %
2194 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
2195 %
2196 %  A description of each parameter follows.
2197 %
2198 %   o  buffer:  Specifies a pointer to a buffer of integers.
2199 %
2200 %   o  length:  Specifies the length of the buffer.
2201 %
2202 */
2203 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2204 {
2205   int
2206     c;
2207
2208   register unsigned char
2209     *p,
2210     *q;
2211
2212   assert(buffer != (unsigned char *) NULL);
2213   q=buffer+length;
2214   while (buffer < q)
2215   {
2216     p=buffer+3;
2217     c=(int) (*p);
2218     *p=(*buffer);
2219     *buffer++=(unsigned char) c;
2220     p=buffer+1;
2221     c=(int) (*p);
2222     *p=(*buffer);
2223     *buffer++=(unsigned char) c;
2224     buffer+=2;
2225   }
2226 }
2227 \f
2228 /*
2229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2230 %                                                                             %
2231 %                                                                             %
2232 %                                                                             %
2233 +  M S B O r d e r S h o r t                                                  %
2234 %                                                                             %
2235 %                                                                             %
2236 %                                                                             %
2237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2238 %
2239 %  MSBOrderShort() converts a least-significant byte first buffer of integers
2240 %  to most-significant byte first.
2241 %
2242 %  The format of the MSBOrderShort method is:
2243 %
2244 %      void MSBOrderShort(unsigned char *p,const size_t length)
2245 %
2246 %  A description of each parameter follows.
2247 %
2248 %   o  p:  Specifies a pointer to a buffer of integers.
2249 %
2250 %   o  length:  Specifies the length of the buffer.
2251 %
2252 */
2253 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2254 {
2255   int
2256     c;
2257
2258   register unsigned char
2259     *q;
2260
2261   assert(p != (unsigned char *) NULL);
2262   q=p+length;
2263   while (p < q)
2264   {
2265     c=(int) (*p);
2266     *p=(*(p+1));
2267     p++;
2268     *p++=(unsigned char) c;
2269   }
2270 }
2271 \f
2272 /*
2273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274 %                                                                             %
2275 %                                                                             %
2276 %                                                                             %
2277 +   O p e n B l o b                                                           %
2278 %                                                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282 %
2283 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
2284 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
2285 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2286 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
2287 %  from a system command.
2288 %
2289 %  The format of the OpenBlob method is:
2290 %
2291 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2292 %        const BlobMode mode,ExceptionInfo *exception)
2293 %
2294 %  A description of each parameter follows:
2295 %
2296 %    o image_info: the image info.
2297 %
2298 %    o image: the image.
2299 %
2300 %    o mode: the mode for opening the file.
2301 %
2302 */
2303 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2304   Image *image,const BlobMode mode,ExceptionInfo *exception)
2305 {
2306   char
2307     extension[MaxTextExtent],
2308     filename[MaxTextExtent];
2309
2310   const char
2311     *type;
2312
2313   MagickBooleanType
2314     status;
2315
2316   PolicyRights
2317     rights;
2318
2319   assert(image_info != (ImageInfo *) NULL);
2320   assert(image_info->signature == MagickSignature);
2321   if (image_info->debug != MagickFalse)
2322     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2323       image_info->filename);
2324   assert(image != (Image *) NULL);
2325   assert(image->signature == MagickSignature);
2326   if (image_info->blob != (void *) NULL)
2327     {
2328       if (image_info->stream != (StreamHandler) NULL)
2329         image->blob->stream=(StreamHandler) image_info->stream;
2330       AttachBlob(image->blob,image_info->blob,image_info->length);
2331       return(MagickTrue);
2332     }
2333   (void) DetachBlob(image->blob);
2334   switch (mode)
2335   {
2336     default: type="r"; break;
2337     case ReadBlobMode: type="r"; break;
2338     case ReadBinaryBlobMode: type="rb"; break;
2339     case WriteBlobMode: type="w"; break;
2340     case WriteBinaryBlobMode: type="w+b"; break;
2341     case AppendBlobMode: type="a"; break;
2342     case AppendBinaryBlobMode: type="a+b"; break;
2343   }
2344   if (*type != 'r')
2345     image->blob->synchronize=image_info->synchronize;
2346   if (image_info->stream != (StreamHandler) NULL)
2347     {
2348       image->blob->stream=(StreamHandler) image_info->stream;
2349       if (*type == 'w')
2350         {
2351           image->blob->type=FifoStream;
2352           return(MagickTrue);
2353         }
2354     }
2355   /*
2356     Open image file.
2357   */
2358   *filename='\0';
2359   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2360   rights=ReadPolicyRights;
2361   if (*type == 'w')
2362     rights=WritePolicyRights;
2363   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2364     {
2365       errno=EPERM;
2366       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2367         "NotAuthorized","`%s'",filename);
2368       return(MagickFalse);
2369     }
2370   if ((LocaleCompare(filename,"-") == 0) ||
2371       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2372     {
2373       image->blob->file=(*type == 'r') ? stdin : stdout;
2374 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2375       if (strchr(type,'b') != (char *) NULL)
2376         setmode(_fileno(image->blob->file),_O_BINARY);
2377 #endif
2378       image->blob->type=StandardStream;
2379       image->blob->exempt=MagickTrue;
2380       return(MagickTrue);
2381     }
2382   if (LocaleNCompare(filename,"fd:",3) == 0)
2383     {
2384       char
2385         mode[MaxTextExtent];
2386
2387       *mode=(*type);
2388       mode[1]='\0';
2389       image->blob->file=fdopen(StringToLong(filename+3),mode);
2390 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2391       if (strchr(type,'b') != (char *) NULL)
2392         setmode(_fileno(image->blob->file),_O_BINARY);
2393 #endif
2394       image->blob->type=StandardStream;
2395       image->blob->exempt=MagickTrue;
2396       return(MagickTrue);
2397     }
2398 #if defined(MAGICKCORE_HAVE_POPEN)
2399   if (*filename == '|')
2400     {
2401       char
2402         mode[MaxTextExtent];
2403
2404       /*
2405         Pipe image to or from a system command.
2406       */
2407 #if defined(SIGPIPE)
2408       if (*type == 'w')
2409         (void) signal(SIGPIPE,SIG_IGN);
2410 #endif
2411       *mode=(*type);
2412       mode[1]='\0';
2413       image->blob->file=(FILE *) popen_utf8(filename+1,mode);
2414       if (image->blob->file == (FILE *) NULL)
2415         {
2416           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2417           return(MagickFalse);
2418         }
2419       image->blob->type=PipeStream;
2420       image->blob->exempt=MagickTrue;
2421       return(MagickTrue);
2422     }
2423 #endif
2424   status=GetPathAttributes(filename,&image->blob->properties);
2425 #if defined(S_ISFIFO)
2426   if ((status == MagickTrue) && S_ISFIFO(image->blob->properties.st_mode))
2427     {
2428       image->blob->file=(FILE *) fopen_utf8(filename,type);
2429       if (image->blob->file == (FILE *) NULL)
2430         {
2431           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2432           return(MagickFalse);
2433         }
2434       image->blob->type=FileStream;
2435       image->blob->exempt=MagickTrue;
2436       return(MagickTrue);
2437     }
2438 #endif
2439   GetPathComponent(image->filename,ExtensionPath,extension);
2440   if (*type == 'w')
2441     {
2442       (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2443       if ((image_info->adjoin == MagickFalse) ||
2444           (strchr(filename,'%') != (char *) NULL))
2445         {
2446           /*
2447             Form filename for multi-part images.
2448           */
2449           (void) InterpretImageFilename(image_info,image,image->filename,(int)
2450             image->scene,filename,exception);
2451           if ((LocaleCompare(filename,image->filename) == 0) &&
2452               ((GetPreviousImageInList(image) != (Image *) NULL) ||
2453                (GetNextImageInList(image) != (Image *) NULL)))
2454             {
2455               char
2456                 path[MaxTextExtent];
2457
2458               GetPathComponent(image->filename,RootPath,path);
2459               if (*extension == '\0')
2460                 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g",
2461                   path,(double) image->scene);
2462               else
2463                 (void) FormatLocaleString(filename,MaxTextExtent,"%s-%.20g.%s",
2464                   path,(double) image->scene,extension);
2465             }
2466           (void) CopyMagickString(image->filename,filename,MaxTextExtent);
2467 #if defined(macintosh)
2468           SetApplicationType(filename,image_info->magick,'8BIM');
2469 #endif
2470         }
2471     }
2472   if (image_info->file != (FILE *) NULL)
2473     {
2474       image->blob->file=image_info->file;
2475       image->blob->type=FileStream;
2476       image->blob->exempt=MagickTrue;
2477     }
2478   else
2479     if (*type == 'r')
2480       {
2481         image->blob->file=(FILE *) fopen_utf8(filename,type);
2482         if (image->blob->file != (FILE *) NULL)
2483           {
2484             size_t
2485               count;
2486
2487             unsigned char
2488               magick[3];
2489
2490             image->blob->type=FileStream;
2491 #if defined(MAGICKCORE_HAVE_SETVBUF)
2492             (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,16384);
2493 #endif
2494             (void) ResetMagickMemory(magick,0,sizeof(magick));
2495             count=fread(magick,1,sizeof(magick),image->blob->file);
2496             (void) rewind(image->blob->file);
2497             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2498                "  read %.20g magic header bytes",(double) count);
2499 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2500             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2501                 ((int) magick[2] == 0x08))
2502               {
2503                 (void) fclose(image->blob->file);
2504                 image->blob->gzfile=gzopen(filename,type);
2505                 if (image->blob->gzfile != (gzFile) NULL)
2506                   image->blob->type=ZipStream;
2507                }
2508 #endif
2509 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2510             if (strncmp((char *) magick,"BZh",3) == 0)
2511               {
2512                 (void) fclose(image->blob->file);
2513                 image->blob->bzfile=BZ2_bzopen(filename,type);
2514                 if (image->blob->bzfile != (BZFILE *) NULL)
2515                   image->blob->type=BZipStream;
2516               }
2517 #endif
2518             if (image->blob->type == FileStream)
2519               {
2520                 const MagickInfo
2521                   *magick_info;
2522
2523                 ExceptionInfo
2524                   *sans_exception;
2525
2526                 struct stat
2527                   *properties;
2528
2529                 sans_exception=AcquireExceptionInfo();
2530                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
2531                 sans_exception=DestroyExceptionInfo(sans_exception);
2532                 properties=(&image->blob->properties);
2533                 if ((magick_info != (const MagickInfo *) NULL) &&
2534                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2535                     (properties->st_size <= MagickMaxBufferExtent))
2536                   {
2537                     size_t
2538                       length;
2539
2540                     void
2541                       *blob;
2542
2543                     length=(size_t) properties->st_size;
2544                     blob=MapBlob(fileno(image->blob->file),ReadMode,0,length);
2545                     if (blob != (void *) NULL)
2546                       {
2547                         /*
2548                           Format supports blobs-- use memory-mapped I/O.
2549                         */
2550                         if (image_info->file != (FILE *) NULL)
2551                           image->blob->exempt=MagickFalse;
2552                         else
2553                           {
2554                             (void) fclose(image->blob->file);
2555                             image->blob->file=(FILE *) NULL;
2556                           }
2557                         AttachBlob(image->blob,blob,length);
2558                         image->blob->mapped=MagickTrue;
2559                       }
2560                   }
2561               }
2562           }
2563         }
2564       else
2565 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2566         if ((LocaleCompare(extension,"Z") == 0) ||
2567             (LocaleCompare(extension,"gz") == 0) ||
2568             (LocaleCompare(extension,"wmz") == 0) ||
2569             (LocaleCompare(extension,"svgz") == 0))
2570           {
2571             if (mode == WriteBinaryBlobMode)
2572               type="wb";
2573             image->blob->gzfile=gzopen(filename,type);
2574             if (image->blob->gzfile != (gzFile) NULL)
2575               image->blob->type=ZipStream;
2576           }
2577         else
2578 #endif
2579 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2580           if (LocaleCompare(extension,"bz2") == 0)
2581             {
2582               image->blob->bzfile=BZ2_bzopen(filename,type);
2583               if (image->blob->bzfile != (BZFILE *) NULL)
2584                 image->blob->type=BZipStream;
2585             }
2586           else
2587 #endif
2588             {
2589               image->blob->file=(FILE *) fopen_utf8(filename,type);
2590               if (image->blob->file != (FILE *) NULL)
2591                 {
2592                   image->blob->type=FileStream;
2593 #if defined(MAGICKCORE_HAVE_SETVBUF)
2594                   (void) setvbuf(image->blob->file,(char *) NULL,(int) _IOFBF,
2595                     16384);
2596 #endif
2597                 }
2598        }
2599   image->blob->status=MagickFalse;
2600   if (image->blob->type != UndefinedStream)
2601     image->blob->size=GetBlobSize(image);
2602   else
2603     {
2604       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2605       return(MagickFalse);
2606     }
2607   return(MagickTrue);
2608 }
2609 \f
2610 /*
2611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2612 %                                                                             %
2613 %                                                                             %
2614 %                                                                             %
2615 +   P i n g B l o b                                                           %
2616 %                                                                             %
2617 %                                                                             %
2618 %                                                                             %
2619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2620 %
2621 %  PingBlob() returns all the attributes of an image or image sequence except
2622 %  for the pixels.  It is much faster and consumes far less memory than
2623 %  BlobToImage().  On failure, a NULL image is returned and exception
2624 %  describes the reason for the failure.
2625 %
2626 %  The format of the PingBlob method is:
2627 %
2628 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
2629 %        const size_t length,ExceptionInfo *exception)
2630 %
2631 %  A description of each parameter follows:
2632 %
2633 %    o image_info: the image info.
2634 %
2635 %    o blob: the address of a character stream in one of the image formats
2636 %      understood by ImageMagick.
2637 %
2638 %    o length: This size_t integer reflects the length in bytes of the blob.
2639 %
2640 %    o exception: return any errors or warnings in this structure.
2641 %
2642 */
2643
2644 #if defined(__cplusplus) || defined(c_plusplus)
2645 extern "C" {
2646 #endif
2647
2648 static size_t PingStream(const Image *magick_unused(image),
2649   const void *magick_unused(pixels),const size_t columns)
2650 {
2651   return(columns);
2652 }
2653
2654 #if defined(__cplusplus) || defined(c_plusplus)
2655 }
2656 #endif
2657
2658 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
2659   const size_t length,ExceptionInfo *exception)
2660 {
2661   Image
2662     *image;
2663
2664   ImageInfo
2665     *ping_info;
2666
2667   assert(image_info != (ImageInfo *) NULL);
2668   assert(image_info->signature == MagickSignature);
2669   if (image_info->debug != MagickFalse)
2670     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2671       image_info->filename);
2672   assert(exception != (ExceptionInfo *) NULL);
2673   if ((blob == (const void *) NULL) || (length == 0))
2674     {
2675       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
2676         "UnrecognizedImageFormat","`%s'",image_info->magick);
2677       return((Image *) NULL);
2678     }
2679   ping_info=CloneImageInfo(image_info);
2680   ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
2681   if (ping_info->blob == (const void *) NULL)
2682     {
2683       (void) ThrowMagickException(exception,GetMagickModule(),
2684         ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
2685       return((Image *) NULL);
2686     }
2687   (void) memcpy(ping_info->blob,blob,length);
2688   ping_info->length=length;
2689   ping_info->ping=MagickTrue;
2690   image=ReadStream(ping_info,&PingStream,exception);
2691   ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
2692   ping_info=DestroyImageInfo(ping_info);
2693   return(image);
2694 }
2695 \f
2696 /*
2697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2698 %                                                                             %
2699 %                                                                             %
2700 %                                                                             %
2701 +  R e a d B l o b                                                            %
2702 %                                                                             %
2703 %                                                                             %
2704 %                                                                             %
2705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2706 %
2707 %  ReadBlob() reads data from the blob or image file and returns it.  It
2708 %  returns the number of bytes read.
2709 %
2710 %  The format of the ReadBlob method is:
2711 %
2712 %      ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
2713 %
2714 %  A description of each parameter follows:
2715 %
2716 %    o image: the image.
2717 %
2718 %    o length:  Specifies an integer representing the number of bytes to read
2719 %      from the file.
2720 %
2721 %    o data:  Specifies an area to place the information requested from the
2722 %      file.
2723 %
2724 */
2725 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
2726   unsigned char *data)
2727 {
2728   int
2729     c;
2730
2731   register unsigned char
2732     *q;
2733
2734   ssize_t
2735     count;
2736
2737   assert(image != (Image *) NULL);
2738   assert(image->signature == MagickSignature);
2739   assert(image->blob != (BlobInfo *) NULL);
2740   assert(image->blob->type != UndefinedStream);
2741   if (length == 0)
2742     return(0);
2743   assert(data != (void *) NULL);
2744   count=0;
2745   q=data;
2746   switch (image->blob->type)
2747   {
2748     case UndefinedStream:
2749       break;
2750     case FileStream:
2751     case StandardStream:
2752     case PipeStream:
2753     {
2754       switch (length)
2755       {
2756         default:
2757         {
2758           count=(ssize_t) fread(q,1,length,image->blob->file);
2759           break;
2760         }
2761         case 2:
2762         {
2763           c=getc(image->blob->file);
2764           if (c == EOF)
2765             break;
2766           *q++=(unsigned char) c;
2767           count++;
2768         }
2769         case 1:
2770         {
2771           c=getc(image->blob->file);
2772           if (c == EOF)
2773             break;
2774           *q++=(unsigned char) c;
2775           count++;
2776         }
2777         case 0:
2778           break;
2779       }
2780       break;
2781     }
2782     case ZipStream:
2783     {
2784 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2785       switch (length)
2786       {
2787         default:
2788         {
2789           count=(ssize_t) gzread(image->blob->gzfile,q,(unsigned int) length);
2790           break;
2791         }
2792         case 2:
2793         {
2794           c=gzgetc(image->blob->gzfile);
2795           if (c == EOF)
2796             break;
2797           *q++=(unsigned char) c;
2798           count++;
2799         }
2800         case 1:
2801         {
2802           c=gzgetc(image->blob->gzfile);
2803           if (c == EOF)
2804             break;
2805           *q++=(unsigned char) c;
2806           count++;
2807         }
2808         case 0:
2809           break;
2810       }
2811 #endif
2812       break;
2813     }
2814     case BZipStream:
2815     {
2816 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2817       count=(ssize_t) BZ2_bzread(image->blob->bzfile,q,(int) length);
2818 #endif
2819       break;
2820     }
2821     case FifoStream:
2822       break;
2823     case BlobStream:
2824     {
2825       register const unsigned char
2826         *p;
2827
2828       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
2829         {
2830           image->blob->eof=MagickTrue;
2831           break;
2832         }
2833       p=image->blob->data+image->blob->offset;
2834       count=(ssize_t) MagickMin(length,image->blob->length-image->blob->offset);
2835       image->blob->offset+=count;
2836       if (count != (ssize_t) length)
2837         image->blob->eof=MagickTrue;
2838       (void) memcpy(q,p,(size_t) count);
2839       break;
2840     }
2841   }
2842   return(count);
2843 }
2844 \f
2845 /*
2846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2847 %                                                                             %
2848 %                                                                             %
2849 %                                                                             %
2850 +  R e a d B l o b B y t e                                                    %
2851 %                                                                             %
2852 %                                                                             %
2853 %                                                                             %
2854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2855 %
2856 %  ReadBlobByte() reads a single byte from the image file and returns it.
2857 %
2858 %  The format of the ReadBlobByte method is:
2859 %
2860 %      int ReadBlobByte(Image *image)
2861 %
2862 %  A description of each parameter follows.
2863 %
2864 %    o image: the image.
2865 %
2866 */
2867 MagickExport int ReadBlobByte(Image *image)
2868 {
2869   register const unsigned char
2870     *p;
2871
2872   ssize_t
2873     count;
2874
2875   unsigned char
2876     buffer[1];
2877
2878   assert(image != (Image *) NULL);
2879   assert(image->signature == MagickSignature);
2880   p=ReadBlobStream(image,1,buffer,&count);
2881   if (count != 1)
2882     return(EOF);
2883   return((int) (*p));
2884 }
2885 \f
2886 /*
2887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2888 %                                                                             %
2889 %                                                                             %
2890 %                                                                             %
2891 +  R e a d B l o b D o u b l e                                                %
2892 %                                                                             %
2893 %                                                                             %
2894 %                                                                             %
2895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2896 %
2897 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
2898 %  specified by the endian member of the image structure.
2899 %
2900 %  The format of the ReadBlobDouble method is:
2901 %
2902 %      double ReadBlobDouble(Image *image)
2903 %
2904 %  A description of each parameter follows.
2905 %
2906 %    o image: the image.
2907 %
2908 */
2909 MagickExport double ReadBlobDouble(Image *image)
2910 {
2911   union
2912   {
2913     MagickSizeType
2914       unsigned_value;
2915
2916     double
2917       double_value;
2918   } quantum;
2919
2920   quantum.double_value=0.0;
2921   quantum.unsigned_value=ReadBlobLongLong(image);
2922   return(quantum.double_value);
2923 }
2924 \f
2925 /*
2926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2927 %                                                                             %
2928 %                                                                             %
2929 %                                                                             %
2930 +  R e a d B l o b F l o a t                                                  %
2931 %                                                                             %
2932 %                                                                             %
2933 %                                                                             %
2934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2935 %
2936 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
2937 %  specified by the endian member of the image structure.
2938 %
2939 %  The format of the ReadBlobFloat method is:
2940 %
2941 %      float ReadBlobFloat(Image *image)
2942 %
2943 %  A description of each parameter follows.
2944 %
2945 %    o image: the image.
2946 %
2947 */
2948 MagickExport float ReadBlobFloat(Image *image)
2949 {
2950   union
2951   {
2952     unsigned int
2953       unsigned_value;
2954
2955     float
2956       float_value;
2957   } quantum;
2958
2959   quantum.float_value=0.0;
2960   quantum.unsigned_value=ReadBlobLong(image);
2961   return(quantum.float_value);
2962 }
2963 \f
2964 /*
2965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2966 %                                                                             %
2967 %                                                                             %
2968 %                                                                             %
2969 +  R e a d B l o b L o n g                                                    %
2970 %                                                                             %
2971 %                                                                             %
2972 %                                                                             %
2973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2974 %
2975 %  ReadBlobLong() reads a ssize_t value as a 32-bit quantity in the byte-order
2976 %  specified by the endian member of the image structure.
2977 %
2978 %  The format of the ReadBlobLong method is:
2979 %
2980 %      unsigned int ReadBlobLong(Image *image)
2981 %
2982 %  A description of each parameter follows.
2983 %
2984 %    o image: the image.
2985 %
2986 */
2987 MagickExport unsigned int ReadBlobLong(Image *image)
2988 {
2989   register const unsigned char
2990     *p;
2991
2992   ssize_t
2993     count;
2994
2995   unsigned char
2996     buffer[4];
2997
2998   unsigned int
2999     value;
3000
3001   assert(image != (Image *) NULL);
3002   assert(image->signature == MagickSignature);
3003   *buffer='\0';
3004   p=ReadBlobStream(image,4,buffer,&count);
3005   if (count != 4)
3006     return(0UL);
3007   if (image->endian == LSBEndian)
3008     {
3009       value=(unsigned int) (*p++);
3010       value|=((unsigned int) (*p++)) << 8;
3011       value|=((unsigned int) (*p++)) << 16;
3012       value|=((unsigned int) (*p++)) << 24;
3013       return(value);
3014     }
3015   value=((unsigned int) (*p++)) << 24;
3016   value|=((unsigned int) (*p++)) << 16;
3017   value|=((unsigned int) (*p++)) << 8;
3018   value|=((unsigned int) (*p++));
3019   return(value);
3020 }
3021 \f
3022 /*
3023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3024 %                                                                             %
3025 %                                                                             %
3026 %                                                                             %
3027 +  R e a d B l o b L o n g L o n g                                            %
3028 %                                                                             %
3029 %                                                                             %
3030 %                                                                             %
3031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3032 %
3033 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3034 %  byte-order specified by the endian member of the image structure.
3035 %
3036 %  The format of the ReadBlobLongLong method is:
3037 %
3038 %      MagickSizeType ReadBlobLongLong(Image *image)
3039 %
3040 %  A description of each parameter follows.
3041 %
3042 %    o image: the image.
3043 %
3044 */
3045 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3046 {
3047   MagickSizeType
3048     value;
3049
3050   register const unsigned char
3051     *p;
3052
3053   ssize_t
3054     count;
3055
3056   unsigned char
3057     buffer[8];
3058
3059   assert(image != (Image *) NULL);
3060   assert(image->signature == MagickSignature);
3061   *buffer='\0';
3062   p=ReadBlobStream(image,8,buffer,&count);
3063   if (count != 8)
3064     return(MagickULLConstant(0));
3065   if (image->endian == LSBEndian)
3066     {
3067       value=(MagickSizeType) (*p++);
3068       value|=((MagickSizeType) (*p++)) << 8;
3069       value|=((MagickSizeType) (*p++)) << 16;
3070       value|=((MagickSizeType) (*p++)) << 24;
3071       value|=((MagickSizeType) (*p++)) << 32;
3072       value|=((MagickSizeType) (*p++)) << 40;
3073       value|=((MagickSizeType) (*p++)) << 48;
3074       value|=((MagickSizeType) (*p++)) << 56;
3075       return(value & MagickULLConstant(0xffffffffffffffff));
3076     }
3077   value=((MagickSizeType) (*p++)) << 56;
3078   value|=((MagickSizeType) (*p++)) << 48;
3079   value|=((MagickSizeType) (*p++)) << 40;
3080   value|=((MagickSizeType) (*p++)) << 32;
3081   value|=((MagickSizeType) (*p++)) << 24;
3082   value|=((MagickSizeType) (*p++)) << 16;
3083   value|=((MagickSizeType) (*p++)) << 8;
3084   value|=((MagickSizeType) (*p++));
3085   return(value & MagickULLConstant(0xffffffffffffffff));
3086 }
3087 \f
3088 /*
3089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3090 %                                                                             %
3091 %                                                                             %
3092 %                                                                             %
3093 +  R e a d B l o b S h o r t                                                  %
3094 %                                                                             %
3095 %                                                                             %
3096 %                                                                             %
3097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3098 %
3099 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3100 %  specified by the endian member of the image structure.
3101 %
3102 %  The format of the ReadBlobShort method is:
3103 %
3104 %      unsigned short ReadBlobShort(Image *image)
3105 %
3106 %  A description of each parameter follows.
3107 %
3108 %    o image: the image.
3109 %
3110 */
3111 MagickExport unsigned short ReadBlobShort(Image *image)
3112 {
3113   register const unsigned char
3114     *p;
3115
3116   register unsigned int
3117     value;
3118
3119   ssize_t
3120     count;
3121
3122   unsigned char
3123     buffer[2];
3124
3125   assert(image != (Image *) NULL);
3126   assert(image->signature == MagickSignature);
3127   *buffer='\0';
3128   p=ReadBlobStream(image,2,buffer,&count);
3129   if (count != 2)
3130     return((unsigned short) 0U);
3131   if (image->endian == LSBEndian)
3132     {
3133       value=(unsigned int) (*p++);
3134       value|=((unsigned int) (*p++)) << 8;
3135       return((unsigned short) (value & 0xffff));
3136     }
3137   value=(unsigned int) ((*p++) << 8);
3138   value|=(unsigned int) (*p++);
3139   return((unsigned short) (value & 0xffff));
3140 }
3141 \f
3142 /*
3143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3144 %                                                                             %
3145 %                                                                             %
3146 %                                                                             %
3147 +  R e a d B l o b L S B L o n g                                              %
3148 %                                                                             %
3149 %                                                                             %
3150 %                                                                             %
3151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3152 %
3153 %  ReadBlobLSBLong() reads a ssize_t value as a 32-bit quantity in
3154 %  least-significant byte first order.
3155 %
3156 %  The format of the ReadBlobLSBLong method is:
3157 %
3158 %      unsigned int ReadBlobLSBLong(Image *image)
3159 %
3160 %  A description of each parameter follows.
3161 %
3162 %    o image: the image.
3163 %
3164 */
3165 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3166 {
3167   register const unsigned char
3168     *p;
3169
3170   register unsigned int
3171     value;
3172
3173   ssize_t
3174     count;
3175
3176   unsigned char
3177     buffer[4];
3178
3179   assert(image != (Image *) NULL);
3180   assert(image->signature == MagickSignature);
3181   *buffer='\0';
3182   p=ReadBlobStream(image,4,buffer,&count);
3183   if (count != 4)
3184     return(0U);
3185   value=(unsigned int) (*p++);
3186   value|=((unsigned int) (*p++)) << 8;
3187   value|=((unsigned int) (*p++)) << 16;
3188   value|=((unsigned int) (*p++)) << 24;
3189   return(value);
3190 }
3191 \f
3192 /*
3193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3194 %                                                                             %
3195 %                                                                             %
3196 %                                                                             %
3197 +  R e a d B l o b L S B S h o r t                                            %
3198 %                                                                             %
3199 %                                                                             %
3200 %                                                                             %
3201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3202 %
3203 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3204 %  least-significant byte first order.
3205 %
3206 %  The format of the ReadBlobLSBShort method is:
3207 %
3208 %      unsigned short ReadBlobLSBShort(Image *image)
3209 %
3210 %  A description of each parameter follows.
3211 %
3212 %    o image: the image.
3213 %
3214 */
3215 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3216 {
3217   register const unsigned char
3218     *p;
3219
3220   register unsigned int
3221     value;
3222
3223   ssize_t
3224     count;
3225
3226   unsigned char
3227     buffer[2];
3228
3229   assert(image != (Image *) NULL);
3230   assert(image->signature == MagickSignature);
3231   *buffer='\0';
3232   p=ReadBlobStream(image,2,buffer,&count);
3233   if (count != 2)
3234     return((unsigned short) 0U);
3235   value=(unsigned int) (*p++);
3236   value|=((unsigned int) ((*p++)) << 8);
3237   return((unsigned short) (value & 0xffff));
3238 }
3239 \f
3240 /*
3241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3242 %                                                                             %
3243 %                                                                             %
3244 %                                                                             %
3245 +  R e a d B l o b M S B L o n g                                              %
3246 %                                                                             %
3247 %                                                                             %
3248 %                                                                             %
3249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3250 %
3251 %  ReadBlobMSBLong() reads a ssize_t value as a 32-bit quantity in
3252 %  most-significant byte first order.
3253 %
3254 %  The format of the ReadBlobMSBLong method is:
3255 %
3256 %      unsigned int ReadBlobMSBLong(Image *image)
3257 %
3258 %  A description of each parameter follows.
3259 %
3260 %    o image: the image.
3261 %
3262 */
3263 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3264 {
3265   register const unsigned char
3266     *p;
3267
3268   register unsigned int
3269     value;
3270
3271   ssize_t
3272     count;
3273
3274   unsigned char
3275     buffer[4];
3276
3277   assert(image != (Image *) NULL);
3278   assert(image->signature == MagickSignature);
3279   *buffer='\0';
3280   p=ReadBlobStream(image,4,buffer,&count);
3281   if (count != 4)
3282     return(0UL);
3283   value=((unsigned int) (*p++) << 24);
3284   value|=((unsigned int) (*p++) << 16);
3285   value|=((unsigned int) (*p++) << 8);
3286   value|=(unsigned int) (*p++);
3287   return(value);
3288 }
3289 \f
3290 /*
3291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3292 %                                                                             %
3293 %                                                                             %
3294 %                                                                             %
3295 +  R e a d B l o b M S B L o n g L o n g                                      %
3296 %                                                                             %
3297 %                                                                             %
3298 %                                                                             %
3299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3300 %
3301 %  ReadBlobMSBLongLong() reads a ssize_t value as a 64-bit quantity in
3302 %  most-significant byte first order.
3303 %
3304 %  The format of the ReadBlobMSBLongLong method is:
3305 %
3306 %      unsigned int ReadBlobMSBLongLong(Image *image)
3307 %
3308 %  A description of each parameter follows.
3309 %
3310 %    o image: the image.
3311 %
3312 */
3313 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3314 {
3315   register const unsigned char
3316     *p;
3317
3318   register MagickSizeType
3319     value;
3320
3321   ssize_t
3322     count;
3323
3324   unsigned char
3325     buffer[8];
3326
3327   assert(image != (Image *) NULL);
3328   assert(image->signature == MagickSignature);
3329   *buffer='\0';
3330   p=ReadBlobStream(image,8,buffer,&count);
3331   if (count != 8)
3332     return(MagickULLConstant(0));
3333   value=((MagickSizeType) (*p++)) << 56;
3334   value|=((MagickSizeType) (*p++)) << 48;
3335   value|=((MagickSizeType) (*p++)) << 40;
3336   value|=((MagickSizeType) (*p++)) << 32;
3337   value|=((MagickSizeType) (*p++)) << 24;
3338   value|=((MagickSizeType) (*p++)) << 16;
3339   value|=((MagickSizeType) (*p++)) << 8;
3340   value|=((MagickSizeType) (*p++));
3341   return(value & MagickULLConstant(0xffffffffffffffff));
3342 }
3343 \f
3344 /*
3345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3346 %                                                                             %
3347 %                                                                             %
3348 %                                                                             %
3349 +  R e a d B l o b M S B S h o r t                                            %
3350 %                                                                             %
3351 %                                                                             %
3352 %                                                                             %
3353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3354 %
3355 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3356 %  most-significant byte first order.
3357 %
3358 %  The format of the ReadBlobMSBShort method is:
3359 %
3360 %      unsigned short ReadBlobMSBShort(Image *image)
3361 %
3362 %  A description of each parameter follows.
3363 %
3364 %    o image: the image.
3365 %
3366 */
3367 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3368 {
3369   register const unsigned char
3370     *p;
3371
3372   register unsigned int
3373     value;
3374
3375   ssize_t
3376     count;
3377
3378   unsigned char
3379     buffer[2];
3380
3381   assert(image != (Image *) NULL);
3382   assert(image->signature == MagickSignature);
3383   *buffer='\0';
3384   p=ReadBlobStream(image,2,buffer,&count);
3385   if (count != 2)
3386     return((unsigned short) 0U);
3387   value=(unsigned int) ((*p++) << 8);
3388   value|=(unsigned int) (*p++);
3389   return((unsigned short) (value & 0xffff));
3390 }
3391 \f
3392 /*
3393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3394 %                                                                             %
3395 %                                                                             %
3396 %                                                                             %
3397 +   R e a d B l o b S t r i n g                                               %
3398 %                                                                             %
3399 %                                                                             %
3400 %                                                                             %
3401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3402 %
3403 %  ReadBlobString() reads characters from a blob or file until a newline
3404 %  character is read or an end-of-file condition is encountered.
3405 %
3406 %  The format of the ReadBlobString method is:
3407 %
3408 %      char *ReadBlobString(Image *image,char *string)
3409 %
3410 %  A description of each parameter follows:
3411 %
3412 %    o image: the image.
3413 %
3414 %    o string: the address of a character buffer.
3415 %
3416 */
3417 MagickExport char *ReadBlobString(Image *image,char *string)
3418 {
3419   register const unsigned char
3420     *p;
3421
3422   register ssize_t
3423     i;
3424
3425   ssize_t
3426     count;
3427
3428   unsigned char
3429     buffer[1];
3430
3431   assert(image != (Image *) NULL);
3432   assert(image->signature == MagickSignature);
3433   for (i=0; i < (MaxTextExtent-1L); i++)
3434   {
3435     p=ReadBlobStream(image,1,buffer,&count);
3436     if (count != 1)
3437       {
3438         if (i == 0)
3439           return((char *) NULL);
3440         break;
3441       }
3442     string[i]=(char) (*p);
3443     if ((string[i] == '\r') || (string[i] == '\n'))
3444       break;
3445   }
3446   if (string[i] == '\r')
3447     (void) ReadBlobStream(image,1,buffer,&count);
3448   string[i]='\0';
3449   return(string);
3450 }
3451 \f
3452 /*
3453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3454 %                                                                             %
3455 %                                                                             %
3456 %                                                                             %
3457 +   R e f e r e n c e B l o b                                                 %
3458 %                                                                             %
3459 %                                                                             %
3460 %                                                                             %
3461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3462 %
3463 %  ReferenceBlob() increments the reference count associated with the pixel
3464 %  blob returning a pointer to the blob.
3465 %
3466 %  The format of the ReferenceBlob method is:
3467 %
3468 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
3469 %
3470 %  A description of each parameter follows:
3471 %
3472 %    o blob_info: the blob_info.
3473 %
3474 */
3475 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
3476 {
3477   assert(blob != (BlobInfo *) NULL);
3478   assert(blob->signature == MagickSignature);
3479   if (blob->debug != MagickFalse)
3480     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3481   LockSemaphoreInfo(blob->semaphore);
3482   blob->reference_count++;
3483   UnlockSemaphoreInfo(blob->semaphore);
3484   return(blob);
3485 }
3486 \f
3487 /*
3488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3489 %                                                                             %
3490 %                                                                             %
3491 %                                                                             %
3492 +  S e e k B l o b                                                            %
3493 %                                                                             %
3494 %                                                                             %
3495 %                                                                             %
3496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3497 %
3498 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
3499 %  and returns the resulting offset.
3500 %
3501 %  The format of the SeekBlob method is:
3502 %
3503 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
3504 %        const int whence)
3505 %
3506 %  A description of each parameter follows:
3507 %
3508 %    o image: the image.
3509 %
3510 %    o offset:  Specifies an integer representing the offset in bytes.
3511 %
3512 %    o whence:  Specifies an integer representing how the offset is
3513 %      treated relative to the beginning of the blob as follows:
3514 %
3515 %        SEEK_SET  Set position equal to offset bytes.
3516 %        SEEK_CUR  Set position to current location plus offset.
3517 %        SEEK_END  Set position to EOF plus offset.
3518 %
3519 */
3520 MagickExport MagickOffsetType SeekBlob(Image *image,
3521   const MagickOffsetType offset,const int whence)
3522 {
3523   assert(image != (Image *) NULL);
3524   assert(image->signature == MagickSignature);
3525   if (image->debug != MagickFalse)
3526     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3527   assert(image->blob != (BlobInfo *) NULL);
3528   assert(image->blob->type != UndefinedStream);
3529   switch (image->blob->type)
3530   {
3531     case UndefinedStream:
3532       break;
3533     case FileStream:
3534     {
3535       if (fseek(image->blob->file,offset,whence) < 0)
3536         return(-1);
3537       image->blob->offset=TellBlob(image);
3538       break;
3539     }
3540     case StandardStream:
3541     case PipeStream:
3542     case ZipStream:
3543     {
3544 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3545       if (gzseek(image->blob->gzfile,(off_t) offset,whence) < 0)
3546         return(-1);
3547 #endif
3548       image->blob->offset=TellBlob(image);
3549       break;
3550     }
3551     case BZipStream:
3552       return(-1);
3553     case FifoStream:
3554       return(-1);
3555     case BlobStream:
3556     {
3557       switch (whence)
3558       {
3559         case SEEK_SET:
3560         default:
3561         {
3562           if (offset < 0)
3563             return(-1);
3564           image->blob->offset=offset;
3565           break;
3566         }
3567         case SEEK_CUR:
3568         {
3569           if ((image->blob->offset+offset) < 0)
3570             return(-1);
3571           image->blob->offset+=offset;
3572           break;
3573         }
3574         case SEEK_END:
3575         {
3576           if (((MagickOffsetType) image->blob->length+offset) < 0)
3577             return(-1);
3578           image->blob->offset=image->blob->length+offset;
3579           break;
3580         }
3581       }
3582       if (image->blob->offset <= (MagickOffsetType)
3583           ((off_t) image->blob->length))
3584         image->blob->eof=MagickFalse;
3585       else
3586         if (image->blob->mapped != MagickFalse)
3587           return(-1);
3588         else
3589           {
3590             image->blob->extent=(size_t) (image->blob->offset+
3591               image->blob->quantum);
3592             image->blob->data=(unsigned char *) ResizeQuantumMemory(
3593               image->blob->data,image->blob->extent+1,
3594               sizeof(*image->blob->data));
3595             (void) SyncBlob(image);
3596             if (image->blob->data == (unsigned char *) NULL)
3597               {
3598                 (void) DetachBlob(image->blob);
3599                 return(-1);
3600               }
3601           }
3602       break;
3603     }
3604   }
3605   return(image->blob->offset);
3606 }
3607 \f
3608 /*
3609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3610 %                                                                             %
3611 %                                                                             %
3612 %                                                                             %
3613 +   S e t B l o b E x e m p t                                                 %
3614 %                                                                             %
3615 %                                                                             %
3616 %                                                                             %
3617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618 %
3619 %  SetBlobExempt() sets the blob exempt status.
3620 %
3621 %  The format of the SetBlobExempt method is:
3622 %
3623 %      MagickBooleanType SetBlobExempt(const Image *image,
3624 %        const MagickBooleanType exempt)
3625 %
3626 %  A description of each parameter follows:
3627 %
3628 %    o image: the image.
3629 %
3630 %    o exempt: Set to true if this blob is exempt from being closed.
3631 %
3632 */
3633 MagickPrivate void SetBlobExempt(Image *image,const MagickBooleanType exempt)
3634 {
3635   assert(image != (const Image *) NULL);
3636   assert(image->signature == MagickSignature);
3637   if (image->debug != MagickFalse)
3638     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3639   image->blob->exempt=exempt;
3640 }
3641 \f
3642 /*
3643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3644 %                                                                             %
3645 %                                                                             %
3646 %                                                                             %
3647 +  S e t B l o b E x t e n t                                                  %
3648 %                                                                             %
3649 %                                                                             %
3650 %                                                                             %
3651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652 %
3653 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
3654 %  method is successful, subsequent writes to bytes in the specified range are
3655 %  guaranteed not to fail.
3656 %
3657 %  The format of the SetBlobExtent method is:
3658 %
3659 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
3660 %
3661 %  A description of each parameter follows:
3662 %
3663 %    o image: the image.
3664 %
3665 %    o extent:  the blob maximum extent.
3666 %
3667 */
3668 MagickPrivate MagickBooleanType SetBlobExtent(Image *image,
3669   const MagickSizeType extent)
3670 {
3671   assert(image != (Image *) NULL);
3672   assert(image->signature == MagickSignature);
3673   if (image->debug != MagickFalse)
3674     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3675   assert(image->blob != (BlobInfo *) NULL);
3676   assert(image->blob->type != UndefinedStream);
3677   switch (image->blob->type)
3678   {
3679     case UndefinedStream:
3680       break;
3681     case FileStream:
3682     {
3683       if (extent != (MagickSizeType) ((off_t) extent))
3684         return(MagickFalse);
3685 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
3686         return(MagickFalse);
3687 #else
3688       {
3689         int
3690           status;
3691
3692         MagickOffsetType
3693           offset;
3694
3695         offset=TellBlob(image);
3696         status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3697           (off_t) (extent-offset));
3698         if (status != 0)
3699           return(MagickFalse);
3700       }
3701 #endif
3702       break;
3703     }
3704     case StandardStream:
3705     case PipeStream:
3706     case ZipStream:
3707       return(MagickFalse);
3708     case BZipStream:
3709       return(MagickFalse);
3710     case FifoStream:
3711       return(MagickFalse);
3712     case BlobStream:
3713     {
3714       if (image->blob->mapped != MagickFalse)
3715         {
3716           if (image->blob->file == (FILE *) NULL)
3717             return(MagickFalse);
3718           (void) UnmapBlob(image->blob->data,image->blob->length);
3719 #if !defined(MAGICKCORE_POSIX_FALLOCATE)
3720           return(MagickFalse);
3721 #else
3722           {
3723             int
3724               status;
3725
3726             MagickOffsetType
3727               offset;
3728
3729             offset=TellBlob(image);
3730             status=posix_fallocate(fileno(image->blob->file),(off_t) offset,
3731               (off_t) (extent-offset));
3732             if (status != 0)
3733               return(MagickFalse);
3734           }
3735           image->blob->data=(unsigned char*) MapBlob(fileno(image->blob->file),
3736             WriteMode,0,(size_t) extent);
3737           image->blob->extent=(size_t) extent;
3738           image->blob->length=(size_t) extent;
3739           (void) SyncBlob(image);
3740           break;
3741 #endif
3742         }
3743       if (extent != (MagickSizeType) ((size_t) extent))
3744         return(MagickFalse);
3745       image->blob->extent=(size_t) extent;
3746       image->blob->data=(unsigned char *) ResizeQuantumMemory(image->blob->data,
3747         image->blob->extent+1,sizeof(*image->blob->data));
3748       (void) SyncBlob(image);
3749       if (image->blob->data == (unsigned char *) NULL)
3750         {
3751           (void) DetachBlob(image->blob);
3752           return(MagickFalse);
3753         }
3754       break;
3755     }
3756   }
3757   return(MagickTrue);
3758 }
3759 \f
3760 /*
3761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3762 %                                                                             %
3763 %                                                                             %
3764 %                                                                             %
3765 +  S y n c B l o b                                                            %
3766 %                                                                             %
3767 %                                                                             %
3768 %                                                                             %
3769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3770 %
3771 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
3772 %  attributes if it is an blob.
3773 %
3774 %  The format of the SyncBlob method is:
3775 %
3776 %      int SyncBlob(Image *image)
3777 %
3778 %  A description of each parameter follows:
3779 %
3780 %    o image: the image.
3781 %
3782 */
3783 static int SyncBlob(Image *image)
3784 {
3785   int
3786     status;
3787
3788   assert(image != (Image *) NULL);
3789   assert(image->signature == MagickSignature);
3790   if (image->debug != MagickFalse)
3791     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3792   assert(image->blob != (BlobInfo *) NULL);
3793   assert(image->blob->type != UndefinedStream);
3794   status=0;
3795   switch (image->blob->type)
3796   {
3797     case UndefinedStream:
3798       break;
3799     case FileStream:
3800     case StandardStream:
3801     case PipeStream:
3802     {
3803       status=fflush(image->blob->file);
3804       break;
3805     }
3806     case ZipStream:
3807     {
3808 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3809       status=gzflush(image->blob->gzfile,Z_SYNC_FLUSH);
3810 #endif
3811       break;
3812     }
3813     case BZipStream:
3814     {
3815 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3816       status=BZ2_bzflush(image->blob->bzfile);
3817 #endif
3818       break;
3819     }
3820     case FifoStream:
3821       break;
3822     case BlobStream:
3823     {
3824 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3825       if (image->blob->mapped != MagickFalse)
3826         status=msync(image->blob->data,image->blob->length,MS_SYNC);
3827 #endif
3828       break;
3829     }
3830   }
3831   return(status);
3832 }
3833 \f
3834 /*
3835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836 %                                                                             %
3837 %                                                                             %
3838 %                                                                             %
3839 +  T e l l B l o b                                                            %
3840 %                                                                             %
3841 %                                                                             %
3842 %                                                                             %
3843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3844 %
3845 %  TellBlob() obtains the current value of the blob or file position.
3846 %
3847 %  The format of the TellBlob method is:
3848 %
3849 %      MagickOffsetType TellBlob(const Image *image)
3850 %
3851 %  A description of each parameter follows:
3852 %
3853 %    o image: the image.
3854 %
3855 */
3856 MagickExport MagickOffsetType TellBlob(const Image *image)
3857 {
3858   MagickOffsetType
3859     offset;
3860
3861   assert(image != (Image *) NULL);
3862   assert(image->signature == MagickSignature);
3863   if (image->debug != MagickFalse)
3864     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3865   assert(image->blob != (BlobInfo *) NULL);
3866   assert(image->blob->type != UndefinedStream);
3867   offset=(-1);
3868   switch (image->blob->type)
3869   {
3870     case UndefinedStream:
3871       break;
3872     case FileStream:
3873     {
3874       offset=ftell(image->blob->file);
3875       break;
3876     }
3877     case StandardStream:
3878     case PipeStream:
3879       break;
3880     case ZipStream:
3881     {
3882 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3883       offset=(MagickOffsetType) gztell(image->blob->gzfile);
3884 #endif
3885       break;
3886     }
3887     case BZipStream:
3888       break;
3889     case FifoStream:
3890       break;
3891     case BlobStream:
3892     {
3893       offset=image->blob->offset;
3894       break;
3895     }
3896   }
3897   return(offset);
3898 }
3899 \f
3900 /*
3901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3902 %                                                                             %
3903 %                                                                             %
3904 %                                                                             %
3905 +  U n m a p B l o b                                                          %
3906 %                                                                             %
3907 %                                                                             %
3908 %                                                                             %
3909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3910 %
3911 %  UnmapBlob() deallocates the binary large object previously allocated with
3912 %  the MapBlob method.
3913 %
3914 %  The format of the UnmapBlob method is:
3915 %
3916 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
3917 %
3918 %  A description of each parameter follows:
3919 %
3920 %    o map: the address  of the binary large object.
3921 %
3922 %    o length: the length of the binary large object.
3923 %
3924 */
3925 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
3926 {
3927 #if defined(MAGICKCORE_HAVE_MMAP_FILEIO)
3928   int
3929     status;
3930
3931   status=munmap(map,length);
3932   return(status == -1 ? MagickFalse : MagickTrue);
3933 #else
3934   (void) map;
3935   (void) length;
3936   return(MagickFalse);
3937 #endif
3938 }
3939 \f
3940 /*
3941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3942 %                                                                             %
3943 %                                                                             %
3944 %                                                                             %
3945 +  W r i t e B l o b                                                          %
3946 %                                                                             %
3947 %                                                                             %
3948 %                                                                             %
3949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3950 %
3951 %  WriteBlob() writes data to a blob or image file.  It returns the number of
3952 %  bytes written.
3953 %
3954 %  The format of the WriteBlob method is:
3955 %
3956 %      ssize_t WriteBlob(Image *image,const size_t length,
3957 %        const unsigned char *data)
3958 %
3959 %  A description of each parameter follows:
3960 %
3961 %    o image: the image.
3962 %
3963 %    o length:  Specifies an integer representing the number of bytes to
3964 %      write to the file.
3965 %
3966 %    o data:  The address of the data to write to the blob or file.
3967 %
3968 */
3969 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
3970   const unsigned char *data)
3971 {
3972   int
3973     c;
3974
3975   register const unsigned char
3976     *p;
3977
3978   ssize_t
3979     count;
3980
3981   assert(image != (Image *) NULL);
3982   assert(image->signature == MagickSignature);
3983   assert(data != (const unsigned char *) NULL);
3984   assert(image->blob != (BlobInfo *) NULL);
3985   assert(image->blob->type != UndefinedStream);
3986   if (length == 0)
3987     return(0);
3988   count=0;
3989   p=data;
3990   switch (image->blob->type)
3991   {
3992     case UndefinedStream:
3993       break;
3994     case FileStream:
3995     case StandardStream:
3996     case PipeStream:
3997     {
3998       switch (length)
3999       {
4000         default:
4001         {
4002           count=(ssize_t) fwrite((const char *) data,1,length,
4003             image->blob->file);
4004           break;
4005         }
4006         case 2:
4007         {
4008           c=putc((int) *p++,image->blob->file);
4009           if (c == EOF)
4010             break;
4011           count++;
4012         }
4013         case 1:
4014         {
4015           c=putc((int) *p++,image->blob->file);
4016           if (c == EOF)
4017             break;
4018           count++;
4019         }
4020         case 0:
4021           break;
4022       }
4023       break;
4024     }
4025     case ZipStream:
4026     {
4027 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4028       switch (length)
4029       {
4030         default:
4031         {
4032           count=(ssize_t) gzwrite(image->blob->gzfile,(void *) data,
4033             (unsigned int) length);
4034           break;
4035         }
4036         case 2:
4037         {
4038           c=gzputc(image->blob->gzfile,(int) *p++);
4039           if (c == EOF)
4040             break;
4041           count++;
4042         }
4043         case 1:
4044         {
4045           c=gzputc(image->blob->gzfile,(int) *p++);
4046           if (c == EOF)
4047             break;
4048           count++;
4049         }
4050         case 0:
4051           break;
4052       }
4053 #endif
4054       break;
4055     }
4056     case BZipStream:
4057     {
4058 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4059       count=(ssize_t) BZ2_bzwrite(image->blob->bzfile,(void *) data,(int)
4060         length);
4061 #endif
4062       break;
4063     }
4064     case FifoStream:
4065     {
4066       count=(ssize_t) image->blob->stream(image,data,length);
4067       break;
4068     }
4069     case BlobStream:
4070     {
4071       register unsigned char
4072         *q;
4073
4074       if ((image->blob->offset+(MagickOffsetType) length) >=
4075           (MagickOffsetType) image->blob->extent)
4076         {
4077           if (image->blob->mapped != MagickFalse)
4078             return(0);
4079           image->blob->quantum<<=1;
4080           image->blob->extent+=length+image->blob->quantum;
4081           image->blob->data=(unsigned char *) ResizeQuantumMemory(
4082             image->blob->data,image->blob->extent+1,sizeof(*image->blob->data));
4083           (void) SyncBlob(image);
4084           if (image->blob->data == (unsigned char *) NULL)
4085             {
4086               (void) DetachBlob(image->blob);
4087               return(0);
4088             }
4089         }
4090       q=image->blob->data+image->blob->offset;
4091       (void) memcpy(q,p,length);
4092       image->blob->offset+=length;
4093       if (image->blob->offset >= (MagickOffsetType) image->blob->length)
4094         image->blob->length=(size_t) image->blob->offset;
4095       count=(ssize_t) length;
4096     }
4097   }
4098   return(count);
4099 }
4100 \f
4101 /*
4102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4103 %                                                                             %
4104 %                                                                             %
4105 %                                                                             %
4106 +  W r i t e B l o b B y t e                                                  %
4107 %                                                                             %
4108 %                                                                             %
4109 %                                                                             %
4110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4111 %
4112 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
4113 %  written (either 0 or 1);
4114 %
4115 %  The format of the WriteBlobByte method is:
4116 %
4117 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
4118 %
4119 %  A description of each parameter follows.
4120 %
4121 %    o image: the image.
4122 %
4123 %    o value: Specifies the value to write.
4124 %
4125 */
4126 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
4127 {
4128   assert(image != (Image *) NULL);
4129   assert(image->signature == MagickSignature);
4130   return(WriteBlobStream(image,1,&value));
4131 }
4132 \f
4133 /*
4134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4135 %                                                                             %
4136 %                                                                             %
4137 %                                                                             %
4138 +  W r i t e B l o b F l o a t                                                %
4139 %                                                                             %
4140 %                                                                             %
4141 %                                                                             %
4142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4143 %
4144 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
4145 %  specified by the endian member of the image structure.
4146 %
4147 %  The format of the WriteBlobFloat method is:
4148 %
4149 %      ssize_t WriteBlobFloat(Image *image,const float value)
4150 %
4151 %  A description of each parameter follows.
4152 %
4153 %    o image: the image.
4154 %
4155 %    o value: Specifies the value to write.
4156 %
4157 */
4158 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
4159 {
4160   union
4161   {
4162     unsigned int
4163       unsigned_value;
4164
4165     float
4166       float_value;
4167   } quantum;
4168
4169   quantum.unsigned_value=0U;
4170   quantum.float_value=value;
4171   return(WriteBlobLong(image,quantum.unsigned_value));
4172 }
4173 \f
4174 /*
4175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4176 %                                                                             %
4177 %                                                                             %
4178 %                                                                             %
4179 +  W r i t e B l o b L o n g                                                  %
4180 %                                                                             %
4181 %                                                                             %
4182 %                                                                             %
4183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4184 %
4185 %  WriteBlobLong() writes a ssize_t value as a 32-bit quantity in the byte-order
4186 %  specified by the endian member of the image structure.
4187 %
4188 %  The format of the WriteBlobLong method is:
4189 %
4190 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
4191 %
4192 %  A description of each parameter follows.
4193 %
4194 %    o image: the image.
4195 %
4196 %    o value: Specifies the value to write.
4197 %
4198 */
4199 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
4200 {
4201   unsigned char
4202     buffer[4];
4203
4204   assert(image != (Image *) NULL);
4205   assert(image->signature == MagickSignature);
4206   if (image->endian == LSBEndian)
4207     {
4208       buffer[0]=(unsigned char) value;
4209       buffer[1]=(unsigned char) (value >> 8);
4210       buffer[2]=(unsigned char) (value >> 16);
4211       buffer[3]=(unsigned char) (value >> 24);
4212       return(WriteBlobStream(image,4,buffer));
4213     }
4214   buffer[0]=(unsigned char) (value >> 24);
4215   buffer[1]=(unsigned char) (value >> 16);
4216   buffer[2]=(unsigned char) (value >> 8);
4217   buffer[3]=(unsigned char) value;
4218   return(WriteBlobStream(image,4,buffer));
4219 }
4220 \f
4221 /*
4222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4223 %                                                                             %
4224 %                                                                             %
4225 %                                                                             %
4226 +   W r i t e B l o b S h o r t                                               %
4227 %                                                                             %
4228 %                                                                             %
4229 %                                                                             %
4230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4231 %
4232 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
4233 %  byte-order specified by the endian member of the image structure.
4234 %
4235 %  The format of the WriteBlobShort method is:
4236 %
4237 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
4238 %
4239 %  A description of each parameter follows.
4240 %
4241 %    o image: the image.
4242 %
4243 %    o value:  Specifies the value to write.
4244 %
4245 */
4246 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
4247 {
4248   unsigned char
4249     buffer[2];
4250
4251   assert(image != (Image *) NULL);
4252   assert(image->signature == MagickSignature);
4253   if (image->endian == LSBEndian)
4254     {
4255       buffer[0]=(unsigned char) value;
4256       buffer[1]=(unsigned char) (value >> 8);
4257       return(WriteBlobStream(image,2,buffer));
4258     }
4259   buffer[0]=(unsigned char) (value >> 8);
4260   buffer[1]=(unsigned char) value;
4261   return(WriteBlobStream(image,2,buffer));
4262 }
4263 \f
4264 /*
4265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4266 %                                                                             %
4267 %                                                                             %
4268 %                                                                             %
4269 +  W r i t e B l o b L S B L o n g                                            %
4270 %                                                                             %
4271 %                                                                             %
4272 %                                                                             %
4273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4274 %
4275 %  WriteBlobLSBLong() writes a ssize_t value as a 32-bit quantity in
4276 %  least-significant byte first order.
4277 %
4278 %  The format of the WriteBlobLSBLong method is:
4279 %
4280 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4281 %
4282 %  A description of each parameter follows.
4283 %
4284 %    o image: the image.
4285 %
4286 %    o value: Specifies the value to write.
4287 %
4288 */
4289 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
4290 {
4291   unsigned char
4292     buffer[4];
4293
4294   assert(image != (Image *) NULL);
4295   assert(image->signature == MagickSignature);
4296   buffer[0]=(unsigned char) value;
4297   buffer[1]=(unsigned char) (value >> 8);
4298   buffer[2]=(unsigned char) (value >> 16);
4299   buffer[3]=(unsigned char) (value >> 24);
4300   return(WriteBlobStream(image,4,buffer));
4301 }
4302 \f
4303 /*
4304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4305 %                                                                             %
4306 %                                                                             %
4307 %                                                                             %
4308 +   W r i t e B l o b L S B S h o r t                                         %
4309 %                                                                             %
4310 %                                                                             %
4311 %                                                                             %
4312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4313 %
4314 %  WriteBlobLSBShort() writes a ssize_t value as a 16-bit quantity in
4315 %  least-significant byte first order.
4316 %
4317 %  The format of the WriteBlobLSBShort method is:
4318 %
4319 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4320 %
4321 %  A description of each parameter follows.
4322 %
4323 %    o image: the image.
4324 %
4325 %    o value:  Specifies the value to write.
4326 %
4327 */
4328 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
4329 {
4330   unsigned char
4331     buffer[2];
4332
4333   assert(image != (Image *) NULL);
4334   assert(image->signature == MagickSignature);
4335   buffer[0]=(unsigned char) value;
4336   buffer[1]=(unsigned char) (value >> 8);
4337   return(WriteBlobStream(image,2,buffer));
4338 }
4339 \f
4340 /*
4341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4342 %                                                                             %
4343 %                                                                             %
4344 %                                                                             %
4345 +  W r i t e B l o b M S B L o n g                                            %
4346 %                                                                             %
4347 %                                                                             %
4348 %                                                                             %
4349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4350 %
4351 %  WriteBlobMSBLong() writes a ssize_t value as a 32-bit quantity in
4352 %  most-significant byte first order.
4353 %
4354 %  The format of the WriteBlobMSBLong method is:
4355 %
4356 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4357 %
4358 %  A description of each parameter follows.
4359 %
4360 %    o value:  Specifies the value to write.
4361 %
4362 %    o image: the image.
4363 %
4364 */
4365 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
4366 {
4367   unsigned char
4368     buffer[4];
4369
4370   assert(image != (Image *) NULL);
4371   assert(image->signature == MagickSignature);
4372   buffer[0]=(unsigned char) (value >> 24);
4373   buffer[1]=(unsigned char) (value >> 16);
4374   buffer[2]=(unsigned char) (value >> 8);
4375   buffer[3]=(unsigned char) value;
4376   return(WriteBlobStream(image,4,buffer));
4377 }
4378 \f
4379 /*
4380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4381 %                                                                             %
4382 %                                                                             %
4383 %                                                                             %
4384 +  W r i t e B l o b M S B L o n g L o n g                                    %
4385 %                                                                             %
4386 %                                                                             %
4387 %                                                                             %
4388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4389 %
4390 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
4391 %  most-significant byte first order.
4392 %
4393 %  The format of the WriteBlobMSBLongLong method is:
4394 %
4395 %      ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
4396 %
4397 %  A description of each parameter follows.
4398 %
4399 %    o value:  Specifies the value to write.
4400 %
4401 %    o image: the image.
4402 %
4403 */
4404 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
4405   const MagickSizeType value)
4406 {
4407   unsigned char
4408     buffer[8];
4409
4410   assert(image != (Image *) NULL);
4411   assert(image->signature == MagickSignature);
4412   buffer[0]=(unsigned char) (value >> 56);
4413   buffer[1]=(unsigned char) (value >> 48);
4414   buffer[2]=(unsigned char) (value >> 40);
4415   buffer[3]=(unsigned char) (value >> 32);
4416   buffer[4]=(unsigned char) (value >> 24);
4417   buffer[5]=(unsigned char) (value >> 16);
4418   buffer[6]=(unsigned char) (value >> 8);
4419   buffer[7]=(unsigned char) value;
4420   return(WriteBlobStream(image,8,buffer));
4421 }
4422 \f
4423 /*
4424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4425 %                                                                             %
4426 %                                                                             %
4427 %                                                                             %
4428 +  W r i t e B l o b M S B S h o r t                                          %
4429 %                                                                             %
4430 %                                                                             %
4431 %                                                                             %
4432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4433 %
4434 %  WriteBlobMSBShort() writes a ssize_t value as a 16-bit quantity in
4435 %  most-significant byte first order.
4436 %
4437 %  The format of the WriteBlobMSBShort method is:
4438 %
4439 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4440 %
4441 %  A description of each parameter follows.
4442 %
4443 %   o  value:  Specifies the value to write.
4444 %
4445 %   o  file:  Specifies the file to write the data to.
4446 %
4447 */
4448 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
4449 {
4450   unsigned char
4451     buffer[2];
4452
4453   assert(image != (Image *) NULL);
4454   assert(image->signature == MagickSignature);
4455   buffer[0]=(unsigned char) (value >> 8);
4456   buffer[1]=(unsigned char) value;
4457   return(WriteBlobStream(image,2,buffer));
4458 }
4459 \f
4460 /*
4461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4462 %                                                                             %
4463 %                                                                             %
4464 %                                                                             %
4465 +  W r i t e B l o b S t r i n g                                              %
4466 %                                                                             %
4467 %                                                                             %
4468 %                                                                             %
4469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4470 %
4471 %  WriteBlobString() write a string to a blob.  It returns the number of
4472 %  characters written.
4473 %
4474 %  The format of the WriteBlobString method is:
4475 %
4476 %      ssize_t WriteBlobString(Image *image,const char *string)
4477 %
4478 %  A description of each parameter follows.
4479 %
4480 %    o image: the image.
4481 %
4482 %    o string: Specifies the string to write.
4483 %
4484 */
4485 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
4486 {
4487   assert(image != (Image *) NULL);
4488   assert(image->signature == MagickSignature);
4489   assert(string != (const char *) NULL);
4490   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
4491 }