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