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