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