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