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