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