• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2020 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 %    https://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 
40 /*
41   Include declarations.
42 */
43 #ifdef __VMS
44 #include  <types.h>
45 #include  <mman.h>
46 #endif
47 #include "MagickCore/studio.h"
48 #include "MagickCore/blob.h"
49 #include "MagickCore/blob-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/delegate.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image-private.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/locale_.h"
60 #include "MagickCore/log.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/memory-private.h"
64 #include "MagickCore/nt-base-private.h"
65 #include "MagickCore/option.h"
66 #include "MagickCore/policy.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/semaphore.h"
69 #include "MagickCore/string_.h"
70 #include "MagickCore/string-private.h"
71 #include "MagickCore/timer-private.h"
72 #include "MagickCore/token.h"
73 #include "MagickCore/utility.h"
74 #include "MagickCore/utility-private.h"
75 #if defined(MAGICKCORE_ZLIB_DELEGATE)
76 #include "zlib.h"
77 #endif
78 #if defined(MAGICKCORE_BZLIB_DELEGATE)
79 #include "bzlib.h"
80 #endif
81 
82 /*
83   Define declarations.
84 */
85 #define MagickMaxBlobExtent  (8*8192)
86 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
87 # define MAP_ANONYMOUS  MAP_ANON
88 #endif
89 #if !defined(MAP_FAILED)
90 #define MAP_FAILED  ((void *) -1)
91 #endif
92 #if defined(__OS2__)
93 #include <io.h>
94 #define _O_BINARY O_BINARY
95 #endif
96 
97 /*
98   Typedef declarations.
99 */
100 typedef union FileInfo
101 {
102   FILE
103     *file;
104 
105 #if defined(MAGICKCORE_ZLIB_DELEGATE)
106   gzFile
107     gzfile;
108 #endif
109 
110 #if defined(MAGICKCORE_BZLIB_DELEGATE)
111   BZFILE
112     *bzfile;
113 #endif
114 } FileInfo;
115 
116 struct _BlobInfo
117 {
118   size_t
119     length,
120     extent,
121     quantum;
122 
123   BlobMode
124     mode;
125 
126   MagickBooleanType
127     mapped,
128     eof;
129 
130   int
131     error;
132 
133   MagickOffsetType
134     offset;
135 
136   MagickSizeType
137     size;
138 
139   MagickBooleanType
140     exempt,
141     synchronize,
142     status,
143     temporary;
144 
145   StreamType
146     type;
147 
148   FileInfo
149     file_info;
150 
151   struct stat
152     properties;
153 
154   StreamHandler
155     stream;
156 
157   CustomStreamInfo
158     *custom_stream;
159 
160   unsigned char
161     *data;
162 
163   MagickBooleanType
164     debug;
165 
166   SemaphoreInfo
167     *semaphore;
168 
169   ssize_t
170     reference_count;
171 
172   size_t
173     signature;
174 };
175 
176 struct _CustomStreamInfo
177 {
178   CustomStreamHandler
179     reader,
180     writer;
181 
182   CustomStreamSeeker
183     seeker;
184 
185   CustomStreamTeller
186     teller;
187 
188   void
189     *data;
190 
191   size_t
192     signature;
193 };
194 
195 /*
196   Forward declarations.
197 */
198 static int
199   SyncBlob(Image *);
200 
201 /*
202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203 %                                                                             %
204 %                                                                             %
205 %                                                                             %
206 +   A c q u i r e C u s t o m S t r e a m I n f o                             %
207 %                                                                             %
208 %                                                                             %
209 %                                                                             %
210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211 %
212 %  AcquireCustomStreamInfo() allocates the CustomStreamInfo structure.
213 %
214 %  The format of the AcquireCustomStreamInfo method is:
215 %
216 %      CustomStreamInfo *AcquireCustomStreamInfo(ExceptionInfo *exception)
217 %
218 %  A description of each parameter follows:
219 %
220 %    o exception: return any errors or warnings in this structure.
221 %
222 */
AcquireCustomStreamInfo(ExceptionInfo * magick_unused (exception))223 MagickExport CustomStreamInfo *AcquireCustomStreamInfo(
224   ExceptionInfo *magick_unused(exception))
225 {
226   CustomStreamInfo
227     *custom_stream;
228 
229   magick_unreferenced(exception);
230   custom_stream=(CustomStreamInfo *) AcquireCriticalMemory(
231     sizeof(*custom_stream));
232   (void) memset(custom_stream,0,sizeof(*custom_stream));
233   custom_stream->signature=MagickCoreSignature;
234   return(custom_stream);
235 }
236 
237 /*
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 %                                                                             %
240 %                                                                             %
241 %                                                                             %
242 +   A t t a c h B l o b                                                       %
243 %                                                                             %
244 %                                                                             %
245 %                                                                             %
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 %
248 %  AttachBlob() attaches a blob to the BlobInfo structure.
249 %
250 %  The format of the AttachBlob method is:
251 %
252 %      void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length)
253 %
254 %  A description of each parameter follows:
255 %
256 %    o blob_info: Specifies a pointer to a BlobInfo structure.
257 %
258 %    o blob: the address of a character stream in one of the image formats
259 %      understood by ImageMagick.
260 %
261 %    o length: This size_t integer reflects the length in bytes of the blob.
262 %
263 */
AttachBlob(BlobInfo * blob_info,const void * blob,const size_t length)264 MagickExport void AttachBlob(BlobInfo *blob_info,const void *blob,
265   const size_t length)
266 {
267   assert(blob_info != (BlobInfo *) NULL);
268   if (blob_info->debug != MagickFalse)
269     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
270   blob_info->length=length;
271   blob_info->extent=length;
272   blob_info->quantum=(size_t) MagickMaxBlobExtent;
273   blob_info->offset=0;
274   blob_info->type=BlobStream;
275   blob_info->file_info.file=(FILE *) NULL;
276   blob_info->data=(unsigned char *) blob;
277   blob_info->mapped=MagickFalse;
278 }
279 
280 /*
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 %                                                                             %
283 %                                                                             %
284 %                                                                             %
285 +   A t t a c h C u s t o m S t r e a m                                       %
286 %                                                                             %
287 %                                                                             %
288 %                                                                             %
289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290 %
291 %  AttachCustomStream() attaches a CustomStreamInfo to the BlobInfo structure.
292 %
293 %  The format of the AttachCustomStream method is:
294 %
295 %      void AttachCustomStream(BlobInfo *blob_info,
296 %        CustomStreamInfo *custom_stream)
297 %
298 %  A description of each parameter follows:
299 %
300 %    o blob_info: specifies a pointer to a BlobInfo structure.
301 %
302 %    o custom_stream: the custom stream info.
303 %
304 */
AttachCustomStream(BlobInfo * blob_info,CustomStreamInfo * custom_stream)305 MagickExport void AttachCustomStream(BlobInfo *blob_info,
306   CustomStreamInfo *custom_stream)
307 {
308   assert(blob_info != (BlobInfo *) NULL);
309   assert(custom_stream != (CustomStreamInfo *) NULL);
310   assert(custom_stream->signature == MagickCoreSignature);
311   if (blob_info->debug != MagickFalse)
312     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
313   blob_info->type=CustomStream;
314   blob_info->custom_stream=custom_stream;
315 }
316 
317 /*
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 %                                                                             %
320 %                                                                             %
321 %                                                                             %
322 +   B l o b T o F i l e                                                       %
323 %                                                                             %
324 %                                                                             %
325 %                                                                             %
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 %
328 %  BlobToFile() writes a blob to a file.  It returns MagickFalse if an error
329 %  occurs otherwise MagickTrue.
330 %
331 %  The format of the BlobToFile method is:
332 %
333 %       MagickBooleanType BlobToFile(char *filename,const void *blob,
334 %         const size_t length,ExceptionInfo *exception)
335 %
336 %  A description of each parameter follows:
337 %
338 %    o filename: Write the blob to this file.
339 %
340 %    o blob: the address of a blob.
341 %
342 %    o length: This length in bytes of the blob.
343 %
344 %    o exception: return any errors or warnings in this structure.
345 %
346 */
BlobToFile(char * filename,const void * blob,const size_t length,ExceptionInfo * exception)347 MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
348   const size_t length,ExceptionInfo *exception)
349 {
350   int
351     file;
352 
353   register size_t
354     i;
355 
356   ssize_t
357     count;
358 
359   assert(filename != (const char *) NULL);
360   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
361   assert(blob != (const void *) NULL);
362   if (*filename == '\0')
363     file=AcquireUniqueFileResource(filename);
364   else
365     file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
366   if (file == -1)
367     {
368       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
369       return(MagickFalse);
370     }
371   for (i=0; i < length; i+=count)
372   {
373     count=write(file,(const char *) blob+i,MagickMin(length-i,(size_t)
374       SSIZE_MAX));
375     if (count <= 0)
376       {
377         count=0;
378         if (errno != EINTR)
379           break;
380       }
381   }
382   file=close(file);
383   if ((file == -1) || (i < length))
384     {
385       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
386       return(MagickFalse);
387     }
388   return(MagickTrue);
389 }
390 
391 /*
392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393 %                                                                             %
394 %                                                                             %
395 %                                                                             %
396 %   B l o b T o I m a g e                                                     %
397 %                                                                             %
398 %                                                                             %
399 %                                                                             %
400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401 %
402 %  BlobToImage() implements direct to memory image formats.  It returns the
403 %  blob as an image.
404 %
405 %  The format of the BlobToImage method is:
406 %
407 %      Image *BlobToImage(const ImageInfo *image_info,const void *blob,
408 %        const size_t length,ExceptionInfo *exception)
409 %
410 %  A description of each parameter follows:
411 %
412 %    o image_info: the image info.
413 %
414 %    o blob: the address of a character stream in one of the image formats
415 %      understood by ImageMagick.
416 %
417 %    o length: This size_t integer reflects the length in bytes of the blob.
418 %
419 %    o exception: return any errors or warnings in this structure.
420 %
421 */
BlobToImage(const ImageInfo * image_info,const void * blob,const size_t length,ExceptionInfo * exception)422 MagickExport Image *BlobToImage(const ImageInfo *image_info,const void *blob,
423   const size_t length,ExceptionInfo *exception)
424 {
425   const MagickInfo
426     *magick_info;
427 
428   Image
429     *image;
430 
431   ImageInfo
432     *blob_info,
433     *clone_info;
434 
435   MagickBooleanType
436     status;
437 
438   assert(image_info != (ImageInfo *) NULL);
439   assert(image_info->signature == MagickCoreSignature);
440   if (image_info->debug != MagickFalse)
441     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
442       image_info->filename);
443   assert(exception != (ExceptionInfo *) NULL);
444   if ((blob == (const void *) NULL) || (length == 0))
445     {
446       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
447         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
448       return((Image *) NULL);
449     }
450   blob_info=CloneImageInfo(image_info);
451   blob_info->blob=(void *) blob;
452   blob_info->length=length;
453   if (*blob_info->magick == '\0')
454     (void) SetImageInfo(blob_info,0,exception);
455   magick_info=GetMagickInfo(blob_info->magick,exception);
456   if (magick_info == (const MagickInfo *) NULL)
457     {
458       (void) ThrowMagickException(exception,GetMagickModule(),
459         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
460         blob_info->magick);
461       blob_info=DestroyImageInfo(blob_info);
462       return((Image *) NULL);
463     }
464   if (GetMagickBlobSupport(magick_info) != MagickFalse)
465     {
466       char
467         filename[MagickPathExtent];
468 
469       /*
470         Native blob support for this image format.
471       */
472       (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
473       (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
474         blob_info->magick,filename);
475       image=ReadImage(blob_info,exception);
476       if (image != (Image *) NULL)
477         (void) DetachBlob(image->blob);
478       blob_info=DestroyImageInfo(blob_info);
479       return(image);
480     }
481   /*
482     Write blob to a temporary file on disk.
483   */
484   blob_info->blob=(void *) NULL;
485   blob_info->length=0;
486   *blob_info->filename='\0';
487   status=BlobToFile(blob_info->filename,blob,length,exception);
488   if (status == MagickFalse)
489     {
490       (void) RelinquishUniqueFileResource(blob_info->filename);
491       blob_info=DestroyImageInfo(blob_info);
492       return((Image *) NULL);
493     }
494   clone_info=CloneImageInfo(blob_info);
495   (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
496     blob_info->magick,blob_info->filename);
497   image=ReadImage(clone_info,exception);
498   if (image != (Image *) NULL)
499     {
500       Image
501         *images;
502 
503       /*
504         Restore original filenames and image format.
505       */
506       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
507       {
508         (void) CopyMagickString(images->filename,image_info->filename,
509           MagickPathExtent);
510         (void) CopyMagickString(images->magick_filename,image_info->filename,
511           MagickPathExtent);
512         (void) CopyMagickString(images->magick,magick_info->name,
513           MagickPathExtent);
514         images=GetNextImageInList(images);
515       }
516     }
517   clone_info=DestroyImageInfo(clone_info);
518   (void) RelinquishUniqueFileResource(blob_info->filename);
519   blob_info=DestroyImageInfo(blob_info);
520   return(image);
521 }
522 
523 /*
524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525 %                                                                             %
526 %                                                                             %
527 %                                                                             %
528 +   C l o n e B l o b I n f o                                                 %
529 %                                                                             %
530 %                                                                             %
531 %                                                                             %
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 %
534 %  CloneBlobInfo() makes a duplicate of the given blob info structure, or if
535 %  blob info is NULL, a new one.
536 %
537 %  The format of the CloneBlobInfo method is:
538 %
539 %      BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
540 %
541 %  A description of each parameter follows:
542 %
543 %    o blob_info: the blob info.
544 %
545 */
CloneBlobInfo(const BlobInfo * blob_info)546 MagickExport BlobInfo *CloneBlobInfo(const BlobInfo *blob_info)
547 {
548   BlobInfo
549     *clone_info;
550 
551   SemaphoreInfo
552     *semaphore;
553 
554   clone_info=(BlobInfo *) AcquireCriticalMemory(sizeof(*clone_info));
555   GetBlobInfo(clone_info);
556   if (blob_info == (BlobInfo *) NULL)
557     return(clone_info);
558   semaphore=clone_info->semaphore;
559   (void) memcpy(clone_info,blob_info,sizeof(*clone_info));
560   if (blob_info->mapped != MagickFalse)
561     (void) AcquireMagickResource(MapResource,blob_info->length);
562   clone_info->semaphore=semaphore;
563   LockSemaphoreInfo(clone_info->semaphore);
564   clone_info->reference_count=1;
565   UnlockSemaphoreInfo(clone_info->semaphore);
566   return(clone_info);
567 }
568 
569 /*
570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 %                                                                             %
572 %                                                                             %
573 %                                                                             %
574 +   C l o s e B l o b                                                         %
575 %                                                                             %
576 %                                                                             %
577 %                                                                             %
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
579 %
580 %  CloseBlob() closes a stream associated with the image.
581 %
582 %  The format of the CloseBlob method is:
583 %
584 %      MagickBooleanType CloseBlob(Image *image)
585 %
586 %  A description of each parameter follows:
587 %
588 %    o image: the image.
589 %
590 */
CloseBlob(Image * image)591 MagickExport MagickBooleanType CloseBlob(Image *image)
592 {
593   BlobInfo
594     *magick_restrict blob_info;
595 
596   int
597     status;
598 
599   /*
600     Close image file.
601   */
602   assert(image != (Image *) NULL);
603   assert(image->signature == MagickCoreSignature);
604   if (image->debug != MagickFalse)
605     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
606   blob_info=image->blob;
607   if ((blob_info == (BlobInfo *) NULL) || (blob_info->type == UndefinedStream))
608     return(MagickTrue);
609   status=SyncBlob(image);
610   switch (blob_info->type)
611   {
612     case UndefinedStream:
613     case StandardStream:
614       break;
615     case FileStream:
616     case PipeStream:
617     {
618       if (blob_info->synchronize != MagickFalse)
619         status=fsync(fileno(blob_info->file_info.file));
620       status=ferror(blob_info->file_info.file);
621       break;
622     }
623     case ZipStream:
624     {
625 #if defined(MAGICKCORE_ZLIB_DELEGATE)
626       (void) gzerror(blob_info->file_info.gzfile,&status);
627 #endif
628       break;
629     }
630     case BZipStream:
631     {
632 #if defined(MAGICKCORE_BZLIB_DELEGATE)
633       (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
634 #endif
635       break;
636     }
637     case FifoStream:
638       break;
639     case BlobStream:
640     {
641       if (blob_info->file_info.file != (FILE *) NULL)
642         {
643           if (blob_info->synchronize != MagickFalse)
644             status=fsync(fileno(blob_info->file_info.file));
645           status=ferror(blob_info->file_info.file);
646         }
647       break;
648     }
649     case CustomStream:
650       break;
651   }
652   blob_info->status=status < 0 ? MagickTrue : MagickFalse;
653   blob_info->size=GetBlobSize(image);
654   image->extent=blob_info->size;
655   blob_info->eof=MagickFalse;
656   blob_info->error=0;
657   blob_info->mode=UndefinedBlobMode;
658   if (blob_info->exempt != MagickFalse)
659     {
660       blob_info->type=UndefinedStream;
661       return(blob_info->status);
662     }
663   switch (blob_info->type)
664   {
665     case UndefinedStream:
666     case StandardStream:
667       break;
668     case FileStream:
669     {
670       if (fileno(blob_info->file_info.file) != -1)
671         status=fclose(blob_info->file_info.file);
672       break;
673     }
674     case PipeStream:
675     {
676 #if defined(MAGICKCORE_HAVE_PCLOSE)
677       status=pclose(blob_info->file_info.file);
678 #endif
679       break;
680     }
681     case ZipStream:
682     {
683 #if defined(MAGICKCORE_ZLIB_DELEGATE)
684       status=gzclose(blob_info->file_info.gzfile);
685 #endif
686       break;
687     }
688     case BZipStream:
689     {
690 #if defined(MAGICKCORE_BZLIB_DELEGATE)
691       BZ2_bzclose(blob_info->file_info.bzfile);
692 #endif
693       break;
694     }
695     case FifoStream:
696       break;
697     case BlobStream:
698     {
699       if (blob_info->file_info.file != (FILE *) NULL)
700         status=fclose(blob_info->file_info.file);
701       break;
702     }
703     case CustomStream:
704       break;
705   }
706   (void) DetachBlob(blob_info);
707   blob_info->status=status < 0 ? MagickTrue : MagickFalse;
708   return(blob_info->status);
709 }
710 
711 /*
712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713 %                                                                             %
714 %                                                                             %
715 %                                                                             %
716 %   C u s t o m S t r e a m T o I m a g e                                     %
717 %                                                                             %
718 %                                                                             %
719 %                                                                             %
720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 %
722 %  CustomStreamToImage() is the equivalent of ReadImage(), but reads the
723 %  formatted "file" from the suplied method rather than to an actual file.
724 %
725 %  The format of the CustomStreamToImage method is:
726 %
727 %      Image *CustomStreamToImage(const ImageInfo *image_info,
728 %         ExceptionInfo *exception)
729 %
730 %  A description of each parameter follows:
731 %
732 %    o image_info: the image info.
733 %
734 %    o exception: return any errors or warnings in this structure.
735 %
736 */
CustomStreamToImage(const ImageInfo * image_info,ExceptionInfo * exception)737 MagickExport Image *CustomStreamToImage(const ImageInfo *image_info,
738   ExceptionInfo *exception)
739 {
740   const MagickInfo
741     *magick_info;
742 
743   Image
744     *image;
745 
746   ImageInfo
747     *blob_info;
748 
749   assert(image_info != (ImageInfo *) NULL);
750   assert(image_info->signature == MagickCoreSignature);
751   if (image_info->debug != MagickFalse)
752     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
753       image_info->filename);
754   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
755   assert(image_info->custom_stream->signature == MagickCoreSignature);
756   assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
757   assert(exception != (ExceptionInfo *) NULL);
758   blob_info=CloneImageInfo(image_info);
759   if (*blob_info->magick == '\0')
760     (void) SetImageInfo(blob_info,0,exception);
761   magick_info=GetMagickInfo(blob_info->magick,exception);
762   if (magick_info == (const MagickInfo *) NULL)
763     {
764       (void) ThrowMagickException(exception,GetMagickModule(),
765         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
766         blob_info->magick);
767       blob_info=DestroyImageInfo(blob_info);
768       return((Image *) NULL);
769     }
770   image=(Image *) NULL;
771   if ((GetMagickBlobSupport(magick_info) != MagickFalse) ||
772       (*blob_info->filename != '\0'))
773     {
774       char
775         filename[MagickPathExtent];
776 
777       /*
778         Native blob support for this image format or SetImageInfo changed the
779         blob to a file.
780       */
781       (void) CopyMagickString(filename,blob_info->filename,MagickPathExtent);
782       (void) FormatLocaleString(blob_info->filename,MagickPathExtent,"%s:%s",
783         blob_info->magick,filename);
784       image=ReadImage(blob_info,exception);
785       if (image != (Image *) NULL)
786         (void) CloseBlob(image);
787     }
788   else
789     {
790       char
791         unique[MagickPathExtent];
792 
793       int
794         file;
795 
796       ImageInfo
797         *clone_info;
798 
799       unsigned char
800         *blob;
801 
802       /*
803         Write data to file on disk.
804       */
805       blob_info->custom_stream=(CustomStreamInfo *) NULL;
806       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
807         sizeof(*blob));
808       if (blob == (unsigned char *) NULL)
809         {
810           ThrowFileException(exception,BlobError,"UnableToReadBlob",
811             image_info->filename);
812           blob_info=DestroyImageInfo(blob_info);
813           return((Image *) NULL);
814         }
815       file=AcquireUniqueFileResource(unique);
816       if (file == -1)
817         {
818           ThrowFileException(exception,BlobError,"UnableToReadBlob",
819             image_info->filename);
820           blob=(unsigned char *) RelinquishMagickMemory(blob);
821           blob_info=DestroyImageInfo(blob_info);
822           return((Image *) NULL);
823         }
824       clone_info=CloneImageInfo(blob_info);
825       blob_info->file=fdopen(file,"wb+");
826       if (blob_info->file != (FILE *) NULL)
827         {
828           ssize_t
829             count;
830 
831           count=(ssize_t) MagickMaxBufferExtent;
832           while (count == (ssize_t) MagickMaxBufferExtent)
833           {
834             count=image_info->custom_stream->reader(blob,MagickMaxBufferExtent,
835               image_info->custom_stream->data);
836             count=(ssize_t) write(file,(const char *) blob,(size_t) count);
837           }
838           (void) fclose(blob_info->file);
839           (void) FormatLocaleString(clone_info->filename,MagickPathExtent,
840             "%s:%s",blob_info->magick,unique);
841           image=ReadImage(clone_info,exception);
842           if (image != (Image *) NULL)
843             {
844               Image
845                 *images;
846 
847               /*
848                 Restore original filenames and image format.
849               */
850               for (images=GetFirstImageInList(image); images != (Image *) NULL; )
851               {
852                 (void) CopyMagickString(images->filename,image_info->filename,
853                   MagickPathExtent);
854                 (void) CopyMagickString(images->magick_filename,
855                   image_info->filename,MagickPathExtent);
856                 (void) CopyMagickString(images->magick,magick_info->name,
857                   MagickPathExtent);
858                 (void) CloseBlob(images);
859                 images=GetNextImageInList(images);
860               }
861             }
862         }
863       clone_info=DestroyImageInfo(clone_info);
864       blob=(unsigned char *) RelinquishMagickMemory(blob);
865       (void) RelinquishUniqueFileResource(unique);
866     }
867   blob_info=DestroyImageInfo(blob_info);
868   return(image);
869 }
870 
871 /*
872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873 %                                                                             %
874 %                                                                             %
875 %                                                                             %
876 +   D e s t r o y B l o b                                                     %
877 %                                                                             %
878 %                                                                             %
879 %                                                                             %
880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 %
882 %  DestroyBlob() deallocates memory associated with a blob.
883 %
884 %  The format of the DestroyBlob method is:
885 %
886 %      void DestroyBlob(Image *image)
887 %
888 %  A description of each parameter follows:
889 %
890 %    o image: the image.
891 %
892 */
DestroyBlob(Image * image)893 MagickExport void DestroyBlob(Image *image)
894 {
895   BlobInfo
896     *magick_restrict blob_info;
897 
898   MagickBooleanType
899     destroy;
900 
901   assert(image != (Image *) NULL);
902   assert(image->signature == MagickCoreSignature);
903   if (image->debug != MagickFalse)
904     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
905   assert(image->blob != (BlobInfo *) NULL);
906   assert(image->blob->signature == MagickCoreSignature);
907   blob_info=image->blob;
908   destroy=MagickFalse;
909   LockSemaphoreInfo(blob_info->semaphore);
910   blob_info->reference_count--;
911   assert(blob_info->reference_count >= 0);
912   if (blob_info->reference_count == 0)
913     destroy=MagickTrue;
914   UnlockSemaphoreInfo(blob_info->semaphore);
915   if (destroy == MagickFalse)
916     {
917       image->blob=(BlobInfo *) NULL;
918       return;
919     }
920   (void) CloseBlob(image);
921   if (blob_info->mapped != MagickFalse)
922     {
923       (void) UnmapBlob(blob_info->data,blob_info->length);
924       RelinquishMagickResource(MapResource,blob_info->length);
925     }
926   if (blob_info->semaphore != (SemaphoreInfo *) NULL)
927     RelinquishSemaphoreInfo(&blob_info->semaphore);
928   blob_info->signature=(~MagickCoreSignature);
929   image->blob=(BlobInfo *) RelinquishMagickMemory(blob_info);
930 }
931 
932 /*
933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 %                                                                             %
935 %                                                                             %
936 %                                                                             %
937 +   D e s t r o y C u s t o m S t r e a m I n f o                             %
938 %                                                                             %
939 %                                                                             %
940 %                                                                             %
941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942 %
943 %  DestroyCustomStreamInfo() destroys memory associated with the
944 %  CustomStreamInfo structure.
945 %
946 %  The format of the DestroyCustomStreamInfo method is:
947 %
948 %      CustomStreamInfo *DestroyCustomStreamInfo(CustomStreamInfo *stream_info)
949 %
950 %  A description of each parameter follows:
951 %
952 %    o custom_stream: the custom stream info.
953 %
954 */
DestroyCustomStreamInfo(CustomStreamInfo * custom_stream)955 MagickExport CustomStreamInfo *DestroyCustomStreamInfo(
956   CustomStreamInfo *custom_stream)
957 {
958   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
959   assert(custom_stream != (CustomStreamInfo *) NULL);
960   assert(custom_stream->signature == MagickCoreSignature);
961   custom_stream->signature=(~MagickCoreSignature);
962   custom_stream=(CustomStreamInfo *) RelinquishMagickMemory(custom_stream);
963   return(custom_stream);
964 }
965 
966 /*
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 %                                                                             %
969 %                                                                             %
970 %                                                                             %
971 +   D e t a c h B l o b                                                       %
972 %                                                                             %
973 %                                                                             %
974 %                                                                             %
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976 %
977 %  DetachBlob() detaches a blob from the BlobInfo structure.
978 %
979 %  The format of the DetachBlob method is:
980 %
981 %      void *DetachBlob(BlobInfo *blob_info)
982 %
983 %  A description of each parameter follows:
984 %
985 %    o blob_info: Specifies a pointer to a BlobInfo structure.
986 %
987 */
DetachBlob(BlobInfo * blob_info)988 MagickExport void *DetachBlob(BlobInfo *blob_info)
989 {
990   void
991     *data;
992 
993   assert(blob_info != (BlobInfo *) NULL);
994   if (blob_info->debug != MagickFalse)
995     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
996   if (blob_info->mapped != MagickFalse)
997     {
998       (void) UnmapBlob(blob_info->data,blob_info->length);
999       blob_info->data=NULL;
1000       RelinquishMagickResource(MapResource,blob_info->length);
1001     }
1002   blob_info->mapped=MagickFalse;
1003   blob_info->length=0;
1004   blob_info->offset=0;
1005   blob_info->eof=MagickFalse;
1006   blob_info->error=0;
1007   blob_info->exempt=MagickFalse;
1008   blob_info->type=UndefinedStream;
1009   blob_info->file_info.file=(FILE *) NULL;
1010   data=blob_info->data;
1011   blob_info->data=(unsigned char *) NULL;
1012   blob_info->stream=(StreamHandler) NULL;
1013   blob_info->custom_stream=(CustomStreamInfo *) NULL;
1014   return(data);
1015 }
1016 
1017 /*
1018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1019 %                                                                             %
1020 %                                                                             %
1021 %                                                                             %
1022 +   D i s a s s o c i a t e B l o b                                           %
1023 %                                                                             %
1024 %                                                                             %
1025 %                                                                             %
1026 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1027 %
1028 %  DisassociateBlob() disassociates the image stream.  It checks if the
1029 %  blob of the specified image is referenced by other images. If the reference
1030 %  count is higher then 1 a new blob is assigned to the specified image.
1031 %
1032 %  The format of the DisassociateBlob method is:
1033 %
1034 %      void DisassociateBlob(const Image *image)
1035 %
1036 %  A description of each parameter follows:
1037 %
1038 %    o image: the image.
1039 %
1040 */
DisassociateBlob(Image * image)1041 MagickExport void DisassociateBlob(Image *image)
1042 {
1043   BlobInfo
1044     *magick_restrict blob_info,
1045     *clone_info;
1046 
1047   MagickBooleanType
1048     clone;
1049 
1050   assert(image != (Image *) NULL);
1051   assert(image->signature == MagickCoreSignature);
1052   if (image->debug != MagickFalse)
1053     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1054   assert(image->blob != (BlobInfo *) NULL);
1055   assert(image->blob->signature == MagickCoreSignature);
1056   blob_info=image->blob;
1057   clone=MagickFalse;
1058   LockSemaphoreInfo(blob_info->semaphore);
1059   assert(blob_info->reference_count >= 0);
1060   if (blob_info->reference_count > 1)
1061     clone=MagickTrue;
1062   UnlockSemaphoreInfo(blob_info->semaphore);
1063   if (clone == MagickFalse)
1064     return;
1065   clone_info=CloneBlobInfo(blob_info);
1066   DestroyBlob(image);
1067   image->blob=clone_info;
1068 }
1069 
1070 /*
1071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1072 %                                                                             %
1073 %                                                                             %
1074 %                                                                             %
1075 +  D i s c a r d B l o b B y t e s                                            %
1076 %                                                                             %
1077 %                                                                             %
1078 %                                                                             %
1079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1080 %
1081 %  DiscardBlobBytes() discards bytes in a blob.
1082 %
1083 %  The format of the DiscardBlobBytes method is:
1084 %
1085 %      MagickBooleanType DiscardBlobBytes(Image *image,
1086 %        const MagickSizeType length)
1087 %
1088 %  A description of each parameter follows.
1089 %
1090 %    o image: the image.
1091 %
1092 %    o length:  the number of bytes to skip.
1093 %
1094 */
DiscardBlobBytes(Image * image,const MagickSizeType length)1095 MagickExport MagickBooleanType DiscardBlobBytes(Image *image,
1096   const MagickSizeType length)
1097 {
1098   register MagickOffsetType
1099     i;
1100 
1101   size_t
1102     quantum;
1103 
1104   ssize_t
1105     count;
1106 
1107   unsigned char
1108     buffer[MagickMinBufferExtent >> 1];
1109 
1110   assert(image != (Image *) NULL);
1111   assert(image->signature == MagickCoreSignature);
1112   if (length != (MagickSizeType) ((MagickOffsetType) length))
1113     return(MagickFalse);
1114   count=0;
1115   for (i=0; i < (MagickOffsetType) length; i+=count)
1116   {
1117     quantum=(size_t) MagickMin(length-i,sizeof(buffer));
1118     (void) ReadBlobStream(image,quantum,buffer,&count);
1119     if (count <= 0)
1120       {
1121         count=0;
1122         if (errno != EINTR)
1123           break;
1124       }
1125   }
1126   return(i < (MagickOffsetType) length ? MagickFalse : MagickTrue);
1127 }
1128 
1129 /*
1130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1131 %                                                                             %
1132 %                                                                             %
1133 %                                                                             %
1134 +   D u p l i c a t e s B l o b                                               %
1135 %                                                                             %
1136 %                                                                             %
1137 %                                                                             %
1138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1139 %
1140 %  DuplicateBlob() duplicates a blob descriptor.
1141 %
1142 %  The format of the DuplicateBlob method is:
1143 %
1144 %      void DuplicateBlob(Image *image,const Image *duplicate)
1145 %
1146 %  A description of each parameter follows:
1147 %
1148 %    o image: the image.
1149 %
1150 %    o duplicate: the duplicate image.
1151 %
1152 */
DuplicateBlob(Image * image,const Image * duplicate)1153 MagickExport void DuplicateBlob(Image *image,const Image *duplicate)
1154 {
1155   assert(image != (Image *) NULL);
1156   assert(image->signature == MagickCoreSignature);
1157   if (image->debug != MagickFalse)
1158     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1159   assert(duplicate != (Image *) NULL);
1160   assert(duplicate->signature == MagickCoreSignature);
1161   DestroyBlob(image);
1162   image->blob=ReferenceBlob(duplicate->blob);
1163 }
1164 
1165 /*
1166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1167 %                                                                             %
1168 %                                                                             %
1169 %                                                                             %
1170 +  E O F B l o b                                                              %
1171 %                                                                             %
1172 %                                                                             %
1173 %                                                                             %
1174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1175 %
1176 %  EOFBlob() returns a non-zero value when EOF has been detected reading from
1177 %  a blob or file.
1178 %
1179 %  The format of the EOFBlob method is:
1180 %
1181 %      int EOFBlob(const Image *image)
1182 %
1183 %  A description of each parameter follows:
1184 %
1185 %    o image: the image.
1186 %
1187 */
EOFBlob(const Image * image)1188 MagickExport int EOFBlob(const Image *image)
1189 {
1190   BlobInfo
1191     *magick_restrict blob_info;
1192 
1193   assert(image != (Image *) NULL);
1194   assert(image->signature == MagickCoreSignature);
1195   if (image->debug != MagickFalse)
1196     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1197   assert(image->blob != (BlobInfo *) NULL);
1198   assert(image->blob->type != UndefinedStream);
1199   blob_info=image->blob;
1200   switch (blob_info->type)
1201   {
1202     case UndefinedStream:
1203     case StandardStream:
1204       break;
1205     case FileStream:
1206     case PipeStream:
1207     {
1208       blob_info->eof=feof(blob_info->file_info.file) != 0 ? MagickTrue :
1209         MagickFalse;
1210       break;
1211     }
1212     case ZipStream:
1213     {
1214 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1215       blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
1216         MagickFalse;
1217 #endif
1218       break;
1219     }
1220     case BZipStream:
1221     {
1222 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1223       int
1224         status;
1225 
1226       status=0;
1227       (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
1228       blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse;
1229 #endif
1230       break;
1231     }
1232     case FifoStream:
1233     {
1234       blob_info->eof=MagickFalse;
1235       break;
1236     }
1237     case BlobStream:
1238       break;
1239     case CustomStream:
1240       break;
1241   }
1242   return((int) blob_info->eof);
1243 }
1244 
1245 /*
1246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1247 %                                                                             %
1248 %                                                                             %
1249 %                                                                             %
1250 +  E r r o r B l o b                                                          %
1251 %                                                                             %
1252 %                                                                             %
1253 %                                                                             %
1254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1255 %
1256 %  ErrorBlob() returns a non-zero value when an error has been detected reading
1257 %  from a blob or file.
1258 %
1259 %  The format of the ErrorBlob method is:
1260 %
1261 %      int ErrorBlob(const Image *image)
1262 %
1263 %  A description of each parameter follows:
1264 %
1265 %    o image: the image.
1266 %
1267 */
ErrorBlob(const Image * image)1268 MagickExport int ErrorBlob(const Image *image)
1269 {
1270   BlobInfo
1271     *magick_restrict blob_info;
1272 
1273   assert(image != (Image *) NULL);
1274   assert(image->signature == MagickCoreSignature);
1275   if (image->debug != MagickFalse)
1276     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1277   assert(image->blob != (BlobInfo *) NULL);
1278   assert(image->blob->type != UndefinedStream);
1279   blob_info=image->blob;
1280   switch (blob_info->type)
1281   {
1282     case UndefinedStream:
1283     case StandardStream:
1284       break;
1285     case FileStream:
1286     case PipeStream:
1287     {
1288       blob_info->error=ferror(blob_info->file_info.file);
1289       break;
1290     }
1291     case ZipStream:
1292     {
1293 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1294       (void) gzerror(blob_info->file_info.gzfile,&blob_info->error);
1295 #endif
1296       break;
1297     }
1298     case BZipStream:
1299     {
1300 #if defined(MAGICKCORE_BZLIB_DELEGATE)
1301       (void) BZ2_bzerror(blob_info->file_info.bzfile,&blob_info->error);
1302 #endif
1303       break;
1304     }
1305     case FifoStream:
1306     {
1307       blob_info->error=0;
1308       break;
1309     }
1310     case BlobStream:
1311       break;
1312     case CustomStream:
1313       break;
1314   }
1315   return(blob_info->error);
1316 }
1317 
1318 /*
1319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1320 %                                                                             %
1321 %                                                                             %
1322 %                                                                             %
1323 %   F i l e T o B l o b                                                       %
1324 %                                                                             %
1325 %                                                                             %
1326 %                                                                             %
1327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1328 %
1329 %  FileToBlob() returns the contents of a file as a buffer terminated with
1330 %  the '\0' character.  The length of the buffer (not including the extra
1331 %  terminating '\0' character) is returned via the 'length' parameter.  Free
1332 %  the buffer with RelinquishMagickMemory().
1333 %
1334 %  The format of the FileToBlob method is:
1335 %
1336 %      void *FileToBlob(const char *filename,const size_t extent,
1337 %        size_t *length,ExceptionInfo *exception)
1338 %
1339 %  A description of each parameter follows:
1340 %
1341 %    o blob:  FileToBlob() returns the contents of a file as a blob.  If
1342 %      an error occurs NULL is returned.
1343 %
1344 %    o filename: the filename.
1345 %
1346 %    o extent:  The maximum length of the blob.
1347 %
1348 %    o length: On return, this reflects the actual length of the blob.
1349 %
1350 %    o exception: return any errors or warnings in this structure.
1351 %
1352 */
FileToBlob(const char * filename,const size_t extent,size_t * length,ExceptionInfo * exception)1353 MagickExport void *FileToBlob(const char *filename,const size_t extent,
1354   size_t *length,ExceptionInfo *exception)
1355 {
1356   int
1357     file;
1358 
1359   MagickBooleanType
1360     status;
1361 
1362   MagickOffsetType
1363     offset;
1364 
1365   register size_t
1366     i;
1367 
1368   ssize_t
1369     count;
1370 
1371   struct stat
1372     attributes;
1373 
1374   unsigned char
1375     *blob;
1376 
1377   void
1378     *map;
1379 
1380   assert(filename != (const char *) NULL);
1381   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1382   assert(exception != (ExceptionInfo *) NULL);
1383   *length=0;
1384   status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename);
1385   if (status == MagickFalse)
1386     {
1387       errno=EPERM;
1388       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1389         "NotAuthorized","`%s'",filename);
1390       return(NULL);
1391     }
1392   file=fileno(stdin);
1393   if (LocaleCompare(filename,"-") != 0)
1394     {
1395       status=GetPathAttributes(filename,&attributes);
1396       if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
1397         {
1398           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1399           return(NULL);
1400         }
1401       file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1402     }
1403   if (file == -1)
1404     {
1405       ThrowFileException(exception,BlobError,"UnableToOpenFile",filename);
1406       return(NULL);
1407     }
1408   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
1409   count=0;
1410   if ((file == fileno(stdin)) || (offset < 0) ||
1411       (offset != (MagickOffsetType) ((ssize_t) offset)))
1412     {
1413       size_t
1414         quantum;
1415 
1416       struct stat
1417         file_stats;
1418 
1419       /*
1420         Stream is not seekable.
1421       */
1422       offset=(MagickOffsetType) lseek(file,0,SEEK_SET);
1423       quantum=(size_t) MagickMaxBufferExtent;
1424       if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1425         quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1426       blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1427       for (i=0; blob != (unsigned char *) NULL; i+=count)
1428       {
1429         count=read(file,blob+i,quantum);
1430         if (count <= 0)
1431           {
1432             count=0;
1433             if (errno != EINTR)
1434               break;
1435           }
1436         if (~((size_t) i) < (quantum+1))
1437           {
1438             blob=(unsigned char *) RelinquishMagickMemory(blob);
1439             break;
1440           }
1441         blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1,
1442           sizeof(*blob));
1443         if ((size_t) (i+count) >= extent)
1444           break;
1445       }
1446       if (LocaleCompare(filename,"-") != 0)
1447         file=close(file);
1448       if (blob == (unsigned char *) NULL)
1449         {
1450           (void) ThrowMagickException(exception,GetMagickModule(),
1451             ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1452           return(NULL);
1453         }
1454       if (file == -1)
1455         {
1456           blob=(unsigned char *) RelinquishMagickMemory(blob);
1457           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1458           return(NULL);
1459         }
1460       *length=(size_t) MagickMin(i+count,extent);
1461       blob[*length]='\0';
1462       return(blob);
1463     }
1464   *length=(size_t) MagickMin(offset,(MagickOffsetType)
1465     MagickMin(extent,(size_t) SSIZE_MAX));
1466   blob=(unsigned char *) NULL;
1467   if (~(*length) >= (MagickPathExtent-1))
1468     blob=(unsigned char *) AcquireQuantumMemory(*length+MagickPathExtent,
1469       sizeof(*blob));
1470   if (blob == (unsigned char *) NULL)
1471     {
1472       file=close(file);
1473       (void) ThrowMagickException(exception,GetMagickModule(),
1474         ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1475       return(NULL);
1476     }
1477   map=MapBlob(file,ReadMode,0,*length);
1478   if (map != (unsigned char *) NULL)
1479     {
1480       (void) memcpy(blob,map,*length);
1481       (void) UnmapBlob(map,*length);
1482     }
1483   else
1484     {
1485       (void) lseek(file,0,SEEK_SET);
1486       for (i=0; i < *length; i+=count)
1487       {
1488         count=read(file,blob+i,(size_t) MagickMin(*length-i,(size_t)
1489           SSIZE_MAX));
1490         if (count <= 0)
1491           {
1492             count=0;
1493             if (errno != EINTR)
1494               break;
1495           }
1496       }
1497       if (i < *length)
1498         {
1499           file=close(file)-1;
1500           blob=(unsigned char *) RelinquishMagickMemory(blob);
1501           ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1502           return(NULL);
1503         }
1504     }
1505   blob[*length]='\0';
1506   if (LocaleCompare(filename,"-") != 0)
1507     file=close(file);
1508   if (file == -1)
1509     {
1510       blob=(unsigned char *) RelinquishMagickMemory(blob);
1511       ThrowFileException(exception,BlobError,"UnableToReadBlob",filename);
1512     }
1513   return(blob);
1514 }
1515 
1516 /*
1517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1518 %                                                                             %
1519 %                                                                             %
1520 %                                                                             %
1521 %   F i l e T o I m a g e                                                     %
1522 %                                                                             %
1523 %                                                                             %
1524 %                                                                             %
1525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1526 %
1527 %  FileToImage() write the contents of a file to an image.
1528 %
1529 %  The format of the FileToImage method is:
1530 %
1531 %      MagickBooleanType FileToImage(Image *,const char *filename)
1532 %
1533 %  A description of each parameter follows:
1534 %
1535 %    o image: the image.
1536 %
1537 %    o filename: the filename.
1538 %
1539 */
WriteBlobStream(Image * image,const size_t length,const void * magick_restrict data)1540 static inline ssize_t WriteBlobStream(Image *image,const size_t length,
1541   const void *magick_restrict data)
1542 {
1543   BlobInfo
1544     *magick_restrict blob_info;
1545 
1546   MagickSizeType
1547     extent;
1548 
1549   register unsigned char
1550     *magick_restrict q;
1551 
1552   assert(image->blob != (BlobInfo *) NULL);
1553   assert(image->blob->type != UndefinedStream);
1554   assert(data != NULL);
1555   blob_info=image->blob;
1556   if (blob_info->type != BlobStream)
1557     return(WriteBlob(image,length,(const unsigned char *) data));
1558   extent=(MagickSizeType) (blob_info->offset+(MagickOffsetType) length);
1559   if (extent >= blob_info->extent)
1560     {
1561       extent=blob_info->extent+blob_info->quantum+length;
1562       blob_info->quantum<<=1;
1563       if (SetBlobExtent(image,extent) == MagickFalse)
1564         return(0);
1565     }
1566   q=blob_info->data+blob_info->offset;
1567   (void) memcpy(q,data,length);
1568   blob_info->offset+=length;
1569   if (blob_info->offset >= (MagickOffsetType) blob_info->length)
1570     blob_info->length=(size_t) blob_info->offset;
1571   return((ssize_t) length);
1572 }
1573 
FileToImage(Image * image,const char * filename,ExceptionInfo * exception)1574 MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
1575   ExceptionInfo *exception)
1576 {
1577   int
1578     file;
1579 
1580   MagickBooleanType
1581     status;
1582 
1583   size_t
1584     length,
1585     quantum;
1586 
1587   ssize_t
1588     count;
1589 
1590   struct stat
1591     file_stats;
1592 
1593   unsigned char
1594     *blob;
1595 
1596   assert(image != (const Image *) NULL);
1597   assert(image->signature == MagickCoreSignature);
1598   assert(filename != (const char *) NULL);
1599   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1600   status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename);
1601   if (status == MagickFalse)
1602     {
1603       errno=EPERM;
1604       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1605         "NotAuthorized","`%s'",filename);
1606       return(MagickFalse);
1607     }
1608   file=fileno(stdin);
1609   if (LocaleCompare(filename,"-") != 0)
1610     file=open_utf8(filename,O_RDONLY | O_BINARY,0);
1611   if (file == -1)
1612     {
1613       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
1614       return(MagickFalse);
1615     }
1616   quantum=(size_t) MagickMaxBufferExtent;
1617   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1618     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1619   blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob));
1620   if (blob == (unsigned char *) NULL)
1621     {
1622       file=close(file);
1623       ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
1624         filename);
1625       return(MagickFalse);
1626     }
1627   for ( ; ; )
1628   {
1629     count=read(file,blob,quantum);
1630     if (count <= 0)
1631       {
1632         count=0;
1633         if (errno != EINTR)
1634           break;
1635       }
1636     length=(size_t) count;
1637     count=WriteBlobStream(image,length,blob);
1638     if (count != (ssize_t) length)
1639       {
1640         ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1641         break;
1642       }
1643   }
1644   file=close(file);
1645   if (file == -1)
1646     ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1647   blob=(unsigned char *) RelinquishMagickMemory(blob);
1648   return(MagickTrue);
1649 }
1650 
1651 /*
1652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653 %                                                                             %
1654 %                                                                             %
1655 %                                                                             %
1656 +   G e t B l o b E r r o r                                                   %
1657 %                                                                             %
1658 %                                                                             %
1659 %                                                                             %
1660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1661 %
1662 %  GetBlobError() returns MagickTrue if the blob associated with the specified
1663 %  image encountered an error.
1664 %
1665 %  The format of the GetBlobError method is:
1666 %
1667 %       MagickBooleanType GetBlobError(const Image *image)
1668 %
1669 %  A description of each parameter follows:
1670 %
1671 %    o image: the image.
1672 %
1673 */
GetBlobError(const Image * image)1674 MagickExport MagickBooleanType GetBlobError(const Image *image)
1675 {
1676   assert(image != (const Image *) NULL);
1677   assert(image->signature == MagickCoreSignature);
1678   if (image->debug != MagickFalse)
1679     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1680   return(image->blob->status);
1681 }
1682 
1683 /*
1684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1685 %                                                                             %
1686 %                                                                             %
1687 %                                                                             %
1688 +   G e t B l o b F i l e H a n d l e                                         %
1689 %                                                                             %
1690 %                                                                             %
1691 %                                                                             %
1692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1693 %
1694 %  GetBlobFileHandle() returns the file handle associated with the image blob.
1695 %
1696 %  The format of the GetBlobFile method is:
1697 %
1698 %      FILE *GetBlobFileHandle(const Image *image)
1699 %
1700 %  A description of each parameter follows:
1701 %
1702 %    o image: the image.
1703 %
1704 */
GetBlobFileHandle(const Image * image)1705 MagickExport FILE *GetBlobFileHandle(const Image *image)
1706 {
1707   assert(image != (const Image *) NULL);
1708   assert(image->signature == MagickCoreSignature);
1709   return(image->blob->file_info.file);
1710 }
1711 
1712 /*
1713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1714 %                                                                             %
1715 %                                                                             %
1716 %                                                                             %
1717 +   G e t B l o b I n f o                                                     %
1718 %                                                                             %
1719 %                                                                             %
1720 %                                                                             %
1721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1722 %
1723 %  GetBlobInfo() initializes the BlobInfo structure.
1724 %
1725 %  The format of the GetBlobInfo method is:
1726 %
1727 %      void GetBlobInfo(BlobInfo *blob_info)
1728 %
1729 %  A description of each parameter follows:
1730 %
1731 %    o blob_info: Specifies a pointer to a BlobInfo structure.
1732 %
1733 */
GetBlobInfo(BlobInfo * blob_info)1734 MagickExport void GetBlobInfo(BlobInfo *blob_info)
1735 {
1736   assert(blob_info != (BlobInfo *) NULL);
1737   (void) memset(blob_info,0,sizeof(*blob_info));
1738   blob_info->type=UndefinedStream;
1739   blob_info->quantum=(size_t) MagickMaxBlobExtent;
1740   blob_info->properties.st_mtime=GetMagickTime();
1741   blob_info->properties.st_ctime=blob_info->properties.st_mtime;
1742   blob_info->debug=IsEventLogging();
1743   blob_info->reference_count=1;
1744   blob_info->semaphore=AcquireSemaphoreInfo();
1745   blob_info->signature=MagickCoreSignature;
1746 }
1747 
1748 /*
1749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1750 %                                                                             %
1751 %                                                                             %
1752 %                                                                             %
1753 %  G e t B l o b P r o p e r t i e s                                          %
1754 %                                                                             %
1755 %                                                                             %
1756 %                                                                             %
1757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1758 %
1759 %  GetBlobProperties() returns information about an image blob.
1760 %
1761 %  The format of the GetBlobProperties method is:
1762 %
1763 %      const struct stat *GetBlobProperties(const Image *image)
1764 %
1765 %  A description of each parameter follows:
1766 %
1767 %    o image: the image.
1768 %
1769 */
GetBlobProperties(const Image * image)1770 MagickExport const struct stat *GetBlobProperties(const Image *image)
1771 {
1772   assert(image != (Image *) NULL);
1773   assert(image->signature == MagickCoreSignature);
1774   if (image->debug != MagickFalse)
1775     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1776   return(&image->blob->properties);
1777 }
1778 
1779 /*
1780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781 %                                                                             %
1782 %                                                                             %
1783 %                                                                             %
1784 +  G e t B l o b S i z e                                                      %
1785 %                                                                             %
1786 %                                                                             %
1787 %                                                                             %
1788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1789 %
1790 %  GetBlobSize() returns the current length of the image file or blob; zero is
1791 %  returned if the size cannot be determined.
1792 %
1793 %  The format of the GetBlobSize method is:
1794 %
1795 %      MagickSizeType GetBlobSize(const Image *image)
1796 %
1797 %  A description of each parameter follows:
1798 %
1799 %    o image: the image.
1800 %
1801 */
GetBlobSize(const Image * image)1802 MagickExport MagickSizeType GetBlobSize(const Image *image)
1803 {
1804   BlobInfo
1805     *magick_restrict blob_info;
1806 
1807   MagickSizeType
1808     extent;
1809 
1810   assert(image != (Image *) NULL);
1811   assert(image->signature == MagickCoreSignature);
1812   if (image->debug != MagickFalse)
1813     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1814   assert(image->blob != (BlobInfo *) NULL);
1815   blob_info=image->blob;
1816   extent=0;
1817   switch (blob_info->type)
1818   {
1819     case UndefinedStream:
1820     case StandardStream:
1821     {
1822       extent=blob_info->size;
1823       break;
1824     }
1825     case FileStream:
1826     {
1827       int
1828         file_descriptor;
1829 
1830       extent=(MagickSizeType) blob_info->properties.st_size;
1831       if (extent == 0)
1832         extent=blob_info->size;
1833       file_descriptor=fileno(blob_info->file_info.file);
1834       if (file_descriptor == -1)
1835         break;
1836       if (fstat(file_descriptor,&blob_info->properties) == 0)
1837         extent=(MagickSizeType) blob_info->properties.st_size;
1838       break;
1839     }
1840     case PipeStream:
1841     {
1842       extent=blob_info->size;
1843       break;
1844     }
1845     case ZipStream:
1846     case BZipStream:
1847     {
1848       MagickBooleanType
1849         status;
1850 
1851       status=GetPathAttributes(image->filename,&blob_info->properties);
1852       if (status != MagickFalse)
1853         extent=(MagickSizeType) blob_info->properties.st_size;
1854       break;
1855     }
1856     case FifoStream:
1857       break;
1858     case BlobStream:
1859     {
1860       extent=(MagickSizeType) blob_info->length;
1861       break;
1862     }
1863     case CustomStream:
1864     {
1865       if ((blob_info->custom_stream->teller != (CustomStreamTeller) NULL) &&
1866           (blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL))
1867         {
1868           MagickOffsetType
1869             offset;
1870 
1871           offset=blob_info->custom_stream->teller(
1872             blob_info->custom_stream->data);
1873           extent=(MagickSizeType) blob_info->custom_stream->seeker(0,SEEK_END,
1874             blob_info->custom_stream->data);
1875           (void) blob_info->custom_stream->seeker(offset,SEEK_SET,
1876             blob_info->custom_stream->data);
1877         }
1878       break;
1879     }
1880   }
1881   return(extent);
1882 }
1883 
1884 /*
1885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1886 %                                                                             %
1887 %                                                                             %
1888 %                                                                             %
1889 +   G e t B l o b S t r e a m D a t a                                         %
1890 %                                                                             %
1891 %                                                                             %
1892 %                                                                             %
1893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1894 %
1895 %  GetBlobStreamData() returns the stream data for the image.
1896 %
1897 %  The format of the GetBlobStreamData method is:
1898 %
1899 %      void *GetBlobStreamData(const Image *image)
1900 %
1901 %  A description of each parameter follows:
1902 %
1903 %    o image: the image.
1904 %
1905 */
GetBlobStreamData(const Image * image)1906 MagickExport void *GetBlobStreamData(const Image *image)
1907 {
1908   assert(image != (const Image *) NULL);
1909   assert(image->signature == MagickCoreSignature);
1910   return(image->blob->data);
1911 }
1912 
1913 /*
1914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1915 %                                                                             %
1916 %                                                                             %
1917 %                                                                             %
1918 +   G e t B l o b S t r e a m H a n d l e r                                   %
1919 %                                                                             %
1920 %                                                                             %
1921 %                                                                             %
1922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1923 %
1924 %  GetBlobStreamHandler() returns the stream handler for the image.
1925 %
1926 %  The format of the GetBlobStreamHandler method is:
1927 %
1928 %      StreamHandler GetBlobStreamHandler(const Image *image)
1929 %
1930 %  A description of each parameter follows:
1931 %
1932 %    o image: the image.
1933 %
1934 */
GetBlobStreamHandler(const Image * image)1935 MagickExport StreamHandler GetBlobStreamHandler(const Image *image)
1936 {
1937   assert(image != (const Image *) NULL);
1938   assert(image->signature == MagickCoreSignature);
1939   if (image->debug != MagickFalse)
1940     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1941   return(image->blob->stream);
1942 }
1943 
1944 /*
1945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1946 %                                                                             %
1947 %                                                                             %
1948 %                                                                             %
1949 %   I m a g e T o B l o b                                                     %
1950 %                                                                             %
1951 %                                                                             %
1952 %                                                                             %
1953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1954 %
1955 %  ImageToBlob() implements direct to memory image formats.  It returns the
1956 %  image as a formatted blob and its length.  The magick member of the Image
1957 %  structure determines the format of the returned blob (GIF, JPEG, PNG,
1958 %  etc.).  This method is the equivalent of WriteImage(), but writes the
1959 %  formatted "file" to a memory buffer rather than to an actual file.
1960 %
1961 %  The format of the ImageToBlob method is:
1962 %
1963 %      void *ImageToBlob(const ImageInfo *image_info,Image *image,
1964 %        size_t *length,ExceptionInfo *exception)
1965 %
1966 %  A description of each parameter follows:
1967 %
1968 %    o image_info: the image info.
1969 %
1970 %    o image: the image.
1971 %
1972 %    o length: return the actual length of the blob.
1973 %
1974 %    o exception: return any errors or warnings in this structure.
1975 %
1976 */
ImageToBlob(const ImageInfo * image_info,Image * image,size_t * length,ExceptionInfo * exception)1977 MagickExport void *ImageToBlob(const ImageInfo *image_info,
1978   Image *image,size_t *length,ExceptionInfo *exception)
1979 {
1980   const MagickInfo
1981     *magick_info;
1982 
1983   ImageInfo
1984     *blob_info;
1985 
1986   MagickBooleanType
1987     status;
1988 
1989   void
1990     *blob;
1991 
1992   assert(image_info != (const ImageInfo *) NULL);
1993   assert(image_info->signature == MagickCoreSignature);
1994   if (image_info->debug != MagickFalse)
1995     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1996       image_info->filename);
1997   assert(image != (Image *) NULL);
1998   assert(image->signature == MagickCoreSignature);
1999   assert(exception != (ExceptionInfo *) NULL);
2000   *length=0;
2001   blob=(unsigned char *) NULL;
2002   blob_info=CloneImageInfo(image_info);
2003   blob_info->adjoin=MagickFalse;
2004   (void) SetImageInfo(blob_info,1,exception);
2005   if (*blob_info->magick != '\0')
2006     (void) CopyMagickString(image->magick,blob_info->magick,MagickPathExtent);
2007   magick_info=GetMagickInfo(image->magick,exception);
2008   if (magick_info == (const MagickInfo *) NULL)
2009     {
2010       (void) ThrowMagickException(exception,GetMagickModule(),
2011         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2012         image->magick);
2013       blob_info=DestroyImageInfo(blob_info);
2014       return(blob);
2015     }
2016   (void) CopyMagickString(blob_info->magick,image->magick,MagickPathExtent);
2017   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2018     {
2019       /*
2020         Native blob support for this image format.
2021       */
2022       blob_info->length=0;
2023       blob_info->blob=AcquireQuantumMemory(MagickMaxBlobExtent,
2024         sizeof(unsigned char));
2025       if (blob_info->blob == NULL)
2026         (void) ThrowMagickException(exception,GetMagickModule(),
2027           ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
2028       else
2029         {
2030           (void) CloseBlob(image);
2031           image->blob->exempt=MagickTrue;
2032           *image->filename='\0';
2033           status=WriteImage(blob_info,image,exception);
2034           *length=image->blob->length;
2035           blob=DetachBlob(image->blob);
2036           if (blob == (void *) NULL)
2037             blob_info->blob=RelinquishMagickMemory(blob_info->blob);
2038           else if (status == MagickFalse)
2039             blob=RelinquishMagickMemory(blob);
2040           else
2041             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2042         }
2043     }
2044   else
2045     {
2046       char
2047         unique[MagickPathExtent];
2048 
2049       int
2050         file;
2051 
2052       /*
2053         Write file to disk in blob image format.
2054       */
2055       file=AcquireUniqueFileResource(unique);
2056       if (file == -1)
2057         {
2058           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2059             image_info->filename);
2060         }
2061       else
2062         {
2063           blob_info->file=fdopen(file,"wb");
2064           if (blob_info->file != (FILE *) NULL)
2065             {
2066               (void) FormatLocaleString(image->filename,MagickPathExtent,
2067                 "%s:%s",image->magick,unique);
2068               status=WriteImage(blob_info,image,exception);
2069               (void) CloseBlob(image);
2070               (void) fclose(blob_info->file);
2071               if (status != MagickFalse)
2072                 blob=FileToBlob(unique,~0UL,length,exception);
2073             }
2074           (void) RelinquishUniqueFileResource(unique);
2075         }
2076     }
2077   blob_info=DestroyImageInfo(blob_info);
2078   return(blob);
2079 }
2080 
2081 /*
2082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2083 %                                                                             %
2084 %                                                                             %
2085 %                                                                             %
2086 +  I m a g e T o C u s t o m S t r e a m                                      %
2087 %                                                                             %
2088 %                                                                             %
2089 %                                                                             %
2090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2091 %
2092 %  ImageToCustomStream() is the equivalent of WriteImage(), but writes the
2093 %  formatted "file" to the custom stream rather than to an actual file.
2094 %
2095 %  The format of the ImageToCustomStream method is:
2096 %
2097 %      void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2098 %        ExceptionInfo *exception)
2099 %
2100 %  A description of each parameter follows:
2101 %
2102 %    o image_info: the image info.
2103 %
2104 %    o image: the image.
2105 %
2106 %    o exception: return any errors or warnings in this structure.
2107 %
2108 */
ImageToCustomStream(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)2109 MagickExport void ImageToCustomStream(const ImageInfo *image_info,Image *image,
2110   ExceptionInfo *exception)
2111 {
2112   const MagickInfo
2113     *magick_info;
2114 
2115   ImageInfo
2116     *clone_info;
2117 
2118   MagickBooleanType
2119     blob_support,
2120     status;
2121 
2122   assert(image_info != (const ImageInfo *) NULL);
2123   assert(image_info->signature == MagickCoreSignature);
2124   if (image_info->debug != MagickFalse)
2125     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2126       image_info->filename);
2127   assert(image != (Image *) NULL);
2128   assert(image->signature == MagickCoreSignature);
2129   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2130   assert(image_info->custom_stream->signature == MagickCoreSignature);
2131   assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2132   assert(exception != (ExceptionInfo *) NULL);
2133   clone_info=CloneImageInfo(image_info);
2134   clone_info->adjoin=MagickFalse;
2135   (void) SetImageInfo(clone_info,1,exception);
2136   if (*clone_info->magick != '\0')
2137     (void) CopyMagickString(image->magick,clone_info->magick,MagickPathExtent);
2138   magick_info=GetMagickInfo(image->magick,exception);
2139   if (magick_info == (const MagickInfo *) NULL)
2140     {
2141       (void) ThrowMagickException(exception,GetMagickModule(),
2142         MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2143         image->magick);
2144       clone_info=DestroyImageInfo(clone_info);
2145       return;
2146     }
2147   (void) CopyMagickString(clone_info->magick,image->magick,MagickPathExtent);
2148   blob_support=GetMagickBlobSupport(magick_info);
2149   if ((blob_support != MagickFalse) &&
2150       (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2151     {
2152       if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2153           (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2154         blob_support=MagickFalse;
2155     }
2156   if (blob_support != MagickFalse)
2157     {
2158       /*
2159         Native blob support for this image format.
2160       */
2161       (void) CloseBlob(image);
2162       *image->filename='\0';
2163       (void) WriteImage(clone_info,image,exception);
2164       (void) CloseBlob(image);
2165     }
2166   else
2167     {
2168       char
2169         unique[MagickPathExtent];
2170 
2171       int
2172         file;
2173 
2174       unsigned char
2175         *blob;
2176 
2177       /*
2178         Write file to disk in blob image format.
2179       */
2180       clone_info->custom_stream=(CustomStreamInfo *) NULL;
2181       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2182         sizeof(*blob));
2183       if (blob == (unsigned char *) NULL)
2184         {
2185           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2186             image_info->filename);
2187           clone_info=DestroyImageInfo(clone_info);
2188           return;
2189         }
2190       file=AcquireUniqueFileResource(unique);
2191       if (file == -1)
2192         {
2193           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2194             image_info->filename);
2195           blob=(unsigned char *) RelinquishMagickMemory(blob);
2196           clone_info=DestroyImageInfo(clone_info);
2197           return;
2198         }
2199       clone_info->file=fdopen(file,"wb+");
2200       if (clone_info->file != (FILE *) NULL)
2201         {
2202           ssize_t
2203             count;
2204 
2205           (void) FormatLocaleString(image->filename,MagickPathExtent,
2206             "%s:%s",image->magick,unique);
2207           status=WriteImage(clone_info,image,exception);
2208           (void) CloseBlob(image);
2209           if (status != MagickFalse)
2210             {
2211               (void) fseek(clone_info->file,0,SEEK_SET);
2212               count=(ssize_t) MagickMaxBufferExtent;
2213               while (count == (ssize_t) MagickMaxBufferExtent)
2214               {
2215                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2216                   clone_info->file);
2217                 (void) image_info->custom_stream->writer(blob,(size_t) count,
2218                   image_info->custom_stream->data);
2219               }
2220             }
2221           (void) fclose(clone_info->file);
2222         }
2223       blob=(unsigned char *) RelinquishMagickMemory(blob);
2224       (void) RelinquishUniqueFileResource(unique);
2225     }
2226   clone_info=DestroyImageInfo(clone_info);
2227 }
2228 
2229 /*
2230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2231 %                                                                             %
2232 %                                                                             %
2233 %                                                                             %
2234 %   I m a g e T o F i l e                                                     %
2235 %                                                                             %
2236 %                                                                             %
2237 %                                                                             %
2238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2239 %
2240 %  ImageToFile() writes an image to a file.  It returns MagickFalse if an error
2241 %  occurs otherwise MagickTrue.
2242 %
2243 %  The format of the ImageToFile method is:
2244 %
2245 %       MagickBooleanType ImageToFile(Image *image,char *filename,
2246 %         ExceptionInfo *exception)
2247 %
2248 %  A description of each parameter follows:
2249 %
2250 %    o image: the image.
2251 %
2252 %    o filename: Write the image to this file.
2253 %
2254 %    o exception: return any errors or warnings in this structure.
2255 %
2256 */
ImageToFile(Image * image,char * filename,ExceptionInfo * exception)2257 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
2258   ExceptionInfo *exception)
2259 {
2260   int
2261     file;
2262 
2263   register const unsigned char
2264     *p;
2265 
2266   register size_t
2267     i;
2268 
2269   size_t
2270     length,
2271     quantum;
2272 
2273   ssize_t
2274     count;
2275 
2276   struct stat
2277     file_stats;
2278 
2279   unsigned char
2280     *buffer;
2281 
2282   assert(image != (Image *) NULL);
2283   assert(image->signature == MagickCoreSignature);
2284   assert(image->blob != (BlobInfo *) NULL);
2285   assert(image->blob->type != UndefinedStream);
2286   if (image->debug != MagickFalse)
2287     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
2288   assert(filename != (const char *) NULL);
2289   if (*filename == '\0')
2290     file=AcquireUniqueFileResource(filename);
2291   else
2292     if (LocaleCompare(filename,"-") == 0)
2293       file=fileno(stdout);
2294     else
2295       file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
2296   if (file == -1)
2297     {
2298       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2299       return(MagickFalse);
2300     }
2301   quantum=(size_t) MagickMaxBufferExtent;
2302   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2303     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2304   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2305   if (buffer == (unsigned char *) NULL)
2306     {
2307       file=close(file)-1;
2308       (void) ThrowMagickException(exception,GetMagickModule(),
2309         ResourceLimitError,"MemoryAllocationError","`%s'",filename);
2310       return(MagickFalse);
2311     }
2312   length=0;
2313   p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2314   for (i=0; count > 0; )
2315   {
2316     length=(size_t) count;
2317     for (i=0; i < length; i+=count)
2318     {
2319       count=write(file,p+i,(size_t) (length-i));
2320       if (count <= 0)
2321         {
2322           count=0;
2323           if (errno != EINTR)
2324             break;
2325         }
2326     }
2327     if (i < length)
2328       break;
2329     p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
2330   }
2331   if (LocaleCompare(filename,"-") != 0)
2332     file=close(file);
2333   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2334   if ((file == -1) || (i < length))
2335     {
2336       if (file != -1)
2337         file=close(file);
2338       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
2339       return(MagickFalse);
2340     }
2341   return(MagickTrue);
2342 }
2343 
2344 /*
2345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346 %                                                                             %
2347 %                                                                             %
2348 %                                                                             %
2349 %   I m a g e s T o B l o b                                                   %
2350 %                                                                             %
2351 %                                                                             %
2352 %                                                                             %
2353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2354 %
2355 %  ImagesToBlob() implements direct to memory image formats.  It returns the
2356 %  image sequence as a blob and its length.  The magick member of the ImageInfo
2357 %  structure determines the format of the returned blob (GIF, JPEG,  PNG, etc.)
2358 %
2359 %  Note, some image formats do not permit multiple images to the same image
2360 %  stream (e.g. JPEG).  in this instance, just the first image of the
2361 %  sequence is returned as a blob.
2362 %
2363 %  The format of the ImagesToBlob method is:
2364 %
2365 %      void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2366 %        size_t *length,ExceptionInfo *exception)
2367 %
2368 %  A description of each parameter follows:
2369 %
2370 %    o image_info: the image info.
2371 %
2372 %    o images: the image list.
2373 %
2374 %    o length: return the actual length of the blob.
2375 %
2376 %    o exception: return any errors or warnings in this structure.
2377 %
2378 */
ImagesToBlob(const ImageInfo * image_info,Image * images,size_t * length,ExceptionInfo * exception)2379 MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images,
2380   size_t *length,ExceptionInfo *exception)
2381 {
2382   const MagickInfo
2383     *magick_info;
2384 
2385   ImageInfo
2386     *clone_info;
2387 
2388   MagickBooleanType
2389     status;
2390 
2391   void
2392     *blob;
2393 
2394   assert(image_info != (const ImageInfo *) NULL);
2395   assert(image_info->signature == MagickCoreSignature);
2396   if (image_info->debug != MagickFalse)
2397     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2398       image_info->filename);
2399   assert(images != (Image *) NULL);
2400   assert(images->signature == MagickCoreSignature);
2401   assert(exception != (ExceptionInfo *) NULL);
2402   *length=0;
2403   blob=(unsigned char *) NULL;
2404   clone_info=CloneImageInfo(image_info);
2405   (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2406     exception);
2407   if (*clone_info->magick != '\0')
2408     (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2409   magick_info=GetMagickInfo(images->magick,exception);
2410   if (magick_info == (const MagickInfo *) NULL)
2411     {
2412       (void) ThrowMagickException(exception,GetMagickModule(),
2413         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2414         images->magick);
2415       clone_info=DestroyImageInfo(clone_info);
2416       return(blob);
2417     }
2418   if (GetMagickAdjoin(magick_info) == MagickFalse)
2419     {
2420       clone_info=DestroyImageInfo(clone_info);
2421       return(ImageToBlob(image_info,images,length,exception));
2422     }
2423   (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2424   if (GetMagickBlobSupport(magick_info) != MagickFalse)
2425     {
2426       /*
2427         Native blob support for this images format.
2428       */
2429       clone_info->length=0;
2430       clone_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2431         sizeof(unsigned char));
2432       if (clone_info->blob == (void *) NULL)
2433         (void) ThrowMagickException(exception,GetMagickModule(),
2434           ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2435       else
2436         {
2437           (void) CloseBlob(images);
2438           images->blob->exempt=MagickTrue;
2439           *images->filename='\0';
2440           status=WriteImages(clone_info,images,images->filename,exception);
2441           *length=images->blob->length;
2442           blob=DetachBlob(images->blob);
2443           if (blob == (void *) NULL)
2444             clone_info->blob=RelinquishMagickMemory(clone_info->blob);
2445           else if (status == MagickFalse)
2446             blob=RelinquishMagickMemory(blob);
2447           else
2448             blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2449         }
2450     }
2451   else
2452     {
2453       char
2454         filename[MagickPathExtent],
2455         unique[MagickPathExtent];
2456 
2457       int
2458         file;
2459 
2460       /*
2461         Write file to disk in blob images format.
2462       */
2463       file=AcquireUniqueFileResource(unique);
2464       if (file == -1)
2465         {
2466           ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2467             image_info->filename);
2468         }
2469       else
2470         {
2471           clone_info->file=fdopen(file,"wb");
2472           if (clone_info->file != (FILE *) NULL)
2473             {
2474               (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2475                 images->magick,unique);
2476               status=WriteImages(clone_info,images,filename,exception);
2477               (void) CloseBlob(images);
2478               (void) fclose(clone_info->file);
2479               if (status != MagickFalse)
2480                 blob=FileToBlob(unique,~0UL,length,exception);
2481             }
2482           (void) RelinquishUniqueFileResource(unique);
2483         }
2484     }
2485   clone_info=DestroyImageInfo(clone_info);
2486   return(blob);
2487 }
2488 
2489 /*
2490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2491 %                                                                             %
2492 %                                                                             %
2493 %                                                                             %
2494 +  I m a g e s T o C u s t o m B l o b                                        %
2495 %                                                                             %
2496 %                                                                             %
2497 %                                                                             %
2498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2499 %
2500 %  ImagesToCustomStream() is the equivalent of WriteImages(), but writes the
2501 %  formatted "file" to the custom stream rather than to an actual file.
2502 %
2503 %  The format of the ImageToCustomStream method is:
2504 %
2505 %      void ImagesToCustomStream(const ImageInfo *image_info,Image *images,
2506 %        ExceptionInfo *exception)
2507 %
2508 %  A description of each parameter follows:
2509 %
2510 %    o image_info: the image info.
2511 %
2512 %    o images: the image list.
2513 %
2514 %    o exception: return any errors or warnings in this structure.
2515 %
2516 */
ImagesToCustomStream(const ImageInfo * image_info,Image * images,ExceptionInfo * exception)2517 MagickExport void ImagesToCustomStream(const ImageInfo *image_info,
2518   Image *images,ExceptionInfo *exception)
2519 {
2520   const MagickInfo
2521     *magick_info;
2522 
2523   ImageInfo
2524     *clone_info;
2525 
2526   MagickBooleanType
2527     blob_support,
2528     status;
2529 
2530   assert(image_info != (const ImageInfo *) NULL);
2531   assert(image_info->signature == MagickCoreSignature);
2532   if (image_info->debug != MagickFalse)
2533     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2534       image_info->filename);
2535   assert(images != (Image *) NULL);
2536   assert(images->signature == MagickCoreSignature);
2537   assert(image_info->custom_stream != (CustomStreamInfo *) NULL);
2538   assert(image_info->custom_stream->signature == MagickCoreSignature);
2539   assert(image_info->custom_stream->reader != (CustomStreamHandler) NULL);
2540   assert(image_info->custom_stream->writer != (CustomStreamHandler) NULL);
2541   assert(exception != (ExceptionInfo *) NULL);
2542   clone_info=CloneImageInfo(image_info);
2543   (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(images),
2544     exception);
2545   if (*clone_info->magick != '\0')
2546     (void) CopyMagickString(images->magick,clone_info->magick,MagickPathExtent);
2547   magick_info=GetMagickInfo(images->magick,exception);
2548   if (magick_info == (const MagickInfo *) NULL)
2549     {
2550       (void) ThrowMagickException(exception,GetMagickModule(),
2551         MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'",
2552         images->magick);
2553       clone_info=DestroyImageInfo(clone_info);
2554       return;
2555     }
2556   (void) CopyMagickString(clone_info->magick,images->magick,MagickPathExtent);
2557   blob_support=GetMagickBlobSupport(magick_info);
2558   if ((blob_support != MagickFalse) &&
2559       (GetMagickEncoderSeekableStream(magick_info) != MagickFalse))
2560     {
2561       if ((clone_info->custom_stream->seeker == (CustomStreamSeeker) NULL) ||
2562           (clone_info->custom_stream->teller == (CustomStreamTeller) NULL))
2563         blob_support=MagickFalse;
2564     }
2565   if (blob_support != MagickFalse)
2566     {
2567       /*
2568         Native blob support for this image format.
2569       */
2570       (void) CloseBlob(images);
2571       *images->filename='\0';
2572       (void) WriteImages(clone_info,images,images->filename,exception);
2573       (void) CloseBlob(images);
2574     }
2575   else
2576     {
2577       char
2578         filename[MagickPathExtent],
2579         unique[MagickPathExtent];
2580 
2581       int
2582         file;
2583 
2584       unsigned char
2585         *blob;
2586 
2587       /*
2588         Write file to disk in blob image format.
2589       */
2590       clone_info->custom_stream=(CustomStreamInfo *) NULL;
2591       blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
2592         sizeof(*blob));
2593       if (blob == (unsigned char *) NULL)
2594         {
2595           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2596             image_info->filename);
2597           clone_info=DestroyImageInfo(clone_info);
2598           return;
2599         }
2600       file=AcquireUniqueFileResource(unique);
2601       if (file == -1)
2602         {
2603           ThrowFileException(exception,BlobError,"UnableToWriteBlob",
2604             image_info->filename);
2605           blob=(unsigned char *) RelinquishMagickMemory(blob);
2606           clone_info=DestroyImageInfo(clone_info);
2607           return;
2608         }
2609       clone_info->file=fdopen(file,"wb+");
2610       if (clone_info->file != (FILE *) NULL)
2611         {
2612           ssize_t
2613             count;
2614 
2615           (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2616             images->magick,unique);
2617           status=WriteImages(clone_info,images,filename,exception);
2618           (void) CloseBlob(images);
2619           if (status != MagickFalse)
2620             {
2621               (void) fseek(clone_info->file,0,SEEK_SET);
2622               count=(ssize_t) MagickMaxBufferExtent;
2623               while (count == (ssize_t) MagickMaxBufferExtent)
2624               {
2625                 count=(ssize_t) fread(blob,sizeof(*blob),MagickMaxBufferExtent,
2626                   clone_info->file);
2627                 (void) image_info->custom_stream->writer(blob,(size_t) count,
2628                   image_info->custom_stream->data);
2629               }
2630             }
2631           (void) fclose(clone_info->file);
2632         }
2633       blob=(unsigned char *) RelinquishMagickMemory(blob);
2634       (void) RelinquishUniqueFileResource(unique);
2635     }
2636   clone_info=DestroyImageInfo(clone_info);
2637 }
2638 
2639 /*
2640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2641 %                                                                             %
2642 %                                                                             %
2643 %                                                                             %
2644 %   I n j e c t I m a g e B l o b                                             %
2645 %                                                                             %
2646 %                                                                             %
2647 %                                                                             %
2648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2649 %
2650 %  InjectImageBlob() injects the image with a copy of itself in the specified
2651 %  format (e.g. inject JPEG into a PDF image).
2652 %
2653 %  The format of the InjectImageBlob method is:
2654 %
2655 %      MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2656 %        Image *image,Image *inject_image,const char *format,
2657 %        ExceptionInfo *exception)
2658 %
2659 %  A description of each parameter follows:
2660 %
2661 %    o image_info: the image info..
2662 %
2663 %    o image: the image.
2664 %
2665 %    o inject_image: inject into the image stream.
2666 %
2667 %    o format: the image format.
2668 %
2669 %    o exception: return any errors or warnings in this structure.
2670 %
2671 */
InjectImageBlob(const ImageInfo * image_info,Image * image,Image * inject_image,const char * format,ExceptionInfo * exception)2672 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2673   Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2674 {
2675   char
2676     filename[MagickPathExtent];
2677 
2678   FILE
2679     *unique_file;
2680 
2681   Image
2682     *byte_image;
2683 
2684   ImageInfo
2685     *write_info;
2686 
2687   int
2688     file;
2689 
2690   MagickBooleanType
2691     status;
2692 
2693   register ssize_t
2694     i;
2695 
2696   size_t
2697     quantum;
2698 
2699   ssize_t
2700     count;
2701 
2702   struct stat
2703     file_stats;
2704 
2705   unsigned char
2706     *buffer;
2707 
2708   /*
2709     Write inject image to a temporary file.
2710   */
2711   assert(image_info != (ImageInfo *) NULL);
2712   assert(image_info->signature == MagickCoreSignature);
2713   assert(image != (Image *) NULL);
2714   assert(image->signature == MagickCoreSignature);
2715   if (image->debug != MagickFalse)
2716     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2717   assert(inject_image != (Image *) NULL);
2718   assert(inject_image->signature == MagickCoreSignature);
2719   assert(exception != (ExceptionInfo *) NULL);
2720   unique_file=(FILE *) NULL;
2721   file=AcquireUniqueFileResource(filename);
2722   if (file != -1)
2723     unique_file=fdopen(file,"wb");
2724   if ((file == -1) || (unique_file == (FILE *) NULL))
2725     {
2726       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2727       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2728         image->filename);
2729       return(MagickFalse);
2730     }
2731   byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2732   if (byte_image == (Image *) NULL)
2733     {
2734       (void) fclose(unique_file);
2735       (void) RelinquishUniqueFileResource(filename);
2736       return(MagickFalse);
2737     }
2738   (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2739     format,filename);
2740   DestroyBlob(byte_image);
2741   byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2742   write_info=CloneImageInfo(image_info);
2743   SetImageInfoFile(write_info,unique_file);
2744   status=WriteImage(write_info,byte_image,exception);
2745   write_info=DestroyImageInfo(write_info);
2746   byte_image=DestroyImage(byte_image);
2747   (void) fclose(unique_file);
2748   if (status == MagickFalse)
2749     {
2750       (void) RelinquishUniqueFileResource(filename);
2751       return(MagickFalse);
2752     }
2753   /*
2754     Inject into image stream.
2755   */
2756   file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2757   if (file == -1)
2758     {
2759       (void) RelinquishUniqueFileResource(filename);
2760       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2761         image_info->filename);
2762       return(MagickFalse);
2763     }
2764   quantum=(size_t) MagickMaxBufferExtent;
2765   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2766     quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2767   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2768   if (buffer == (unsigned char *) NULL)
2769     {
2770       (void) RelinquishUniqueFileResource(filename);
2771       file=close(file);
2772       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2773         image->filename);
2774     }
2775   for (i=0; ; i+=count)
2776   {
2777     count=read(file,buffer,quantum);
2778     if (count <= 0)
2779       {
2780         count=0;
2781         if (errno != EINTR)
2782           break;
2783       }
2784     status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2785       MagickFalse;
2786   }
2787   file=close(file);
2788   if (file == -1)
2789     ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2790   (void) RelinquishUniqueFileResource(filename);
2791   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2792   return(status);
2793 }
2794 
2795 /*
2796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2797 %                                                                             %
2798 %                                                                             %
2799 %                                                                             %
2800 %   I s B l o b E x e m p t                                                   %
2801 %                                                                             %
2802 %                                                                             %
2803 %                                                                             %
2804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2805 %
2806 %  IsBlobExempt() returns true if the blob is exempt.
2807 %
2808 %  The format of the IsBlobExempt method is:
2809 %
2810 %       MagickBooleanType IsBlobExempt(const Image *image)
2811 %
2812 %  A description of each parameter follows:
2813 %
2814 %    o image: the image.
2815 %
2816 */
IsBlobExempt(const Image * image)2817 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2818 {
2819   assert(image != (const Image *) NULL);
2820   assert(image->signature == MagickCoreSignature);
2821   if (image->debug != MagickFalse)
2822     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2823   return(image->blob->exempt);
2824 }
2825 
2826 /*
2827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2828 %                                                                             %
2829 %                                                                             %
2830 %                                                                             %
2831 %   I s B l o b S e e k a b l e                                               %
2832 %                                                                             %
2833 %                                                                             %
2834 %                                                                             %
2835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2836 %
2837 %  IsBlobSeekable() returns true if the blob is seekable.
2838 %
2839 %  The format of the IsBlobSeekable method is:
2840 %
2841 %       MagickBooleanType IsBlobSeekable(const Image *image)
2842 %
2843 %  A description of each parameter follows:
2844 %
2845 %    o image: the image.
2846 %
2847 */
IsBlobSeekable(const Image * image)2848 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2849 {
2850   BlobInfo
2851     *magick_restrict blob_info;
2852 
2853   assert(image != (const Image *) NULL);
2854   assert(image->signature == MagickCoreSignature);
2855   if (image->debug != MagickFalse)
2856     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2857   blob_info=image->blob;
2858   switch (blob_info->type)
2859   {
2860     case BlobStream:
2861       return(MagickTrue);
2862     case FileStream:
2863     {
2864       int
2865         status;
2866 
2867       if (blob_info->file_info.file == (FILE *) NULL)
2868         return(MagickFalse);
2869       status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2870       return(status == -1 ? MagickFalse : MagickTrue);
2871     }
2872     case ZipStream:
2873     {
2874 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2875       MagickOffsetType
2876         offset;
2877 
2878       if (blob_info->file_info.gzfile == (gzFile) NULL)
2879         return(MagickFalse);
2880       offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2881       return(offset < 0 ? MagickFalse : MagickTrue);
2882 #else
2883       break;
2884 #endif
2885     }
2886     case UndefinedStream:
2887     case BZipStream:
2888     case FifoStream:
2889     case PipeStream:
2890     case StandardStream:
2891       break;
2892     case CustomStream:
2893     {
2894       if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
2895           (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
2896         return(MagickTrue);
2897       break;
2898     }
2899     default:
2900       break;
2901   }
2902   return(MagickFalse);
2903 }
2904 
2905 /*
2906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2907 %                                                                             %
2908 %                                                                             %
2909 %                                                                             %
2910 %   I s B l o b T e m p o r a r y                                             %
2911 %                                                                             %
2912 %                                                                             %
2913 %                                                                             %
2914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2915 %
2916 %  IsBlobTemporary() returns true if the blob is temporary.
2917 %
2918 %  The format of the IsBlobTemporary method is:
2919 %
2920 %       MagickBooleanType IsBlobTemporary(const Image *image)
2921 %
2922 %  A description of each parameter follows:
2923 %
2924 %    o image: the image.
2925 %
2926 */
IsBlobTemporary(const Image * image)2927 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2928 {
2929   assert(image != (const Image *) NULL);
2930   assert(image->signature == MagickCoreSignature);
2931   if (image->debug != MagickFalse)
2932     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2933   return(image->blob->temporary);
2934 }
2935 
2936 /*
2937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2938 %                                                                             %
2939 %                                                                             %
2940 %                                                                             %
2941 +  M a p B l o b                                                              %
2942 %                                                                             %
2943 %                                                                             %
2944 %                                                                             %
2945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2946 %
2947 %  MapBlob() creates a mapping from a file to a binary large object.
2948 %
2949 %  The format of the MapBlob method is:
2950 %
2951 %      void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2952 %        const size_t length)
2953 %
2954 %  A description of each parameter follows:
2955 %
2956 %    o file: map this file descriptor.
2957 %
2958 %    o mode: ReadMode, WriteMode, or IOMode.
2959 %
2960 %    o offset: starting at this offset within the file.
2961 %
2962 %    o length: the length of the mapping is returned in this pointer.
2963 %
2964 */
MapBlob(int file,const MapMode mode,const MagickOffsetType offset,const size_t length)2965 MagickExport void *MapBlob(int file,const MapMode mode,
2966   const MagickOffsetType offset,const size_t length)
2967 {
2968 #if defined(MAGICKCORE_HAVE_MMAP)
2969   int
2970     flags,
2971     protection;
2972 
2973   void
2974     *map;
2975 
2976   /*
2977     Map file.
2978   */
2979   flags=0;
2980   if (file == -1)
2981 #if defined(MAP_ANONYMOUS)
2982     flags|=MAP_ANONYMOUS;
2983 #else
2984     return(NULL);
2985 #endif
2986   switch (mode)
2987   {
2988     case ReadMode:
2989     default:
2990     {
2991       protection=PROT_READ;
2992       flags|=MAP_PRIVATE;
2993       break;
2994     }
2995     case WriteMode:
2996     {
2997       protection=PROT_WRITE;
2998       flags|=MAP_SHARED;
2999       break;
3000     }
3001     case IOMode:
3002     {
3003       protection=PROT_READ | PROT_WRITE;
3004       flags|=MAP_SHARED;
3005       break;
3006     }
3007   }
3008 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
3009   map=mmap((char *) NULL,length,protection,flags,file,offset);
3010 #else
3011   map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,offset);
3012   if (map == MAP_FAILED)
3013     map=mmap((char *) NULL,length,protection,flags,file,offset);
3014 #endif
3015   if (map == MAP_FAILED)
3016     return(NULL);
3017   return(map);
3018 #else
3019   (void) file;
3020   (void) mode;
3021   (void) offset;
3022   (void) length;
3023   return(NULL);
3024 #endif
3025 }
3026 
3027 /*
3028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3029 %                                                                             %
3030 %                                                                             %
3031 %                                                                             %
3032 +  M S B O r d e r L o n g                                                    %
3033 %                                                                             %
3034 %                                                                             %
3035 %                                                                             %
3036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3037 %
3038 %  MSBOrderLong() converts a least-significant byte first buffer of integers to
3039 %  most-significant byte first.
3040 %
3041 %  The format of the MSBOrderLong method is:
3042 %
3043 %      void MSBOrderLong(unsigned char *buffer,const size_t length)
3044 %
3045 %  A description of each parameter follows.
3046 %
3047 %   o  buffer:  Specifies a pointer to a buffer of integers.
3048 %
3049 %   o  length:  Specifies the length of the buffer.
3050 %
3051 */
MSBOrderLong(unsigned char * buffer,const size_t length)3052 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
3053 {
3054   int
3055     c;
3056 
3057   register unsigned char
3058     *p,
3059     *q;
3060 
3061   assert(buffer != (unsigned char *) NULL);
3062   q=buffer+length;
3063   while (buffer < q)
3064   {
3065     p=buffer+3;
3066     c=(int) (*p);
3067     *p=(*buffer);
3068     *buffer++=(unsigned char) c;
3069     p=buffer+1;
3070     c=(int) (*p);
3071     *p=(*buffer);
3072     *buffer++=(unsigned char) c;
3073     buffer+=2;
3074   }
3075 }
3076 
3077 /*
3078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3079 %                                                                             %
3080 %                                                                             %
3081 %                                                                             %
3082 +  M S B O r d e r S h o r t                                                  %
3083 %                                                                             %
3084 %                                                                             %
3085 %                                                                             %
3086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3087 %
3088 %  MSBOrderShort() converts a least-significant byte first buffer of integers
3089 %  to most-significant byte first.
3090 %
3091 %  The format of the MSBOrderShort method is:
3092 %
3093 %      void MSBOrderShort(unsigned char *p,const size_t length)
3094 %
3095 %  A description of each parameter follows.
3096 %
3097 %   o  p:  Specifies a pointer to a buffer of integers.
3098 %
3099 %   o  length:  Specifies the length of the buffer.
3100 %
3101 */
MSBOrderShort(unsigned char * p,const size_t length)3102 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
3103 {
3104   int
3105     c;
3106 
3107   register unsigned char
3108     *q;
3109 
3110   assert(p != (unsigned char *) NULL);
3111   q=p+length;
3112   while (p < q)
3113   {
3114     c=(int) (*p);
3115     *p=(*(p+1));
3116     p++;
3117     *p++=(unsigned char) c;
3118   }
3119 }
3120 
3121 /*
3122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3123 %                                                                             %
3124 %                                                                             %
3125 %                                                                             %
3126 +   O p e n B l o b                                                           %
3127 %                                                                             %
3128 %                                                                             %
3129 %                                                                             %
3130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3131 %
3132 %  OpenBlob() opens a file associated with the image.  A file name of '-' sets
3133 %  the file to stdin for type 'r' and stdout for type 'w'.  If the filename
3134 %  suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
3135 %  compressed for type 'w'.  If the filename prefix is '|', it is piped to or
3136 %  from a system command.
3137 %
3138 %  The format of the OpenBlob method is:
3139 %
3140 %       MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
3141 %        const BlobMode mode,ExceptionInfo *exception)
3142 %
3143 %  A description of each parameter follows:
3144 %
3145 %    o image_info: the image info.
3146 %
3147 %    o image: the image.
3148 %
3149 %    o mode: the mode for opening the file.
3150 %
3151 */
3152 
SetStreamBuffering(const ImageInfo * image_info,Image * image)3153 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
3154   Image *image)
3155 {
3156   const char
3157     *option;
3158 
3159   int
3160     status;
3161 
3162   size_t
3163     size;
3164 
3165   size=MagickMinBufferExtent;
3166   option=GetImageOption(image_info,"stream:buffer-size");
3167   if (option != (const char *) NULL)
3168     size=StringToUnsignedLong(option);
3169   status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
3170     _IONBF : _IOFBF,size);
3171   return(status == 0 ? MagickTrue : MagickFalse);
3172 }
3173 
OpenBlob(const ImageInfo * image_info,Image * image,const BlobMode mode,ExceptionInfo * exception)3174 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
3175   Image *image,const BlobMode mode,ExceptionInfo *exception)
3176 {
3177   BlobInfo
3178     *magick_restrict blob_info;
3179 
3180   char
3181     extension[MagickPathExtent],
3182     filename[MagickPathExtent];
3183 
3184   const char
3185     *type;
3186 
3187   MagickBooleanType
3188     status;
3189 
3190   PolicyRights
3191     rights;
3192 
3193   assert(image_info != (ImageInfo *) NULL);
3194   assert(image_info->signature == MagickCoreSignature);
3195   if (image_info->debug != MagickFalse)
3196     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3197       image_info->filename);
3198   assert(image != (Image *) NULL);
3199   assert(image->signature == MagickCoreSignature);
3200   blob_info=image->blob;
3201   if (image_info->blob != (void *) NULL)
3202     {
3203       if (image_info->stream != (StreamHandler) NULL)
3204         blob_info->stream=(StreamHandler) image_info->stream;
3205       AttachBlob(blob_info,image_info->blob,image_info->length);
3206       return(MagickTrue);
3207     }
3208   if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3209       (*image->filename == '\0'))
3210     {
3211       blob_info->type=CustomStream;
3212       blob_info->custom_stream=image_info->custom_stream;
3213       return(MagickTrue);
3214     }
3215   (void) DetachBlob(blob_info);
3216   blob_info->mode=mode;
3217   switch (mode)
3218   {
3219     default: type="r"; break;
3220     case ReadBlobMode: type="r"; break;
3221     case ReadBinaryBlobMode: type="rb"; break;
3222     case WriteBlobMode: type="w"; break;
3223     case WriteBinaryBlobMode: type="w+b"; break;
3224     case AppendBlobMode: type="a"; break;
3225     case AppendBinaryBlobMode: type="a+b"; break;
3226   }
3227   if (*type != 'r')
3228     blob_info->synchronize=image_info->synchronize;
3229   if (image_info->stream != (StreamHandler) NULL)
3230     {
3231       blob_info->stream=image_info->stream;
3232       if (*type == 'w')
3233         {
3234           blob_info->type=FifoStream;
3235           return(MagickTrue);
3236         }
3237     }
3238   /*
3239     Open image file.
3240   */
3241   *filename='\0';
3242   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3243   rights=ReadPolicyRights;
3244   if (*type == 'w')
3245     rights=WritePolicyRights;
3246   if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
3247     {
3248       errno=EPERM;
3249       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
3250         "NotAuthorized","`%s'",filename);
3251       return(MagickFalse);
3252     }
3253   if ((LocaleCompare(filename,"-") == 0) ||
3254       ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3255     {
3256       blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3257 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3258       if (strchr(type,'b') != (char *) NULL)
3259         setmode(fileno(blob_info->file_info.file),_O_BINARY);
3260 #endif
3261       blob_info->type=StandardStream;
3262       blob_info->exempt=MagickTrue;
3263       return(SetStreamBuffering(image_info,image));
3264     }
3265   if ((LocaleNCompare(filename,"fd:",3) == 0) &&
3266       (IsGeometry(filename+3) != MagickFalse))
3267     {
3268       char
3269         fileMode[MagickPathExtent];
3270 
3271       *fileMode =(*type);
3272       fileMode[1]='\0';
3273       blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
3274       if (blob_info->file_info.file == (FILE *) NULL)
3275         {
3276           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3277           return(MagickFalse);
3278         }
3279 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3280       if (strchr(type,'b') != (char *) NULL)
3281         setmode(fileno(blob_info->file_info.file),_O_BINARY);
3282 #endif
3283       blob_info->type=FileStream;
3284       blob_info->exempt=MagickTrue;
3285       return(SetStreamBuffering(image_info,image));
3286     }
3287 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3288   if (*filename == '|')
3289     {
3290       char
3291         fileMode[MagickPathExtent],
3292         *sanitize_command;
3293 
3294       /*
3295         Pipe image to or from a system command.
3296       */
3297 #if defined(SIGPIPE)
3298       if (*type == 'w')
3299         (void) signal(SIGPIPE,SIG_IGN);
3300 #endif
3301       *fileMode =(*type);
3302       fileMode[1]='\0';
3303       sanitize_command=SanitizeString(filename+1);
3304       blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3305       sanitize_command=DestroyString(sanitize_command);
3306       if (blob_info->file_info.file == (FILE *) NULL)
3307         {
3308           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3309           return(MagickFalse);
3310         }
3311       blob_info->type=PipeStream;
3312       blob_info->exempt=MagickTrue;
3313       return(SetStreamBuffering(image_info,image));
3314     }
3315 #endif
3316   status=GetPathAttributes(filename,&blob_info->properties);
3317 #if defined(S_ISFIFO)
3318   if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3319     {
3320       blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3321       if (blob_info->file_info.file == (FILE *) NULL)
3322         {
3323           ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3324           return(MagickFalse);
3325         }
3326       blob_info->type=FileStream;
3327       blob_info->exempt=MagickTrue;
3328       return(SetStreamBuffering(image_info,image));
3329     }
3330 #endif
3331   GetPathComponent(image->filename,ExtensionPath,extension);
3332   if (*type == 'w')
3333     {
3334       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3335       if ((image_info->adjoin == MagickFalse) ||
3336           (strchr(filename,'%') != (char *) NULL))
3337         {
3338           /*
3339             Form filename for multi-part images.
3340           */
3341           (void) InterpretImageFilename(image_info,image,image->filename,(int)
3342             image->scene,filename,exception);
3343           if ((LocaleCompare(filename,image->filename) == 0) &&
3344               ((GetPreviousImageInList(image) != (Image *) NULL) ||
3345                (GetNextImageInList(image) != (Image *) NULL)))
3346             {
3347               char
3348                 path[MagickPathExtent];
3349 
3350               GetPathComponent(image->filename,RootPath,path);
3351               if (*extension == '\0')
3352                 (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
3353                   path,(double) image->scene);
3354               else
3355                 (void) FormatLocaleString(filename,MagickPathExtent,
3356                   "%s-%.20g.%s",path,(double) image->scene,extension);
3357             }
3358           (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3359 #if defined(macintosh)
3360           SetApplicationType(filename,image_info->magick,'8BIM');
3361 #endif
3362         }
3363     }
3364   if (image_info->file != (FILE *) NULL)
3365     {
3366       blob_info->file_info.file=image_info->file;
3367       blob_info->type=FileStream;
3368       blob_info->exempt=MagickTrue;
3369     }
3370   else
3371     if (*type == 'r')
3372       {
3373         blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3374         if (blob_info->file_info.file != (FILE *) NULL)
3375           {
3376             size_t
3377               count;
3378 
3379             unsigned char
3380               magick[3];
3381 
3382             blob_info->type=FileStream;
3383             (void) SetStreamBuffering(image_info,image);
3384             (void) memset(magick,0,sizeof(magick));
3385             count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3386             (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3387 #if defined(MAGICKCORE_POSIX_SUPPORT)
3388             (void) fflush(blob_info->file_info.file);
3389 #endif
3390             (void) LogMagickEvent(BlobEvent,GetMagickModule(),
3391                "  read %.20g magic header bytes",(double) count);
3392 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3393             if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3394                 ((int) magick[2] == 0x08))
3395               {
3396                 if (blob_info->file_info.file != (FILE *) NULL)
3397                   (void) fclose(blob_info->file_info.file);
3398                 blob_info->file_info.file=(FILE *) NULL;
3399                 blob_info->file_info.gzfile=gzopen(filename,"rb");
3400                 if (blob_info->file_info.gzfile != (gzFile) NULL)
3401                   blob_info->type=ZipStream;
3402                }
3403 #endif
3404 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3405             if (strncmp((char *) magick,"BZh",3) == 0)
3406               {
3407                 if (blob_info->file_info.file != (FILE *) NULL)
3408                   (void) fclose(blob_info->file_info.file);
3409                 blob_info->file_info.file=(FILE *) NULL;
3410                 blob_info->file_info.bzfile=BZ2_bzopen(filename,"r");
3411                 if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3412                   blob_info->type=BZipStream;
3413               }
3414 #endif
3415             if (blob_info->type == FileStream)
3416               {
3417                 const MagickInfo
3418                   *magick_info;
3419 
3420                 ExceptionInfo
3421                   *sans_exception;
3422 
3423                 size_t
3424                   length;
3425 
3426                 sans_exception=AcquireExceptionInfo();
3427                 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3428                 sans_exception=DestroyExceptionInfo(sans_exception);
3429                 length=(size_t) blob_info->properties.st_size;
3430                 if ((magick_info != (const MagickInfo *) NULL) &&
3431                     (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3432                     (length > MagickMaxBufferExtent) &&
3433                     (AcquireMagickResource(MapResource,length) != MagickFalse))
3434                   {
3435                     void
3436                       *blob;
3437 
3438                     blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3439                       length);
3440                     if (blob == (void *) NULL)
3441                       RelinquishMagickResource(MapResource,length);
3442                     else
3443                       {
3444                         /*
3445                           Format supports blobs-- use memory-mapped I/O.
3446                         */
3447                         if (image_info->file != (FILE *) NULL)
3448                           blob_info->exempt=MagickFalse;
3449                         else
3450                           {
3451                             (void) fclose(blob_info->file_info.file);
3452                             blob_info->file_info.file=(FILE *) NULL;
3453                           }
3454                         AttachBlob(blob_info,blob,length);
3455                         blob_info->mapped=MagickTrue;
3456                       }
3457                   }
3458               }
3459           }
3460         }
3461       else
3462 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3463         if ((LocaleCompare(extension,"Z") == 0) ||
3464             (LocaleCompare(extension,"gz") == 0) ||
3465             (LocaleCompare(extension,"wmz") == 0) ||
3466             (LocaleCompare(extension,"svgz") == 0))
3467           {
3468             blob_info->file_info.gzfile=gzopen(filename,"wb");
3469             if (blob_info->file_info.gzfile != (gzFile) NULL)
3470               blob_info->type=ZipStream;
3471           }
3472         else
3473 #endif
3474 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3475           if (LocaleCompare(extension,"bz2") == 0)
3476             {
3477               blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
3478               if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3479                 blob_info->type=BZipStream;
3480             }
3481           else
3482 #endif
3483             {
3484               blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3485               if (blob_info->file_info.file != (FILE *) NULL)
3486                 {
3487                   blob_info->type=FileStream;
3488                   (void) SetStreamBuffering(image_info,image);
3489                 }
3490        }
3491   blob_info->status=MagickFalse;
3492   if (blob_info->type != UndefinedStream)
3493     blob_info->size=GetBlobSize(image);
3494   else
3495     {
3496       ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3497       return(MagickFalse);
3498     }
3499   return(MagickTrue);
3500 }
3501 
3502 /*
3503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3504 %                                                                             %
3505 %                                                                             %
3506 %                                                                             %
3507 +   P i n g B l o b                                                           %
3508 %                                                                             %
3509 %                                                                             %
3510 %                                                                             %
3511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3512 %
3513 %  PingBlob() returns all the attributes of an image or image sequence except
3514 %  for the pixels.  It is much faster and consumes far less memory than
3515 %  BlobToImage().  On failure, a NULL image is returned and exception
3516 %  describes the reason for the failure.
3517 %
3518 %  The format of the PingBlob method is:
3519 %
3520 %      Image *PingBlob(const ImageInfo *image_info,const void *blob,
3521 %        const size_t length,ExceptionInfo *exception)
3522 %
3523 %  A description of each parameter follows:
3524 %
3525 %    o image_info: the image info.
3526 %
3527 %    o blob: the address of a character stream in one of the image formats
3528 %      understood by ImageMagick.
3529 %
3530 %    o length: This size_t integer reflects the length in bytes of the blob.
3531 %
3532 %    o exception: return any errors or warnings in this structure.
3533 %
3534 */
3535 
3536 #if defined(__cplusplus) || defined(c_plusplus)
3537 extern "C" {
3538 #endif
3539 
PingStream(const Image * magick_unused (image),const void * magick_unused (pixels),const size_t columns)3540 static size_t PingStream(const Image *magick_unused(image),
3541   const void *magick_unused(pixels),const size_t columns)
3542 {
3543   magick_unreferenced(image);
3544   magick_unreferenced(pixels);
3545   return(columns);
3546 }
3547 
3548 #if defined(__cplusplus) || defined(c_plusplus)
3549 }
3550 #endif
3551 
PingBlob(const ImageInfo * image_info,const void * blob,const size_t length,ExceptionInfo * exception)3552 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3553   const size_t length,ExceptionInfo *exception)
3554 {
3555   const MagickInfo
3556     *magick_info;
3557 
3558   Image
3559     *image;
3560 
3561   ImageInfo
3562     *clone_info,
3563     *ping_info;
3564 
3565   MagickBooleanType
3566     status;
3567 
3568   assert(image_info != (ImageInfo *) NULL);
3569   assert(image_info->signature == MagickCoreSignature);
3570   if (image_info->debug != MagickFalse)
3571     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3572       image_info->filename);
3573   assert(exception != (ExceptionInfo *) NULL);
3574   if ((blob == (const void *) NULL) || (length == 0))
3575     {
3576       (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3577         "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3578       return((Image *) NULL);
3579     }
3580   ping_info=CloneImageInfo(image_info);
3581   ping_info->blob=(void *) blob;
3582   ping_info->length=length;
3583   ping_info->ping=MagickTrue;
3584   if (*ping_info->magick == '\0')
3585     (void) SetImageInfo(ping_info,0,exception);
3586   magick_info=GetMagickInfo(ping_info->magick,exception);
3587   if (magick_info == (const MagickInfo *) NULL)
3588     {
3589       (void) ThrowMagickException(exception,GetMagickModule(),
3590         MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3591         ping_info->magick);
3592       ping_info=DestroyImageInfo(ping_info);
3593       return((Image *) NULL);
3594     }
3595   if (GetMagickBlobSupport(magick_info) != MagickFalse)
3596     {
3597       char
3598         filename[MagickPathExtent];
3599 
3600       /*
3601         Native blob support for this image format.
3602       */
3603       (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3604       (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3605         ping_info->magick,filename);
3606       image=ReadStream(ping_info,&PingStream,exception);
3607       if (image != (Image *) NULL)
3608         (void) DetachBlob(image->blob);
3609       ping_info=DestroyImageInfo(ping_info);
3610       return(image);
3611     }
3612   /*
3613     Write blob to a temporary file on disk.
3614   */
3615   ping_info->blob=(void *) NULL;
3616   ping_info->length=0;
3617   *ping_info->filename='\0';
3618   status=BlobToFile(ping_info->filename,blob,length,exception);
3619   if (status == MagickFalse)
3620     {
3621       (void) RelinquishUniqueFileResource(ping_info->filename);
3622       ping_info=DestroyImageInfo(ping_info);
3623       return((Image *) NULL);
3624     }
3625   clone_info=CloneImageInfo(ping_info);
3626   (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3627     ping_info->magick,ping_info->filename);
3628   image=ReadStream(clone_info,&PingStream,exception);
3629   if (image != (Image *) NULL)
3630     {
3631       Image
3632         *images;
3633 
3634       /*
3635         Restore original filenames and image format.
3636       */
3637       for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3638       {
3639         (void) CopyMagickString(images->filename,image_info->filename,
3640           MagickPathExtent);
3641         (void) CopyMagickString(images->magick_filename,image_info->filename,
3642           MagickPathExtent);
3643         (void) CopyMagickString(images->magick,magick_info->name,
3644           MagickPathExtent);
3645         images=GetNextImageInList(images);
3646       }
3647     }
3648   clone_info=DestroyImageInfo(clone_info);
3649   (void) RelinquishUniqueFileResource(ping_info->filename);
3650   ping_info=DestroyImageInfo(ping_info);
3651   return(image);
3652 }
3653 
3654 /*
3655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3656 %                                                                             %
3657 %                                                                             %
3658 %                                                                             %
3659 +  R e a d B l o b                                                            %
3660 %                                                                             %
3661 %                                                                             %
3662 %                                                                             %
3663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3664 %
3665 %  ReadBlob() reads data from the blob or image file and returns it.  It
3666 %  returns the number of bytes read. If length is zero, ReadBlob() returns
3667 %  zero and has no other results. If length is greater than SSIZE_MAX, the
3668 %  result is unspecified.
3669 %
3670 %  The format of the ReadBlob method is:
3671 %
3672 %      ssize_t ReadBlob(Image *image,const size_t length,void *data)
3673 %
3674 %  A description of each parameter follows:
3675 %
3676 %    o image: the image.
3677 %
3678 %    o length:  Specifies an integer representing the number of bytes to read
3679 %      from the file.
3680 %
3681 %    o data:  Specifies an area to place the information requested from the
3682 %      file.
3683 %
3684 */
ReadBlob(Image * image,const size_t length,void * data)3685 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3686 {
3687   BlobInfo
3688     *magick_restrict blob_info;
3689 
3690   int
3691     c;
3692 
3693   register unsigned char
3694     *q;
3695 
3696   ssize_t
3697     count;
3698 
3699   assert(image != (Image *) NULL);
3700   assert(image->signature == MagickCoreSignature);
3701   assert(image->blob != (BlobInfo *) NULL);
3702   assert(image->blob->type != UndefinedStream);
3703   if (length == 0)
3704     return(0);
3705   assert(data != (void *) NULL);
3706   blob_info=image->blob;
3707   count=0;
3708   q=(unsigned char *) data;
3709   switch (blob_info->type)
3710   {
3711     case UndefinedStream:
3712       break;
3713     case StandardStream:
3714     case FileStream:
3715     case PipeStream:
3716     {
3717       switch (length)
3718       {
3719         default:
3720         {
3721           count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3722           break;
3723         }
3724         case 4:
3725         {
3726           c=getc(blob_info->file_info.file);
3727           if (c == EOF)
3728             break;
3729           *q++=(unsigned char) c;
3730           count++;
3731         }
3732         case 3:
3733         {
3734           c=getc(blob_info->file_info.file);
3735           if (c == EOF)
3736             break;
3737           *q++=(unsigned char) c;
3738           count++;
3739         }
3740         case 2:
3741         {
3742           c=getc(blob_info->file_info.file);
3743           if (c == EOF)
3744             break;
3745           *q++=(unsigned char) c;
3746           count++;
3747         }
3748         case 1:
3749         {
3750           c=getc(blob_info->file_info.file);
3751           if (c == EOF)
3752             break;
3753           *q++=(unsigned char) c;
3754           count++;
3755         }
3756         case 0:
3757           break;
3758       }
3759       break;
3760     }
3761     case ZipStream:
3762     {
3763 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3764       switch (length)
3765       {
3766         default:
3767         {
3768           register ssize_t
3769             i;
3770 
3771           for (i=0; i < (ssize_t) length; i+=count)
3772           {
3773             count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3774               (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3775             if (count <= 0)
3776               {
3777                 count=0;
3778                 if (errno != EINTR)
3779                   break;
3780               }
3781           }
3782           count=i;
3783           break;
3784         }
3785         case 4:
3786         {
3787           c=gzgetc(blob_info->file_info.gzfile);
3788           if (c == EOF)
3789             break;
3790           *q++=(unsigned char) c;
3791           count++;
3792         }
3793         case 3:
3794         {
3795           c=gzgetc(blob_info->file_info.gzfile);
3796           if (c == EOF)
3797             break;
3798           *q++=(unsigned char) c;
3799           count++;
3800         }
3801         case 2:
3802         {
3803           c=gzgetc(blob_info->file_info.gzfile);
3804           if (c == EOF)
3805             break;
3806           *q++=(unsigned char) c;
3807           count++;
3808         }
3809         case 1:
3810         {
3811           c=gzgetc(blob_info->file_info.gzfile);
3812           if (c == EOF)
3813             break;
3814           *q++=(unsigned char) c;
3815           count++;
3816         }
3817         case 0:
3818           break;
3819       }
3820 #endif
3821       break;
3822     }
3823     case BZipStream:
3824     {
3825 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3826       register ssize_t
3827         i;
3828 
3829       for (i=0; i < (ssize_t) length; i+=count)
3830       {
3831         count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
3832           (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3833         if (count <= 0)
3834           {
3835             count=0;
3836             if (errno != EINTR)
3837               break;
3838           }
3839       }
3840       count=i;
3841 #endif
3842       break;
3843     }
3844     case FifoStream:
3845       break;
3846     case BlobStream:
3847     {
3848       register const unsigned char
3849         *p;
3850 
3851       if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3852         {
3853           blob_info->eof=MagickTrue;
3854           break;
3855         }
3856       p=blob_info->data+blob_info->offset;
3857       count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3858         blob_info->length-blob_info->offset);
3859       blob_info->offset+=count;
3860       if (count != (ssize_t) length)
3861         blob_info->eof=MagickTrue;
3862       (void) memcpy(q,p,(size_t) count);
3863       break;
3864     }
3865     case CustomStream:
3866     {
3867       if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
3868         count=blob_info->custom_stream->reader(q,length,
3869           blob_info->custom_stream->data);
3870       break;
3871     }
3872   }
3873   return(count);
3874 }
3875 
3876 /*
3877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3878 %                                                                             %
3879 %                                                                             %
3880 %                                                                             %
3881 +  R e a d B l o b B y t e                                                    %
3882 %                                                                             %
3883 %                                                                             %
3884 %                                                                             %
3885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3886 %
3887 %  ReadBlobByte() reads a single byte from the image file and returns it.
3888 %
3889 %  The format of the ReadBlobByte method is:
3890 %
3891 %      int ReadBlobByte(Image *image)
3892 %
3893 %  A description of each parameter follows.
3894 %
3895 %    o image: the image.
3896 %
3897 */
ReadBlobByte(Image * image)3898 MagickExport int ReadBlobByte(Image *image)
3899 {
3900   BlobInfo
3901     *magick_restrict blob_info;
3902 
3903   register const unsigned char
3904     *p;
3905 
3906   unsigned char
3907     buffer[1];
3908 
3909   assert(image != (Image *) NULL);
3910   assert(image->signature == MagickCoreSignature);
3911   assert(image->blob != (BlobInfo *) NULL);
3912   assert(image->blob->type != UndefinedStream);
3913   blob_info=image->blob;
3914   switch (blob_info->type)
3915   {
3916     case StandardStream:
3917     case FileStream:
3918     case PipeStream:
3919     {
3920       int
3921         c;
3922 
3923       p=(const unsigned char *) buffer;
3924       c=getc(blob_info->file_info.file);
3925       if (c == EOF)
3926         return(EOF);
3927       *buffer=(unsigned char) c;
3928       break;
3929     }
3930     default:
3931     {
3932       ssize_t
3933         count;
3934 
3935       p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3936       if (count != 1)
3937         return(EOF);
3938       break;
3939     }
3940   }
3941   return((int) (*p));
3942 }
3943 
3944 /*
3945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3946 %                                                                             %
3947 %                                                                             %
3948 %                                                                             %
3949 +  R e a d B l o b D o u b l e                                                %
3950 %                                                                             %
3951 %                                                                             %
3952 %                                                                             %
3953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3954 %
3955 %  ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3956 %  specified by the endian member of the image structure.
3957 %
3958 %  The format of the ReadBlobDouble method is:
3959 %
3960 %      double ReadBlobDouble(Image *image)
3961 %
3962 %  A description of each parameter follows.
3963 %
3964 %    o image: the image.
3965 %
3966 */
ReadBlobDouble(Image * image)3967 MagickExport double ReadBlobDouble(Image *image)
3968 {
3969   union
3970   {
3971     MagickSizeType
3972       unsigned_value;
3973 
3974     double
3975       double_value;
3976   } quantum;
3977 
3978   quantum.double_value=0.0;
3979   quantum.unsigned_value=ReadBlobLongLong(image);
3980   return(quantum.double_value);
3981 }
3982 
3983 /*
3984 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3985 %                                                                             %
3986 %                                                                             %
3987 %                                                                             %
3988 +  R e a d B l o b F l o a t                                                  %
3989 %                                                                             %
3990 %                                                                             %
3991 %                                                                             %
3992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3993 %
3994 %  ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3995 %  specified by the endian member of the image structure.
3996 %
3997 %  The format of the ReadBlobFloat method is:
3998 %
3999 %      float ReadBlobFloat(Image *image)
4000 %
4001 %  A description of each parameter follows.
4002 %
4003 %    o image: the image.
4004 %
4005 */
ReadBlobFloat(Image * image)4006 MagickExport float ReadBlobFloat(Image *image)
4007 {
4008   union
4009   {
4010     unsigned int
4011       unsigned_value;
4012 
4013     float
4014       float_value;
4015   } quantum;
4016 
4017   quantum.float_value=0.0;
4018   quantum.unsigned_value=ReadBlobLong(image);
4019   return(quantum.float_value);
4020 }
4021 
4022 /*
4023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4024 %                                                                             %
4025 %                                                                             %
4026 %                                                                             %
4027 +  R e a d B l o b L o n g                                                    %
4028 %                                                                             %
4029 %                                                                             %
4030 %                                                                             %
4031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4032 %
4033 %  ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
4034 %  byte-order specified by the endian member of the image structure.
4035 %
4036 %  The format of the ReadBlobLong method is:
4037 %
4038 %      unsigned int ReadBlobLong(Image *image)
4039 %
4040 %  A description of each parameter follows.
4041 %
4042 %    o image: the image.
4043 %
4044 */
ReadBlobLong(Image * image)4045 MagickExport unsigned int ReadBlobLong(Image *image)
4046 {
4047   register const unsigned char
4048     *p;
4049 
4050   ssize_t
4051     count;
4052 
4053   unsigned char
4054     buffer[4];
4055 
4056   unsigned int
4057     value;
4058 
4059   assert(image != (Image *) NULL);
4060   assert(image->signature == MagickCoreSignature);
4061   *buffer='\0';
4062   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4063   if (count != 4)
4064     return(0UL);
4065   if (image->endian == LSBEndian)
4066     {
4067       value=(unsigned int) (*p++);
4068       value|=(unsigned int) (*p++) << 8;
4069       value|=(unsigned int) (*p++) << 16;
4070       value|=(unsigned int) (*p++) << 24;
4071       return(value);
4072     }
4073   value=(unsigned int) (*p++) << 24;
4074   value|=(unsigned int) (*p++) << 16;
4075   value|=(unsigned int) (*p++) << 8;
4076   value|=(unsigned int) (*p++);
4077   return(value);
4078 }
4079 
4080 /*
4081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4082 %                                                                             %
4083 %                                                                             %
4084 %                                                                             %
4085 +  R e a d B l o b L o n g L o n g                                            %
4086 %                                                                             %
4087 %                                                                             %
4088 %                                                                             %
4089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4090 %
4091 %  ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
4092 %  byte-order specified by the endian member of the image structure.
4093 %
4094 %  The format of the ReadBlobLongLong method is:
4095 %
4096 %      MagickSizeType ReadBlobLongLong(Image *image)
4097 %
4098 %  A description of each parameter follows.
4099 %
4100 %    o image: the image.
4101 %
4102 */
ReadBlobLongLong(Image * image)4103 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
4104 {
4105   MagickSizeType
4106     value;
4107 
4108   register const unsigned char
4109     *p;
4110 
4111   ssize_t
4112     count;
4113 
4114   unsigned char
4115     buffer[8];
4116 
4117   assert(image != (Image *) NULL);
4118   assert(image->signature == MagickCoreSignature);
4119   *buffer='\0';
4120   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4121   if (count != 8)
4122     return(MagickULLConstant(0));
4123   if (image->endian == LSBEndian)
4124     {
4125       value=(MagickSizeType) (*p++);
4126       value|=(MagickSizeType) (*p++) << 8;
4127       value|=(MagickSizeType) (*p++) << 16;
4128       value|=(MagickSizeType) (*p++) << 24;
4129       value|=(MagickSizeType) (*p++) << 32;
4130       value|=(MagickSizeType) (*p++) << 40;
4131       value|=(MagickSizeType) (*p++) << 48;
4132       value|=(MagickSizeType) (*p++) << 56;
4133       return(value);
4134     }
4135   value=(MagickSizeType) (*p++) << 56;
4136   value|=(MagickSizeType) (*p++) << 48;
4137   value|=(MagickSizeType) (*p++) << 40;
4138   value|=(MagickSizeType) (*p++) << 32;
4139   value|=(MagickSizeType) (*p++) << 24;
4140   value|=(MagickSizeType) (*p++) << 16;
4141   value|=(MagickSizeType) (*p++) << 8;
4142   value|=(MagickSizeType) (*p++);
4143   return(value);
4144 }
4145 
4146 /*
4147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4148 %                                                                             %
4149 %                                                                             %
4150 %                                                                             %
4151 +  R e a d B l o b S h o r t                                                  %
4152 %                                                                             %
4153 %                                                                             %
4154 %                                                                             %
4155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4156 %
4157 %  ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
4158 %  specified by the endian member of the image structure.
4159 %
4160 %  The format of the ReadBlobShort method is:
4161 %
4162 %      unsigned short ReadBlobShort(Image *image)
4163 %
4164 %  A description of each parameter follows.
4165 %
4166 %    o image: the image.
4167 %
4168 */
ReadBlobShort(Image * image)4169 MagickExport unsigned short ReadBlobShort(Image *image)
4170 {
4171   register const unsigned char
4172     *p;
4173 
4174   register unsigned short
4175     value;
4176 
4177   ssize_t
4178     count;
4179 
4180   unsigned char
4181     buffer[2];
4182 
4183   assert(image != (Image *) NULL);
4184   assert(image->signature == MagickCoreSignature);
4185   *buffer='\0';
4186   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4187   if (count != 2)
4188     return((unsigned short) 0U);
4189   if (image->endian == LSBEndian)
4190     {
4191       value=(unsigned short) (*p++);
4192       value|=(unsigned short) (*p++) << 8;
4193       return(value);
4194     }
4195   value=(unsigned short) ((unsigned short) (*p++) << 8);
4196   value|=(unsigned short) (*p++);
4197   return(value);
4198 }
4199 
4200 /*
4201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4202 %                                                                             %
4203 %                                                                             %
4204 %                                                                             %
4205 +  R e a d B l o b L S B L o n g                                              %
4206 %                                                                             %
4207 %                                                                             %
4208 %                                                                             %
4209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4210 %
4211 %  ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
4212 %  least-significant byte first order.
4213 %
4214 %  The format of the ReadBlobLSBLong method is:
4215 %
4216 %      unsigned int ReadBlobLSBLong(Image *image)
4217 %
4218 %  A description of each parameter follows.
4219 %
4220 %    o image: the image.
4221 %
4222 */
ReadBlobLSBLong(Image * image)4223 MagickExport unsigned int ReadBlobLSBLong(Image *image)
4224 {
4225   register const unsigned char
4226     *p;
4227 
4228   register unsigned int
4229     value;
4230 
4231   ssize_t
4232     count;
4233 
4234   unsigned char
4235     buffer[4];
4236 
4237   assert(image != (Image *) NULL);
4238   assert(image->signature == MagickCoreSignature);
4239   *buffer='\0';
4240   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4241   if (count != 4)
4242     return(0U);
4243   value=(unsigned int) (*p++);
4244   value|=(unsigned int) (*p++) << 8;
4245   value|=(unsigned int) (*p++) << 16;
4246   value|=(unsigned int) (*p++) << 24;
4247   return(value);
4248 }
4249 
4250 /*
4251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4252 %                                                                             %
4253 %                                                                             %
4254 %                                                                             %
4255 +  R e a d B l o b L S B S i g n e d L o n g                                  %
4256 %                                                                             %
4257 %                                                                             %
4258 %                                                                             %
4259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4260 %
4261 %  ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
4262 %  least-significant byte first order.
4263 %
4264 %  The format of the ReadBlobLSBSignedLong method is:
4265 %
4266 %      signed int ReadBlobLSBSignedLong(Image *image)
4267 %
4268 %  A description of each parameter follows.
4269 %
4270 %    o image: the image.
4271 %
4272 */
ReadBlobLSBSignedLong(Image * image)4273 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
4274 {
4275   union
4276   {
4277     unsigned int
4278       unsigned_value;
4279 
4280     signed int
4281       signed_value;
4282   } quantum;
4283 
4284   quantum.unsigned_value=ReadBlobLSBLong(image);
4285   return(quantum.signed_value);
4286 }
4287 
4288 /*
4289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4290 %                                                                             %
4291 %                                                                             %
4292 %                                                                             %
4293 +  R e a d B l o b L S B S h o r t                                            %
4294 %                                                                             %
4295 %                                                                             %
4296 %                                                                             %
4297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4298 %
4299 %  ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4300 %  least-significant byte first order.
4301 %
4302 %  The format of the ReadBlobLSBShort method is:
4303 %
4304 %      unsigned short ReadBlobLSBShort(Image *image)
4305 %
4306 %  A description of each parameter follows.
4307 %
4308 %    o image: the image.
4309 %
4310 */
ReadBlobLSBShort(Image * image)4311 MagickExport unsigned short ReadBlobLSBShort(Image *image)
4312 {
4313   register const unsigned char
4314     *p;
4315 
4316   register unsigned short
4317     value;
4318 
4319   ssize_t
4320     count;
4321 
4322   unsigned char
4323     buffer[2];
4324 
4325   assert(image != (Image *) NULL);
4326   assert(image->signature == MagickCoreSignature);
4327   *buffer='\0';
4328   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4329   if (count != 2)
4330     return((unsigned short) 0U);
4331   value=(unsigned short) (*p++);
4332   value|=(unsigned short) (*p++) << 8;
4333   return(value);
4334 }
4335 
4336 /*
4337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4338 %                                                                             %
4339 %                                                                             %
4340 %                                                                             %
4341 +  R e a d B l o b L S B S i g n e d S h o r t                                %
4342 %                                                                             %
4343 %                                                                             %
4344 %                                                                             %
4345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4346 %
4347 %  ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4348 %  least-significant byte-order.
4349 %
4350 %  The format of the ReadBlobLSBSignedShort method is:
4351 %
4352 %      signed short ReadBlobLSBSignedShort(Image *image)
4353 %
4354 %  A description of each parameter follows.
4355 %
4356 %    o image: the image.
4357 %
4358 */
ReadBlobLSBSignedShort(Image * image)4359 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
4360 {
4361   union
4362   {
4363     unsigned short
4364       unsigned_value;
4365 
4366     signed short
4367       signed_value;
4368   } quantum;
4369 
4370   quantum.unsigned_value=ReadBlobLSBShort(image);
4371   return(quantum.signed_value);
4372 }
4373 
4374 /*
4375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4376 %                                                                             %
4377 %                                                                             %
4378 %                                                                             %
4379 +  R e a d B l o b M S B L o n g                                              %
4380 %                                                                             %
4381 %                                                                             %
4382 %                                                                             %
4383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4384 %
4385 %  ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4386 %  most-significant byte first order.
4387 %
4388 %  The format of the ReadBlobMSBLong method is:
4389 %
4390 %      unsigned int ReadBlobMSBLong(Image *image)
4391 %
4392 %  A description of each parameter follows.
4393 %
4394 %    o image: the image.
4395 %
4396 */
ReadBlobMSBLong(Image * image)4397 MagickExport unsigned int ReadBlobMSBLong(Image *image)
4398 {
4399   register const unsigned char
4400     *p;
4401 
4402   register unsigned int
4403     value;
4404 
4405   ssize_t
4406     count;
4407 
4408   unsigned char
4409     buffer[4];
4410 
4411   assert(image != (Image *) NULL);
4412   assert(image->signature == MagickCoreSignature);
4413   *buffer='\0';
4414   p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4415   if (count != 4)
4416     return(0UL);
4417   value=(unsigned int) (*p++) << 24;
4418   value|=(unsigned int) (*p++) << 16;
4419   value|=(unsigned int) (*p++) << 8;
4420   value|=(unsigned int) (*p++);
4421   return(value);
4422 }
4423 
4424 /*
4425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4426 %                                                                             %
4427 %                                                                             %
4428 %                                                                             %
4429 +  R e a d B l o b M S B L o n g L o n g                                      %
4430 %                                                                             %
4431 %                                                                             %
4432 %                                                                             %
4433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4434 %
4435 %  ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4436 %  in most-significant byte first order.
4437 %
4438 %  The format of the ReadBlobMSBLongLong method is:
4439 %
4440 %      unsigned int ReadBlobMSBLongLong(Image *image)
4441 %
4442 %  A description of each parameter follows.
4443 %
4444 %    o image: the image.
4445 %
4446 */
ReadBlobMSBLongLong(Image * image)4447 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
4448 {
4449   register const unsigned char
4450     *p;
4451 
4452   register MagickSizeType
4453     value;
4454 
4455   ssize_t
4456     count;
4457 
4458   unsigned char
4459     buffer[8];
4460 
4461   assert(image != (Image *) NULL);
4462   assert(image->signature == MagickCoreSignature);
4463   *buffer='\0';
4464   p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4465   if (count != 8)
4466     return(MagickULLConstant(0));
4467   value=(MagickSizeType) (*p++) << 56;
4468   value|=(MagickSizeType) (*p++) << 48;
4469   value|=(MagickSizeType) (*p++) << 40;
4470   value|=(MagickSizeType) (*p++) << 32;
4471   value|=(MagickSizeType) (*p++) << 24;
4472   value|=(MagickSizeType) (*p++) << 16;
4473   value|=(MagickSizeType) (*p++) << 8;
4474   value|=(MagickSizeType) (*p++);
4475   return(value);
4476 }
4477 
4478 /*
4479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4480 %                                                                             %
4481 %                                                                             %
4482 %                                                                             %
4483 +  R e a d B l o b M S B S h o r t                                            %
4484 %                                                                             %
4485 %                                                                             %
4486 %                                                                             %
4487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4488 %
4489 %  ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4490 %  most-significant byte first order.
4491 %
4492 %  The format of the ReadBlobMSBShort method is:
4493 %
4494 %      unsigned short ReadBlobMSBShort(Image *image)
4495 %
4496 %  A description of each parameter follows.
4497 %
4498 %    o image: the image.
4499 %
4500 */
ReadBlobMSBShort(Image * image)4501 MagickExport unsigned short ReadBlobMSBShort(Image *image)
4502 {
4503   register const unsigned char
4504     *p;
4505 
4506   register unsigned short
4507     value;
4508 
4509   ssize_t
4510     count;
4511 
4512   unsigned char
4513     buffer[2];
4514 
4515   assert(image != (Image *) NULL);
4516   assert(image->signature == MagickCoreSignature);
4517   *buffer='\0';
4518   p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4519   if (count != 2)
4520     return((unsigned short) 0U);
4521   value=(unsigned short) ((*p++) << 8);
4522   value|=(unsigned short) (*p++);
4523   return((unsigned short) (value & 0xffff));
4524 }
4525 
4526 /*
4527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4528 %                                                                             %
4529 %                                                                             %
4530 %                                                                             %
4531 +  R e a d B l o b M S B S i g n e d L o n g                                  %
4532 %                                                                             %
4533 %                                                                             %
4534 %                                                                             %
4535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4536 %
4537 %  ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4538 %  most-significant byte-order.
4539 %
4540 %  The format of the ReadBlobMSBSignedLong method is:
4541 %
4542 %      signed int ReadBlobMSBSignedLong(Image *image)
4543 %
4544 %  A description of each parameter follows.
4545 %
4546 %    o image: the image.
4547 %
4548 */
ReadBlobMSBSignedLong(Image * image)4549 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4550 {
4551   union
4552   {
4553     unsigned int
4554       unsigned_value;
4555 
4556     signed int
4557       signed_value;
4558   } quantum;
4559 
4560   quantum.unsigned_value=ReadBlobMSBLong(image);
4561   return(quantum.signed_value);
4562 }
4563 
4564 /*
4565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4566 %                                                                             %
4567 %                                                                             %
4568 %                                                                             %
4569 +  R e a d B l o b M S B S i g n e d S h o r t                                %
4570 %                                                                             %
4571 %                                                                             %
4572 %                                                                             %
4573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4574 %
4575 %  ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4576 %  most-significant byte-order.
4577 %
4578 %  The format of the ReadBlobMSBSignedShort method is:
4579 %
4580 %      signed short ReadBlobMSBSignedShort(Image *image)
4581 %
4582 %  A description of each parameter follows.
4583 %
4584 %    o image: the image.
4585 %
4586 */
ReadBlobMSBSignedShort(Image * image)4587 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4588 {
4589   union
4590   {
4591     unsigned short
4592       unsigned_value;
4593 
4594     signed short
4595       signed_value;
4596   } quantum;
4597 
4598   quantum.unsigned_value=ReadBlobMSBShort(image);
4599   return(quantum.signed_value);
4600 }
4601 
4602 /*
4603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4604 %                                                                             %
4605 %                                                                             %
4606 %                                                                             %
4607 +  R e a d B l o b S i g n e d L o n g                                        %
4608 %                                                                             %
4609 %                                                                             %
4610 %                                                                             %
4611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4612 %
4613 %  ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4614 %  byte-order specified by the endian member of the image structure.
4615 %
4616 %  The format of the ReadBlobSignedLong method is:
4617 %
4618 %      signed int ReadBlobSignedLong(Image *image)
4619 %
4620 %  A description of each parameter follows.
4621 %
4622 %    o image: the image.
4623 %
4624 */
ReadBlobSignedLong(Image * image)4625 MagickExport signed int ReadBlobSignedLong(Image *image)
4626 {
4627   union
4628   {
4629     unsigned int
4630       unsigned_value;
4631 
4632     signed int
4633       signed_value;
4634   } quantum;
4635 
4636   quantum.unsigned_value=ReadBlobLong(image);
4637   return(quantum.signed_value);
4638 }
4639 
4640 /*
4641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4642 %                                                                             %
4643 %                                                                             %
4644 %                                                                             %
4645 +  R e a d B l o b S i g n e d S h o r t                                      %
4646 %                                                                             %
4647 %                                                                             %
4648 %                                                                             %
4649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4650 %
4651 %  ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4652 %  byte-order specified by the endian member of the image structure.
4653 %
4654 %  The format of the ReadBlobSignedShort method is:
4655 %
4656 %      signed short ReadBlobSignedShort(Image *image)
4657 %
4658 %  A description of each parameter follows.
4659 %
4660 %    o image: the image.
4661 %
4662 */
ReadBlobSignedShort(Image * image)4663 MagickExport signed short ReadBlobSignedShort(Image *image)
4664 {
4665   union
4666   {
4667     unsigned short
4668       unsigned_value;
4669 
4670     signed short
4671       signed_value;
4672   } quantum;
4673 
4674   quantum.unsigned_value=ReadBlobShort(image);
4675   return(quantum.signed_value);
4676 }
4677 
4678 /*
4679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4680 %                                                                             %
4681 %                                                                             %
4682 %                                                                             %
4683 +  R e a d B l o b S t r e a m                                                %
4684 %                                                                             %
4685 %                                                                             %
4686 %                                                                             %
4687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4688 %
4689 %  ReadBlobStream() reads data from the blob or image file and returns it.  It
4690 %  returns a pointer to the data buffer you supply or to the image memory
4691 %  buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4692 %  returns a count of zero and has no other results. If length is greater than
4693 %  SSIZE_MAX, the result is unspecified.
4694 %
4695 %  The format of the ReadBlobStream method is:
4696 %
4697 %      const void *ReadBlobStream(Image *image,const size_t length,
4698 %        void *magick_restrict data,ssize_t *count)
4699 %
4700 %  A description of each parameter follows:
4701 %
4702 %    o image: the image.
4703 %
4704 %    o length:  Specifies an integer representing the number of bytes to read
4705 %      from the file.
4706 %
4707 %    o count: returns the number of bytes read.
4708 %
4709 %    o data:  Specifies an area to place the information requested from the
4710 %      file.
4711 %
4712 */
ReadBlobStream(Image * image,const size_t length,void * magick_restrict data,ssize_t * count)4713 MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
4714   const size_t length,void *magick_restrict data,ssize_t *count)
4715 {
4716   BlobInfo
4717     *magick_restrict blob_info;
4718 
4719   assert(image != (Image *) NULL);
4720   assert(image->signature == MagickCoreSignature);
4721   assert(image->blob != (BlobInfo *) NULL);
4722   assert(image->blob->type != UndefinedStream);
4723   assert(count != (ssize_t *) NULL);
4724   blob_info=image->blob;
4725   if (blob_info->type != BlobStream)
4726     {
4727       assert(data != NULL);
4728       *count=ReadBlob(image,length,(unsigned char *) data);
4729       return(data);
4730     }
4731   if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4732     {
4733       *count=0;
4734       blob_info->eof=MagickTrue;
4735       return(data);
4736     }
4737   data=blob_info->data+blob_info->offset;
4738   *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4739     blob_info->length-blob_info->offset);
4740   blob_info->offset+=(*count);
4741   if (*count != (ssize_t) length)
4742     blob_info->eof=MagickTrue;
4743   return(data);
4744 }
4745 
4746 /*
4747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4748 %                                                                             %
4749 %                                                                             %
4750 %                                                                             %
4751 +   R e a d B l o b S t r i n g                                               %
4752 %                                                                             %
4753 %                                                                             %
4754 %                                                                             %
4755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4756 %
4757 %  ReadBlobString() reads characters from a blob or file until a newline
4758 %  character is read or an end-of-file condition is encountered.
4759 %
4760 %  The format of the ReadBlobString method is:
4761 %
4762 %      char *ReadBlobString(Image *image,char *string)
4763 %
4764 %  A description of each parameter follows:
4765 %
4766 %    o image: the image.
4767 %
4768 %    o string: the address of a character buffer.
4769 %
4770 */
ReadBlobString(Image * image,char * string)4771 MagickExport char *ReadBlobString(Image *image,char *string)
4772 {
4773   int
4774     c;
4775 
4776   register ssize_t
4777     i;
4778 
4779   assert(image != (Image *) NULL);
4780   assert(image->signature == MagickCoreSignature);
4781   for (i=0; i < (MagickPathExtent-1L); i++)
4782   {
4783     c=ReadBlobByte(image);
4784     if (c == EOF)
4785       {
4786         if (i == 0)
4787           return((char *) NULL);
4788         break;
4789       }
4790     string[i]=c;
4791     if (c == '\n')
4792       {
4793         if ((i > 0) && (string[i-1] == '\r'))
4794           i--;
4795         break;
4796       }
4797   }
4798   string[i]='\0';
4799   return(string);
4800 }
4801 
4802 /*
4803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4804 %                                                                             %
4805 %                                                                             %
4806 %                                                                             %
4807 +   R e f e r e n c e B l o b                                                 %
4808 %                                                                             %
4809 %                                                                             %
4810 %                                                                             %
4811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4812 %
4813 %  ReferenceBlob() increments the reference count associated with the pixel
4814 %  blob returning a pointer to the blob.
4815 %
4816 %  The format of the ReferenceBlob method is:
4817 %
4818 %      BlobInfo ReferenceBlob(BlobInfo *blob_info)
4819 %
4820 %  A description of each parameter follows:
4821 %
4822 %    o blob_info: the blob_info.
4823 %
4824 */
ReferenceBlob(BlobInfo * blob)4825 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4826 {
4827   assert(blob != (BlobInfo *) NULL);
4828   assert(blob->signature == MagickCoreSignature);
4829   if (blob->debug != MagickFalse)
4830     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4831   LockSemaphoreInfo(blob->semaphore);
4832   blob->reference_count++;
4833   UnlockSemaphoreInfo(blob->semaphore);
4834   return(blob);
4835 }
4836 
4837 /*
4838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4839 %                                                                             %
4840 %                                                                             %
4841 %                                                                             %
4842 +  S e e k B l o b                                                            %
4843 %                                                                             %
4844 %                                                                             %
4845 %                                                                             %
4846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4847 %
4848 %  SeekBlob() sets the offset in bytes from the beginning of a blob or file
4849 %  and returns the resulting offset.
4850 %
4851 %  The format of the SeekBlob method is:
4852 %
4853 %      MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4854 %        const int whence)
4855 %
4856 %  A description of each parameter follows:
4857 %
4858 %    o image: the image.
4859 %
4860 %    o offset:  Specifies an integer representing the offset in bytes.
4861 %
4862 %    o whence:  Specifies an integer representing how the offset is
4863 %      treated relative to the beginning of the blob as follows:
4864 %
4865 %        SEEK_SET  Set position equal to offset bytes.
4866 %        SEEK_CUR  Set position to current location plus offset.
4867 %        SEEK_END  Set position to EOF plus offset.
4868 %
4869 */
SeekBlob(Image * image,const MagickOffsetType offset,const int whence)4870 MagickExport MagickOffsetType SeekBlob(Image *image,
4871   const MagickOffsetType offset,const int whence)
4872 {
4873   BlobInfo
4874     *magick_restrict blob_info;
4875 
4876   assert(image != (Image *) NULL);
4877   assert(image->signature == MagickCoreSignature);
4878   if (image->debug != MagickFalse)
4879     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4880   assert(image->blob != (BlobInfo *) NULL);
4881   assert(image->blob->type != UndefinedStream);
4882   blob_info=image->blob;
4883   switch (blob_info->type)
4884   {
4885     case UndefinedStream:
4886       break;
4887     case StandardStream:
4888     case PipeStream:
4889       return(-1);
4890     case FileStream:
4891     {
4892       if ((offset < 0) && (whence == SEEK_SET))
4893         return(-1);
4894       if (fseek(blob_info->file_info.file,offset,whence) < 0)
4895         return(-1);
4896       blob_info->offset=TellBlob(image);
4897       break;
4898     }
4899     case ZipStream:
4900     {
4901 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4902       if (gzseek(blob_info->file_info.gzfile,offset,whence) < 0)
4903         return(-1);
4904 #endif
4905       blob_info->offset=TellBlob(image);
4906       break;
4907     }
4908     case BZipStream:
4909       return(-1);
4910     case FifoStream:
4911       return(-1);
4912     case BlobStream:
4913     {
4914       switch (whence)
4915       {
4916         case SEEK_SET:
4917         default:
4918         {
4919           if (offset < 0)
4920             return(-1);
4921           blob_info->offset=offset;
4922           break;
4923         }
4924         case SEEK_CUR:
4925         {
4926           if (((offset > 0) && (blob_info->offset > (SSIZE_MAX-offset))) ||
4927               ((offset < 0) && (blob_info->offset < (-SSIZE_MAX-offset))))
4928             {
4929               errno=EOVERFLOW;
4930               return(-1);
4931             }
4932           if ((blob_info->offset+offset) < 0)
4933             return(-1);
4934           blob_info->offset+=offset;
4935           break;
4936         }
4937         case SEEK_END:
4938         {
4939           if (((MagickOffsetType) blob_info->length+offset) < 0)
4940             return(-1);
4941           blob_info->offset=blob_info->length+offset;
4942           break;
4943         }
4944       }
4945       if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
4946         {
4947           blob_info->eof=MagickFalse;
4948           break;
4949         }
4950       if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
4951         return(-1);
4952       break;
4953     }
4954     case CustomStream:
4955     {
4956       if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
4957         return(-1);
4958       blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
4959         blob_info->custom_stream->data);
4960       break;
4961     }
4962   }
4963   return(blob_info->offset);
4964 }
4965 
4966 /*
4967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4968 %                                                                             %
4969 %                                                                             %
4970 %                                                                             %
4971 +   S e t B l o b E x e m p t                                                 %
4972 %                                                                             %
4973 %                                                                             %
4974 %                                                                             %
4975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4976 %
4977 %  SetBlobExempt() sets the blob exempt status.
4978 %
4979 %  The format of the SetBlobExempt method is:
4980 %
4981 %      MagickBooleanType SetBlobExempt(const Image *image,
4982 %        const MagickBooleanType exempt)
4983 %
4984 %  A description of each parameter follows:
4985 %
4986 %    o image: the image.
4987 %
4988 %    o exempt: Set to true if this blob is exempt from being closed.
4989 %
4990 */
SetBlobExempt(Image * image,const MagickBooleanType exempt)4991 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4992 {
4993   assert(image != (const Image *) NULL);
4994   assert(image->signature == MagickCoreSignature);
4995   if (image->debug != MagickFalse)
4996     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4997   image->blob->exempt=exempt;
4998 }
4999 
5000 /*
5001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5002 %                                                                             %
5003 %                                                                             %
5004 %                                                                             %
5005 +  S e t B l o b E x t e n t                                                  %
5006 %                                                                             %
5007 %                                                                             %
5008 %                                                                             %
5009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5010 %
5011 %  SetBlobExtent() ensures enough space is allocated for the blob.  If the
5012 %  method is successful, subsequent writes to bytes in the specified range are
5013 %  guaranteed not to fail.
5014 %
5015 %  The format of the SetBlobExtent method is:
5016 %
5017 %      MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
5018 %
5019 %  A description of each parameter follows:
5020 %
5021 %    o image: the image.
5022 %
5023 %    o extent:  the blob maximum extent.
5024 %
5025 */
SetBlobExtent(Image * image,const MagickSizeType extent)5026 MagickExport MagickBooleanType SetBlobExtent(Image *image,
5027   const MagickSizeType extent)
5028 {
5029   BlobInfo
5030     *magick_restrict blob_info;
5031 
5032   assert(image != (Image *) NULL);
5033   assert(image->signature == MagickCoreSignature);
5034   if (image->debug != MagickFalse)
5035     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5036   assert(image->blob != (BlobInfo *) NULL);
5037   assert(image->blob->type != UndefinedStream);
5038   blob_info=image->blob;
5039   switch (blob_info->type)
5040   {
5041     case UndefinedStream:
5042       break;
5043     case StandardStream:
5044       return(MagickFalse);
5045     case FileStream:
5046     {
5047       MagickOffsetType
5048         offset;
5049 
5050       ssize_t
5051         count;
5052 
5053       if (extent != (MagickSizeType) ((off_t) extent))
5054         return(MagickFalse);
5055       offset=SeekBlob(image,0,SEEK_END);
5056       if (offset < 0)
5057         return(MagickFalse);
5058       if ((MagickSizeType) offset >= extent)
5059         break;
5060       offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5061       if (offset < 0)
5062         break;
5063       count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5064         blob_info->file_info.file);
5065 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5066       if (blob_info->synchronize != MagickFalse)
5067         {
5068           int
5069             file;
5070 
5071           file=fileno(blob_info->file_info.file);
5072           if ((file == -1) || (offset < 0))
5073             return(MagickFalse);
5074           (void) posix_fallocate(file,offset,extent-offset);
5075         }
5076 #endif
5077       offset=SeekBlob(image,offset,SEEK_SET);
5078       if (count != 1)
5079         return(MagickFalse);
5080       break;
5081     }
5082     case PipeStream:
5083     case ZipStream:
5084       return(MagickFalse);
5085     case BZipStream:
5086       return(MagickFalse);
5087     case FifoStream:
5088       return(MagickFalse);
5089     case BlobStream:
5090     {
5091       if (extent != (MagickSizeType) ((size_t) extent))
5092         return(MagickFalse);
5093       if (blob_info->mapped != MagickFalse)
5094         {
5095           MagickOffsetType
5096             offset;
5097 
5098           ssize_t
5099             count;
5100 
5101           (void) UnmapBlob(blob_info->data,blob_info->length);
5102           RelinquishMagickResource(MapResource,blob_info->length);
5103           if (extent != (MagickSizeType) ((off_t) extent))
5104             return(MagickFalse);
5105           offset=SeekBlob(image,0,SEEK_END);
5106           if (offset < 0)
5107             return(MagickFalse);
5108           if ((MagickSizeType) offset >= extent)
5109             break;
5110           offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
5111           count=(ssize_t) fwrite((const unsigned char *) "",1,1,
5112             blob_info->file_info.file);
5113 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
5114           if (blob_info->synchronize != MagickFalse)
5115             {
5116               int
5117                 file;
5118 
5119               file=fileno(blob_info->file_info.file);
5120               if ((file == -1) || (offset < 0))
5121                 return(MagickFalse);
5122               (void) posix_fallocate(file,offset,extent-offset);
5123             }
5124 #endif
5125           offset=SeekBlob(image,offset,SEEK_SET);
5126           if (count != 1)
5127             return(MagickFalse);
5128           (void) AcquireMagickResource(MapResource,extent);
5129           blob_info->data=(unsigned char*) MapBlob(fileno(
5130             blob_info->file_info.file),WriteMode,0,(size_t) extent);
5131           blob_info->extent=(size_t) extent;
5132           blob_info->length=(size_t) extent;
5133           (void) SyncBlob(image);
5134           break;
5135         }
5136       blob_info->extent=(size_t) extent;
5137       blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
5138         blob_info->extent+1,sizeof(*blob_info->data));
5139       (void) SyncBlob(image);
5140       if (blob_info->data == (unsigned char *) NULL)
5141         {
5142           (void) DetachBlob(blob_info);
5143           return(MagickFalse);
5144         }
5145       break;
5146     }
5147     case CustomStream:
5148       break;
5149   }
5150   return(MagickTrue);
5151 }
5152 
5153 /*
5154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5155 %                                                                             %
5156 %                                                                             %
5157 %                                                                             %
5158 +  S e t C u s t o m S t r e a m D a t a                                      %
5159 %                                                                             %
5160 %                                                                             %
5161 %                                                                             %
5162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5163 %
5164 %  SetCustomStreamData() sets the stream info data member.
5165 %
5166 %  The format of the SetCustomStreamData method is:
5167 %
5168 %      void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
5169 %
5170 %  A description of each parameter follows:
5171 %
5172 %    o custom_stream: the custom stream info.
5173 %
5174 %    o data: an object containing information about the custom stream.
5175 %
5176 */
SetCustomStreamData(CustomStreamInfo * custom_stream,void * data)5177 MagickExport void SetCustomStreamData(CustomStreamInfo *custom_stream,
5178   void *data)
5179 {
5180   assert(custom_stream != (CustomStreamInfo *) NULL);
5181   assert(custom_stream->signature == MagickCoreSignature);
5182   custom_stream->data=data;
5183 }
5184 
5185 /*
5186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5187 %                                                                             %
5188 %                                                                             %
5189 %                                                                             %
5190 +  S e t C u s t o m S t r e a m R e a d e r                                  %
5191 %                                                                             %
5192 %                                                                             %
5193 %                                                                             %
5194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5195 %
5196 %  SetCustomStreamReader() sets the stream info reader member.
5197 %
5198 %  The format of the SetCustomStreamReader method is:
5199 %
5200 %      void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5201 %        CustomStreamHandler reader)
5202 %
5203 %  A description of each parameter follows:
5204 %
5205 %    o custom_stream: the custom stream info.
5206 %
5207 %    o reader: a function to read from the stream.
5208 %
5209 */
SetCustomStreamReader(CustomStreamInfo * custom_stream,CustomStreamHandler reader)5210 MagickExport void SetCustomStreamReader(CustomStreamInfo *custom_stream,
5211   CustomStreamHandler reader)
5212 {
5213   assert(custom_stream != (CustomStreamInfo *) NULL);
5214   assert(custom_stream->signature == MagickCoreSignature);
5215   custom_stream->reader=reader;
5216 }
5217 
5218 /*
5219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5220 %                                                                             %
5221 %                                                                             %
5222 %                                                                             %
5223 +  S e t C u s t o m S t r e a m S e e k e r                                  %
5224 %                                                                             %
5225 %                                                                             %
5226 %                                                                             %
5227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5228 %
5229 %  SetCustomStreamSeeker() sets the stream info seeker member.
5230 %
5231 %  The format of the SetCustomStreamReader method is:
5232 %
5233 %      void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5234 %        CustomStreamSeeker seeker)
5235 %
5236 %  A description of each parameter follows:
5237 %
5238 %    o custom_stream: the custom stream info.
5239 %
5240 %    o seeker: a function to seek in the custom stream.
5241 %
5242 */
SetCustomStreamSeeker(CustomStreamInfo * custom_stream,CustomStreamSeeker seeker)5243 MagickExport void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
5244   CustomStreamSeeker seeker)
5245 {
5246   assert(custom_stream != (CustomStreamInfo *) NULL);
5247   assert(custom_stream->signature == MagickCoreSignature);
5248   custom_stream->seeker=seeker;
5249 }
5250 
5251 /*
5252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5253 %                                                                             %
5254 %                                                                             %
5255 %                                                                             %
5256 +  S e t C u s t o m S t r e a m T e l l e r                                  %
5257 %                                                                             %
5258 %                                                                             %
5259 %                                                                             %
5260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5261 %
5262 %  SetCustomStreamTeller() sets the stream info teller member.
5263 %
5264 %  The format of the SetCustomStreamTeller method is:
5265 %
5266 %      void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5267 %        CustomStreamTeller *teller)
5268 %
5269 %  A description of each parameter follows:
5270 %
5271 %    o custom_stream: the custom stream info.
5272 %
5273 %    o teller: a function to set the position in the stream.
5274 %
5275 */
SetCustomStreamTeller(CustomStreamInfo * custom_stream,CustomStreamTeller teller)5276 MagickExport void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
5277   CustomStreamTeller teller)
5278 {
5279   assert(custom_stream != (CustomStreamInfo *) NULL);
5280   assert(custom_stream->signature == MagickCoreSignature);
5281   custom_stream->teller=teller;
5282 }
5283 
5284 /*
5285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5286 %                                                                             %
5287 %                                                                             %
5288 %                                                                             %
5289 +  S e t C u s t o m S t r e a m W r i t e r                                  %
5290 %                                                                             %
5291 %                                                                             %
5292 %                                                                             %
5293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5294 %
5295 %  SetCustomStreamWriter() sets the stream info writer member.
5296 %
5297 %  The format of the SetCustomStreamWriter method is:
5298 %
5299 %      void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5300 %        CustomStreamHandler *writer)
5301 %
5302 %  A description of each parameter follows:
5303 %
5304 %    o custom_stream: the custom stream info.
5305 %
5306 %    o writer: a function to write to the custom stream.
5307 %
5308 */
SetCustomStreamWriter(CustomStreamInfo * custom_stream,CustomStreamHandler writer)5309 MagickExport void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5310   CustomStreamHandler writer)
5311 {
5312   assert(custom_stream != (CustomStreamInfo *) NULL);
5313   assert(custom_stream->signature == MagickCoreSignature);
5314   custom_stream->writer=writer;
5315 }
5316 
5317 /*
5318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5319 %                                                                             %
5320 %                                                                             %
5321 %                                                                             %
5322 +  S y n c B l o b                                                            %
5323 %                                                                             %
5324 %                                                                             %
5325 %                                                                             %
5326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5327 %
5328 %  SyncBlob() flushes the datastream if it is a file or synchronizes the data
5329 %  attributes if it is an blob.
5330 %
5331 %  The format of the SyncBlob method is:
5332 %
5333 %      int SyncBlob(Image *image)
5334 %
5335 %  A description of each parameter follows:
5336 %
5337 %    o image: the image.
5338 %
5339 */
SyncBlob(Image * image)5340 static int SyncBlob(Image *image)
5341 {
5342   BlobInfo
5343     *magick_restrict blob_info;
5344 
5345   int
5346     status;
5347 
5348   assert(image != (Image *) NULL);
5349   assert(image->signature == MagickCoreSignature);
5350   if (image->debug != MagickFalse)
5351     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5352   assert(image->blob != (BlobInfo *) NULL);
5353   assert(image->blob->type != UndefinedStream);
5354   blob_info=image->blob;
5355   status=0;
5356   switch (blob_info->type)
5357   {
5358     case UndefinedStream:
5359     case StandardStream:
5360       break;
5361     case FileStream:
5362     case PipeStream:
5363     {
5364       status=fflush(blob_info->file_info.file);
5365       break;
5366     }
5367     case ZipStream:
5368     {
5369 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5370       status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5371 #endif
5372       break;
5373     }
5374     case BZipStream:
5375     {
5376 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5377       status=BZ2_bzflush(blob_info->file_info.bzfile);
5378 #endif
5379       break;
5380     }
5381     case FifoStream:
5382       break;
5383     case BlobStream:
5384       break;
5385     case CustomStream:
5386       break;
5387   }
5388   return(status);
5389 }
5390 
5391 /*
5392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5393 %                                                                             %
5394 %                                                                             %
5395 %                                                                             %
5396 +  T e l l B l o b                                                            %
5397 %                                                                             %
5398 %                                                                             %
5399 %                                                                             %
5400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5401 %
5402 %  TellBlob() obtains the current value of the blob or file position.
5403 %
5404 %  The format of the TellBlob method is:
5405 %
5406 %      MagickOffsetType TellBlob(const Image *image)
5407 %
5408 %  A description of each parameter follows:
5409 %
5410 %    o image: the image.
5411 %
5412 */
TellBlob(const Image * image)5413 MagickExport MagickOffsetType TellBlob(const Image *image)
5414 {
5415   BlobInfo
5416     *magick_restrict blob_info;
5417 
5418   MagickOffsetType
5419     offset;
5420 
5421   assert(image != (Image *) NULL);
5422   assert(image->signature == MagickCoreSignature);
5423   if (image->debug != MagickFalse)
5424     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5425   assert(image->blob != (BlobInfo *) NULL);
5426   assert(image->blob->type != UndefinedStream);
5427   blob_info=image->blob;
5428   offset=(-1);
5429   switch (blob_info->type)
5430   {
5431     case UndefinedStream:
5432     case StandardStream:
5433       break;
5434     case FileStream:
5435     {
5436       offset=ftell(blob_info->file_info.file);
5437       break;
5438     }
5439     case PipeStream:
5440       break;
5441     case ZipStream:
5442     {
5443 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5444       offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5445 #endif
5446       break;
5447     }
5448     case BZipStream:
5449       break;
5450     case FifoStream:
5451       break;
5452     case BlobStream:
5453     {
5454       offset=blob_info->offset;
5455       break;
5456     }
5457     case CustomStream:
5458     {
5459       if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5460         offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5461       break;
5462     }
5463   }
5464   return(offset);
5465 }
5466 
5467 /*
5468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5469 %                                                                             %
5470 %                                                                             %
5471 %                                                                             %
5472 +  U n m a p B l o b                                                          %
5473 %                                                                             %
5474 %                                                                             %
5475 %                                                                             %
5476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5477 %
5478 %  UnmapBlob() deallocates the binary large object previously allocated with
5479 %  the MapBlob method.
5480 %
5481 %  The format of the UnmapBlob method is:
5482 %
5483 %       MagickBooleanType UnmapBlob(void *map,const size_t length)
5484 %
5485 %  A description of each parameter follows:
5486 %
5487 %    o map: the address  of the binary large object.
5488 %
5489 %    o length: the length of the binary large object.
5490 %
5491 */
UnmapBlob(void * map,const size_t length)5492 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5493 {
5494 #if defined(MAGICKCORE_HAVE_MMAP)
5495   int
5496     status;
5497 
5498   status=munmap(map,length);
5499   return(status == -1 ? MagickFalse : MagickTrue);
5500 #else
5501   (void) map;
5502   (void) length;
5503   return(MagickFalse);
5504 #endif
5505 }
5506 
5507 /*
5508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5509 %                                                                             %
5510 %                                                                             %
5511 %                                                                             %
5512 +  W r i t e B l o b                                                          %
5513 %                                                                             %
5514 %                                                                             %
5515 %                                                                             %
5516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5517 %
5518 %  WriteBlob() writes data to a blob or image file.  It returns the number of
5519 %  bytes written.
5520 %
5521 %  The format of the WriteBlob method is:
5522 %
5523 %      ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5524 %
5525 %  A description of each parameter follows:
5526 %
5527 %    o image: the image.
5528 %
5529 %    o length:  Specifies an integer representing the number of bytes to
5530 %      write to the file.
5531 %
5532 %    o data:  The address of the data to write to the blob or file.
5533 %
5534 */
WriteBlob(Image * image,const size_t length,const void * data)5535 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5536   const void *data)
5537 {
5538   BlobInfo
5539     *magick_restrict blob_info;
5540 
5541   int
5542     c;
5543 
5544   register const unsigned char
5545     *p;
5546 
5547   register unsigned char
5548     *q;
5549 
5550   ssize_t
5551     count;
5552 
5553   assert(image != (Image *) NULL);
5554   assert(image->signature == MagickCoreSignature);
5555   assert(image->blob != (BlobInfo *) NULL);
5556   assert(image->blob->type != UndefinedStream);
5557   if (length == 0)
5558     return(0);
5559   assert(data != (const void *) NULL);
5560   blob_info=image->blob;
5561   count=0;
5562   p=(const unsigned char *) data;
5563   q=(unsigned char *) data;
5564   switch (blob_info->type)
5565   {
5566     case UndefinedStream:
5567       break;
5568     case StandardStream:
5569     case FileStream:
5570     case PipeStream:
5571     {
5572       switch (length)
5573       {
5574         default:
5575         {
5576           count=(ssize_t) fwrite((const char *) data,1,length,
5577             blob_info->file_info.file);
5578           break;
5579         }
5580         case 4:
5581         {
5582           c=putc((int) *p++,blob_info->file_info.file);
5583           if (c == EOF)
5584             break;
5585           count++;
5586         }
5587         case 3:
5588         {
5589           c=putc((int) *p++,blob_info->file_info.file);
5590           if (c == EOF)
5591             break;
5592           count++;
5593         }
5594         case 2:
5595         {
5596           c=putc((int) *p++,blob_info->file_info.file);
5597           if (c == EOF)
5598             break;
5599           count++;
5600         }
5601         case 1:
5602         {
5603           c=putc((int) *p++,blob_info->file_info.file);
5604           if (c == EOF)
5605             break;
5606           count++;
5607         }
5608         case 0:
5609           break;
5610       }
5611       break;
5612     }
5613     case ZipStream:
5614     {
5615 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5616       switch (length)
5617       {
5618         default:
5619         {
5620           register ssize_t
5621             i;
5622 
5623           for (i=0; i < (ssize_t) length; i+=count)
5624           {
5625             count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
5626               (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
5627             if (count <= 0)
5628               {
5629                 count=0;
5630                 if (errno != EINTR)
5631                   break;
5632               }
5633           }
5634           count=i;
5635           break;
5636         }
5637         case 4:
5638         {
5639           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5640           if (c == EOF)
5641             break;
5642           count++;
5643         }
5644         case 3:
5645         {
5646           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5647           if (c == EOF)
5648             break;
5649           count++;
5650         }
5651         case 2:
5652         {
5653           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5654           if (c == EOF)
5655             break;
5656           count++;
5657         }
5658         case 1:
5659         {
5660           c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5661           if (c == EOF)
5662             break;
5663           count++;
5664         }
5665         case 0:
5666           break;
5667       }
5668 #endif
5669       break;
5670     }
5671     case BZipStream:
5672     {
5673 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5674       register ssize_t
5675         i;
5676 
5677       for (i=0; i < (ssize_t) length; i+=count)
5678       {
5679         count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5680           (int) MagickMin(length-i,MagickMaxBufferExtent));
5681         if (count <= 0)
5682           {
5683             count=0;
5684             if (errno != EINTR)
5685               break;
5686           }
5687       }
5688       count=i;
5689 #endif
5690       break;
5691     }
5692     case FifoStream:
5693     {
5694       count=(ssize_t) blob_info->stream(image,data,length);
5695       break;
5696     }
5697     case BlobStream:
5698     {
5699       if ((blob_info->offset+(MagickOffsetType) length) >=
5700           (MagickOffsetType) blob_info->extent)
5701         {
5702           if (blob_info->mapped != MagickFalse)
5703             return(0);
5704           blob_info->extent+=length+blob_info->quantum;
5705           blob_info->quantum<<=1;
5706           blob_info->data=(unsigned char *) ResizeQuantumMemory(
5707             blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5708           (void) SyncBlob(image);
5709           if (blob_info->data == (unsigned char *) NULL)
5710             {
5711               (void) DetachBlob(blob_info);
5712               return(0);
5713             }
5714         }
5715       q=blob_info->data+blob_info->offset;
5716       (void) memcpy(q,p,length);
5717       blob_info->offset+=length;
5718       if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5719         blob_info->length=(size_t) blob_info->offset;
5720       count=(ssize_t) length;
5721       break;
5722     }
5723     case CustomStream:
5724     {
5725       if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
5726         count=blob_info->custom_stream->writer((unsigned char *) data,
5727           length,blob_info->custom_stream->data);
5728       break;
5729     }
5730   }
5731   return(count);
5732 }
5733 
5734 /*
5735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5736 %                                                                             %
5737 %                                                                             %
5738 %                                                                             %
5739 +  W r i t e B l o b B y t e                                                  %
5740 %                                                                             %
5741 %                                                                             %
5742 %                                                                             %
5743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5744 %
5745 %  WriteBlobByte() write an integer to a blob.  It returns the number of bytes
5746 %  written (either 0 or 1);
5747 %
5748 %  The format of the WriteBlobByte method is:
5749 %
5750 %      ssize_t WriteBlobByte(Image *image,const unsigned char value)
5751 %
5752 %  A description of each parameter follows.
5753 %
5754 %    o image: the image.
5755 %
5756 %    o value: Specifies the value to write.
5757 %
5758 */
WriteBlobByte(Image * image,const unsigned char value)5759 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5760 {
5761   BlobInfo
5762     *magick_restrict blob_info;
5763 
5764   ssize_t
5765     count;
5766 
5767   assert(image != (Image *) NULL);
5768   assert(image->signature == MagickCoreSignature);
5769   assert(image->blob != (BlobInfo *) NULL);
5770   assert(image->blob->type != UndefinedStream);
5771   blob_info=image->blob;
5772   count=0;
5773   switch (blob_info->type)
5774   {
5775     case StandardStream:
5776     case FileStream:
5777     case PipeStream:
5778     {
5779       int
5780         c;
5781 
5782       c=putc((int) value,blob_info->file_info.file);
5783       if (c == EOF)
5784         break;
5785       count++;
5786       break;
5787     }
5788     default:
5789     {
5790       count=WriteBlobStream(image,1,&value);
5791       break;
5792     }
5793   }
5794   return(count);
5795 }
5796 
5797 /*
5798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5799 %                                                                             %
5800 %                                                                             %
5801 %                                                                             %
5802 +  W r i t e B l o b F l o a t                                                %
5803 %                                                                             %
5804 %                                                                             %
5805 %                                                                             %
5806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5807 %
5808 %  WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5809 %  specified by the endian member of the image structure.
5810 %
5811 %  The format of the WriteBlobFloat method is:
5812 %
5813 %      ssize_t WriteBlobFloat(Image *image,const float value)
5814 %
5815 %  A description of each parameter follows.
5816 %
5817 %    o image: the image.
5818 %
5819 %    o value: Specifies the value to write.
5820 %
5821 */
WriteBlobFloat(Image * image,const float value)5822 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5823 {
5824   union
5825   {
5826     unsigned int
5827       unsigned_value;
5828 
5829     float
5830       float_value;
5831   } quantum;
5832 
5833   quantum.unsigned_value=0U;
5834   quantum.float_value=value;
5835   return(WriteBlobLong(image,quantum.unsigned_value));
5836 }
5837 
5838 /*
5839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5840 %                                                                             %
5841 %                                                                             %
5842 %                                                                             %
5843 +  W r i t e B l o b L o n g                                                  %
5844 %                                                                             %
5845 %                                                                             %
5846 %                                                                             %
5847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5848 %
5849 %  WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5850 %  byte-order specified by the endian member of the image structure.
5851 %
5852 %  The format of the WriteBlobLong method is:
5853 %
5854 %      ssize_t WriteBlobLong(Image *image,const unsigned int value)
5855 %
5856 %  A description of each parameter follows.
5857 %
5858 %    o image: the image.
5859 %
5860 %    o value: Specifies the value to write.
5861 %
5862 */
WriteBlobLong(Image * image,const unsigned int value)5863 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5864 {
5865   unsigned char
5866     buffer[4];
5867 
5868   assert(image != (Image *) NULL);
5869   assert(image->signature == MagickCoreSignature);
5870   if (image->endian == LSBEndian)
5871     {
5872       buffer[0]=(unsigned char) value;
5873       buffer[1]=(unsigned char) (value >> 8);
5874       buffer[2]=(unsigned char) (value >> 16);
5875       buffer[3]=(unsigned char) (value >> 24);
5876       return(WriteBlobStream(image,4,buffer));
5877     }
5878   buffer[0]=(unsigned char) (value >> 24);
5879   buffer[1]=(unsigned char) (value >> 16);
5880   buffer[2]=(unsigned char) (value >> 8);
5881   buffer[3]=(unsigned char) value;
5882   return(WriteBlobStream(image,4,buffer));
5883 }
5884 
5885 /*
5886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5887 %                                                                             %
5888 %                                                                             %
5889 %                                                                             %
5890 +  W r i t e B l o b L o n g L o n g                                          %
5891 %                                                                             %
5892 %                                                                             %
5893 %                                                                             %
5894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5895 %
5896 %  WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
5897 %  byte-order specified by the endian member of the image structure.
5898 %
5899 %  The format of the WriteBlobLongLong method is:
5900 %
5901 %      ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5902 %
5903 %  A description of each parameter follows.
5904 %
5905 %    o value:  Specifies the value to write.
5906 %
5907 %    o image: the image.
5908 %
5909 */
WriteBlobLongLong(Image * image,const MagickSizeType value)5910 MagickExport ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5911 {
5912   unsigned char
5913     buffer[8];
5914 
5915   assert(image != (Image *) NULL);
5916   assert(image->signature == MagickCoreSignature);
5917   if (image->endian == LSBEndian)
5918     {
5919       buffer[0]=(unsigned char) value;
5920       buffer[1]=(unsigned char) (value >> 8);
5921       buffer[2]=(unsigned char) (value >> 16);
5922       buffer[3]=(unsigned char) (value >> 24);
5923       buffer[4]=(unsigned char) (value >> 32);
5924       buffer[5]=(unsigned char) (value >> 40);
5925       buffer[6]=(unsigned char) (value >> 48);
5926       buffer[7]=(unsigned char) (value >> 56);
5927       return(WriteBlobStream(image,8,buffer));
5928     }
5929   buffer[0]=(unsigned char) (value >> 56);
5930   buffer[1]=(unsigned char) (value >> 48);
5931   buffer[2]=(unsigned char) (value >> 40);
5932   buffer[3]=(unsigned char) (value >> 32);
5933   buffer[4]=(unsigned char) (value >> 24);
5934   buffer[5]=(unsigned char) (value >> 16);
5935   buffer[6]=(unsigned char) (value >> 8);
5936   buffer[7]=(unsigned char) value;
5937   return(WriteBlobStream(image,8,buffer));
5938 }
5939 
5940 /*
5941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5942 %                                                                             %
5943 %                                                                             %
5944 %                                                                             %
5945 +   W r i t e B l o b S h o r t                                               %
5946 %                                                                             %
5947 %                                                                             %
5948 %                                                                             %
5949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5950 %
5951 %  WriteBlobShort() writes a short value as a 16-bit quantity in the
5952 %  byte-order specified by the endian member of the image structure.
5953 %
5954 %  The format of the WriteBlobShort method is:
5955 %
5956 %      ssize_t WriteBlobShort(Image *image,const unsigned short value)
5957 %
5958 %  A description of each parameter follows.
5959 %
5960 %    o image: the image.
5961 %
5962 %    o value:  Specifies the value to write.
5963 %
5964 */
WriteBlobShort(Image * image,const unsigned short value)5965 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5966 {
5967   unsigned char
5968     buffer[2];
5969 
5970   assert(image != (Image *) NULL);
5971   assert(image->signature == MagickCoreSignature);
5972   if (image->endian == LSBEndian)
5973     {
5974       buffer[0]=(unsigned char) value;
5975       buffer[1]=(unsigned char) (value >> 8);
5976       return(WriteBlobStream(image,2,buffer));
5977     }
5978   buffer[0]=(unsigned char) (value >> 8);
5979   buffer[1]=(unsigned char) value;
5980   return(WriteBlobStream(image,2,buffer));
5981 }
5982 
5983 /*
5984 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5985 %                                                                             %
5986 %                                                                             %
5987 %                                                                             %
5988 +  W r i t e B l o b S i g n e d L o n g                                      %
5989 %                                                                             %
5990 %                                                                             %
5991 %                                                                             %
5992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5993 %
5994 %  WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
5995 %  byte-order specified by the endian member of the image structure.
5996 %
5997 %  The format of the WriteBlobSignedLong method is:
5998 %
5999 %      ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6000 %
6001 %  A description of each parameter follows.
6002 %
6003 %    o image: the image.
6004 %
6005 %    o value: Specifies the value to write.
6006 %
6007 */
WriteBlobSignedLong(Image * image,const signed int value)6008 MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
6009 {
6010   union
6011   {
6012     unsigned int
6013       unsigned_value;
6014 
6015     signed int
6016       signed_value;
6017   } quantum;
6018 
6019   unsigned char
6020     buffer[4];
6021 
6022   assert(image != (Image *) NULL);
6023   assert(image->signature == MagickCoreSignature);
6024   quantum.signed_value=value;
6025   if (image->endian == LSBEndian)
6026     {
6027       buffer[0]=(unsigned char) quantum.unsigned_value;
6028       buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6029       buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6030       buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6031       return(WriteBlobStream(image,4,buffer));
6032     }
6033   buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
6034   buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
6035   buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
6036   buffer[3]=(unsigned char) quantum.unsigned_value;
6037   return(WriteBlobStream(image,4,buffer));
6038 }
6039 
6040 /*
6041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6042 %                                                                             %
6043 %                                                                             %
6044 %                                                                             %
6045 +  W r i t e B l o b L S B L o n g                                            %
6046 %                                                                             %
6047 %                                                                             %
6048 %                                                                             %
6049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6050 %
6051 %  WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
6052 %  least-significant byte first order.
6053 %
6054 %  The format of the WriteBlobLSBLong method is:
6055 %
6056 %      ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6057 %
6058 %  A description of each parameter follows.
6059 %
6060 %    o image: the image.
6061 %
6062 %    o value: Specifies the value to write.
6063 %
6064 */
WriteBlobLSBLong(Image * image,const unsigned int value)6065 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
6066 {
6067   unsigned char
6068     buffer[4];
6069 
6070   assert(image != (Image *) NULL);
6071   assert(image->signature == MagickCoreSignature);
6072   buffer[0]=(unsigned char) value;
6073   buffer[1]=(unsigned char) (value >> 8);
6074   buffer[2]=(unsigned char) (value >> 16);
6075   buffer[3]=(unsigned char) (value >> 24);
6076   return(WriteBlobStream(image,4,buffer));
6077 }
6078 
6079 /*
6080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6081 %                                                                             %
6082 %                                                                             %
6083 %                                                                             %
6084 +   W r i t e B l o b L S B S h o r t                                         %
6085 %                                                                             %
6086 %                                                                             %
6087 %                                                                             %
6088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6089 %
6090 %  WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
6091 %  least-significant byte first order.
6092 %
6093 %  The format of the WriteBlobLSBShort method is:
6094 %
6095 %      ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6096 %
6097 %  A description of each parameter follows.
6098 %
6099 %    o image: the image.
6100 %
6101 %    o value:  Specifies the value to write.
6102 %
6103 */
WriteBlobLSBShort(Image * image,const unsigned short value)6104 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
6105 {
6106   unsigned char
6107     buffer[2];
6108 
6109   assert(image != (Image *) NULL);
6110   assert(image->signature == MagickCoreSignature);
6111   buffer[0]=(unsigned char) value;
6112   buffer[1]=(unsigned char) (value >> 8);
6113   return(WriteBlobStream(image,2,buffer));
6114 }
6115 
6116 /*
6117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6118 %                                                                             %
6119 %                                                                             %
6120 %                                                                             %
6121 +  W r i t e B l o b L S B S i g n e d L o n g                                %
6122 %                                                                             %
6123 %                                                                             %
6124 %                                                                             %
6125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6126 %
6127 %  WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
6128 %  least-significant byte first order.
6129 %
6130 %  The format of the WriteBlobLSBSignedLong method is:
6131 %
6132 %      ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6133 %
6134 %  A description of each parameter follows.
6135 %
6136 %    o image: the image.
6137 %
6138 %    o value: Specifies the value to write.
6139 %
6140 */
WriteBlobLSBSignedLong(Image * image,const signed int value)6141 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
6142 {
6143   union
6144   {
6145     unsigned int
6146       unsigned_value;
6147 
6148     signed int
6149       signed_value;
6150   } quantum;
6151 
6152   unsigned char
6153     buffer[4];
6154 
6155   assert(image != (Image *) NULL);
6156   assert(image->signature == MagickCoreSignature);
6157   quantum.signed_value=value;
6158   buffer[0]=(unsigned char) quantum.unsigned_value;
6159   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6160   buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
6161   buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
6162   return(WriteBlobStream(image,4,buffer));
6163 }
6164 
6165 /*
6166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6167 %                                                                             %
6168 %                                                                             %
6169 %                                                                             %
6170 +   W r i t e B l o b L S B S i g n e d S h o r t                             %
6171 %                                                                             %
6172 %                                                                             %
6173 %                                                                             %
6174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6175 %
6176 %  WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
6177 %  in least-significant byte first order.
6178 %
6179 %  The format of the WriteBlobLSBSignedShort method is:
6180 %
6181 %      ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
6182 %
6183 %  A description of each parameter follows.
6184 %
6185 %    o image: the image.
6186 %
6187 %    o value:  Specifies the value to write.
6188 %
6189 */
WriteBlobLSBSignedShort(Image * image,const signed short value)6190 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
6191   const signed short value)
6192 {
6193   union
6194   {
6195     unsigned short
6196       unsigned_value;
6197 
6198     signed short
6199       signed_value;
6200   } quantum;
6201 
6202   unsigned char
6203     buffer[2];
6204 
6205   assert(image != (Image *) NULL);
6206   assert(image->signature == MagickCoreSignature);
6207   quantum.signed_value=value;
6208   buffer[0]=(unsigned char) quantum.unsigned_value;
6209   buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
6210   return(WriteBlobStream(image,2,buffer));
6211 }
6212 
6213 /*
6214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6215 %                                                                             %
6216 %                                                                             %
6217 %                                                                             %
6218 +  W r i t e B l o b M S B L o n g                                            %
6219 %                                                                             %
6220 %                                                                             %
6221 %                                                                             %
6222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6223 %
6224 %  WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
6225 %  most-significant byte first order.
6226 %
6227 %  The format of the WriteBlobMSBLong method is:
6228 %
6229 %      ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6230 %
6231 %  A description of each parameter follows.
6232 %
6233 %    o value:  Specifies the value to write.
6234 %
6235 %    o image: the image.
6236 %
6237 */
WriteBlobMSBLong(Image * image,const unsigned int value)6238 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
6239 {
6240   unsigned char
6241     buffer[4];
6242 
6243   assert(image != (Image *) NULL);
6244   assert(image->signature == MagickCoreSignature);
6245   buffer[0]=(unsigned char) (value >> 24);
6246   buffer[1]=(unsigned char) (value >> 16);
6247   buffer[2]=(unsigned char) (value >> 8);
6248   buffer[3]=(unsigned char) value;
6249   return(WriteBlobStream(image,4,buffer));
6250 }
6251 
6252 /*
6253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6254 %                                                                             %
6255 %                                                                             %
6256 %                                                                             %
6257 +   W r i t e B l o b M S B S i g n e d S h o r t                             %
6258 %                                                                             %
6259 %                                                                             %
6260 %                                                                             %
6261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6262 %
6263 %  WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
6264 %  in most-significant byte first order.
6265 %
6266 %  The format of the WriteBlobMSBSignedShort method is:
6267 %
6268 %      ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
6269 %
6270 %  A description of each parameter follows.
6271 %
6272 %    o image: the image.
6273 %
6274 %    o value:  Specifies the value to write.
6275 %
6276 */
WriteBlobMSBSignedShort(Image * image,const signed short value)6277 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
6278   const signed short value)
6279 {
6280   union
6281   {
6282     unsigned short
6283       unsigned_value;
6284 
6285     signed short
6286       signed_value;
6287   } quantum;
6288 
6289   unsigned char
6290     buffer[2];
6291 
6292   assert(image != (Image *) NULL);
6293   assert(image->signature == MagickCoreSignature);
6294   quantum.signed_value=value;
6295   buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
6296   buffer[1]=(unsigned char) quantum.unsigned_value;
6297   return(WriteBlobStream(image,2,buffer));
6298 }
6299 
6300 /*
6301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6302 %                                                                             %
6303 %                                                                             %
6304 %                                                                             %
6305 +  W r i t e B l o b M S B S h o r t                                          %
6306 %                                                                             %
6307 %                                                                             %
6308 %                                                                             %
6309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6310 %
6311 %  WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6312 %  most-significant byte first order.
6313 %
6314 %  The format of the WriteBlobMSBShort method is:
6315 %
6316 %      ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6317 %
6318 %  A description of each parameter follows.
6319 %
6320 %   o  value:  Specifies the value to write.
6321 %
6322 %   o  file:  Specifies the file to write the data to.
6323 %
6324 */
WriteBlobMSBShort(Image * image,const unsigned short value)6325 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6326 {
6327   unsigned char
6328     buffer[2];
6329 
6330   assert(image != (Image *) NULL);
6331   assert(image->signature == MagickCoreSignature);
6332   buffer[0]=(unsigned char) (value >> 8);
6333   buffer[1]=(unsigned char) value;
6334   return(WriteBlobStream(image,2,buffer));
6335 }
6336 
6337 /*
6338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6339 %                                                                             %
6340 %                                                                             %
6341 %                                                                             %
6342 +  W r i t e B l o b S t r i n g                                              %
6343 %                                                                             %
6344 %                                                                             %
6345 %                                                                             %
6346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6347 %
6348 %  WriteBlobString() write a string to a blob.  It returns the number of
6349 %  characters written.
6350 %
6351 %  The format of the WriteBlobString method is:
6352 %
6353 %      ssize_t WriteBlobString(Image *image,const char *string)
6354 %
6355 %  A description of each parameter follows.
6356 %
6357 %    o image: the image.
6358 %
6359 %    o string: Specifies the string to write.
6360 %
6361 */
WriteBlobString(Image * image,const char * string)6362 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6363 {
6364   assert(image != (Image *) NULL);
6365   assert(image->signature == MagickCoreSignature);
6366   assert(string != (const char *) NULL);
6367   return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
6368 }
6369