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->custom_stream == (CustomStreamInfo *) NULL))
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 FileStream:
2714  case BlobStream:
2715  case ZipStream:
2716  return(MagickTrue);
2717  case UndefinedStream:
2718  case StandardStream:
2719  case BZipStream:
2720  case FifoStream:
2721  case PipeStream:
2722  return(MagickFalse);
2723  case CustomStream:
2724  {
2725  if ((blob_info->custom_stream->seeker != (CustomStreamSeeker) NULL) &&
2726  (blob_info->custom_stream->teller != (CustomStreamTeller) NULL))
2727  return(MagickTrue);
2728  break;
2729  }
2730  default:
2731  break;
2732  }
2733  return(MagickFalse);
2734 }
2735 
2736 /*
2737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2738 % %
2739 % %
2740 % %
2741 % I s B l o b T e m p o r a r y %
2742 % %
2743 % %
2744 % %
2745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2746 %
2747 % IsBlobTemporary() returns true if the blob is temporary.
2748 %
2749 % The format of the IsBlobTemporary method is:
2750 %
2751 % MagickBooleanType IsBlobTemporary(const Image *image)
2752 %
2753 % A description of each parameter follows:
2754 %
2755 % o image: the image.
2756 %
2757 */
2759 {
2760  assert(image != (const Image *) NULL);
2761  assert(image->signature == MagickCoreSignature);
2762  if (image->debug != MagickFalse)
2763  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2764  return(image->blob->temporary);
2765 }
2766 
2767 /*
2768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2769 % %
2770 % %
2771 % %
2772 + M a p B l o b %
2773 % %
2774 % %
2775 % %
2776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2777 %
2778 % MapBlob() creates a mapping from a file to a binary large object.
2779 %
2780 % The format of the MapBlob method is:
2781 %
2782 % void *MapBlob(int file,const MapMode mode,const MagickOffsetType offset,
2783 % const size_t length)
2784 %
2785 % A description of each parameter follows:
2786 %
2787 % o file: map this file descriptor.
2788 %
2789 % o mode: ReadMode, WriteMode, or IOMode.
2790 %
2791 % o offset: starting at this offset within the file.
2792 %
2793 % o length: the length of the mapping is returned in this pointer.
2794 %
2795 */
2796 MagickExport void *MapBlob(int file,const MapMode mode,
2797  const MagickOffsetType offset,const size_t length)
2798 {
2799 #if defined(MAGICKCORE_HAVE_MMAP)
2800  int
2801  flags,
2802  protection;
2803 
2804  void
2805  *map;
2806 
2807  /*
2808  Map file.
2809  */
2810  flags=0;
2811  if (file == -1)
2812 #if defined(MAP_ANONYMOUS)
2813  flags|=MAP_ANONYMOUS;
2814 #else
2815  return(NULL);
2816 #endif
2817  switch (mode)
2818  {
2819  case ReadMode:
2820  default:
2821  {
2822  protection=PROT_READ;
2823  flags|=MAP_PRIVATE;
2824  break;
2825  }
2826  case WriteMode:
2827  {
2828  protection=PROT_WRITE;
2829  flags|=MAP_SHARED;
2830  break;
2831  }
2832  case IOMode:
2833  {
2834  protection=PROT_READ | PROT_WRITE;
2835  flags|=MAP_SHARED;
2836  break;
2837  }
2838  }
2839 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2840  map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2841 #else
2842  map=mmap((char *) NULL,length,protection,flags | MAP_HUGETLB,file,(off_t)
2843  offset);
2844  if (map == MAP_FAILED)
2845  map=mmap((char *) NULL,length,protection,flags,file,(off_t) offset);
2846 #endif
2847  if (map == MAP_FAILED)
2848  return(NULL);
2849  return(map);
2850 #else
2851  (void) file;
2852  (void) mode;
2853  (void) offset;
2854  (void) length;
2855  return(NULL);
2856 #endif
2857 }
2858 
2859 /*
2860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2861 % %
2862 % %
2863 % %
2864 + M S B O r d e r L o n g %
2865 % %
2866 % %
2867 % %
2868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2869 %
2870 % MSBOrderLong() converts a least-significant byte first buffer of integers to
2871 % most-significant byte first.
2872 %
2873 % The format of the MSBOrderLong method is:
2874 %
2875 % void MSBOrderLong(unsigned char *buffer,const size_t length)
2876 %
2877 % A description of each parameter follows.
2878 %
2879 % o buffer: Specifies a pointer to a buffer of integers.
2880 %
2881 % o length: Specifies the length of the buffer.
2882 %
2883 */
2884 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2885 {
2886  int
2887  c;
2888 
2889  register unsigned char
2890  *p,
2891  *q;
2892 
2893  assert(buffer != (unsigned char *) NULL);
2894  q=buffer+length;
2895  while (buffer < q)
2896  {
2897  p=buffer+3;
2898  c=(int) (*p);
2899  *p=(*buffer);
2900  *buffer++=(unsigned char) c;
2901  p=buffer+1;
2902  c=(int) (*p);
2903  *p=(*buffer);
2904  *buffer++=(unsigned char) c;
2905  buffer+=2;
2906  }
2907 }
2908 
2909 /*
2910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2911 % %
2912 % %
2913 % %
2914 + M S B O r d e r S h o r t %
2915 % %
2916 % %
2917 % %
2918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2919 %
2920 % MSBOrderShort() converts a least-significant byte first buffer of integers
2921 % to most-significant byte first.
2922 %
2923 % The format of the MSBOrderShort method is:
2924 %
2925 % void MSBOrderShort(unsigned char *p,const size_t length)
2926 %
2927 % A description of each parameter follows.
2928 %
2929 % o p: Specifies a pointer to a buffer of integers.
2930 %
2931 % o length: Specifies the length of the buffer.
2932 %
2933 */
2934 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2935 {
2936  int
2937  c;
2938 
2939  register unsigned char
2940  *q;
2941 
2942  assert(p != (unsigned char *) NULL);
2943  q=p+length;
2944  while (p < q)
2945  {
2946  c=(int) (*p);
2947  *p=(*(p+1));
2948  p++;
2949  *p++=(unsigned char) c;
2950  }
2951 }
2952 
2953 /*
2954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2955 % %
2956 % %
2957 % %
2958 + O p e n B l o b %
2959 % %
2960 % %
2961 % %
2962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2963 %
2964 % OpenBlob() opens a file associated with the image. A file name of '-' sets
2965 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
2966 % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2967 % compressed for type 'w'. If the filename prefix is '|', it is piped to or
2968 % from a system command.
2969 %
2970 % The format of the OpenBlob method is:
2971 %
2972 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2973 % const BlobMode mode,ExceptionInfo *exception)
2974 %
2975 % A description of each parameter follows:
2976 %
2977 % o image_info: the image info.
2978 %
2979 % o image: the image.
2980 %
2981 % o mode: the mode for opening the file.
2982 %
2983 */
2984 
2985 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2986  Image *image)
2987 {
2988  const char
2989  *option;
2990 
2991  int
2992  status;
2993 
2994  size_t
2995  size;
2996 
2997  size=16384;
2998  option=GetImageOption(image_info,"stream:buffer-size");
2999  if (option != (const char *) NULL)
3000  size=StringToUnsignedLong(option);
3001  status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
3002  _IONBF : _IOFBF,size);
3003  return(status == 0 ? MagickTrue : MagickFalse);
3004 }
3005 
3007  Image *image,const BlobMode mode,ExceptionInfo *exception)
3008 {
3009  BlobInfo
3010  *magick_restrict blob_info;
3011 
3012  char
3013  extension[MagickPathExtent],
3014  filename[MagickPathExtent];
3015 
3016  const char
3017  *type;
3018 
3020  status;
3021 
3022  PolicyRights
3023  rights;
3024 
3025  assert(image_info != (ImageInfo *) NULL);
3026  assert(image_info->signature == MagickCoreSignature);
3027  if (image_info->debug != MagickFalse)
3029  image_info->filename);
3030  assert(image != (Image *) NULL);
3031  assert(image->signature == MagickCoreSignature);
3032  blob_info=image->blob;
3033  if (image_info->blob != (void *) NULL)
3034  {
3035  if (image_info->stream != (StreamHandler) NULL)
3036  blob_info->stream=(StreamHandler) image_info->stream;
3037  AttachBlob(blob_info,image_info->blob,image_info->length);
3038  return(MagickTrue);
3039  }
3040  if ((image_info->custom_stream != (CustomStreamInfo *) NULL) &&
3041  (*image->filename == '\0'))
3042  {
3043  blob_info->type=CustomStream;
3044  blob_info->custom_stream=image_info->custom_stream;
3045  return(MagickTrue);
3046  }
3047  (void) DetachBlob(blob_info);
3048  switch (mode)
3049  {
3050  default: type="r"; break;
3051  case ReadBlobMode: type="r"; break;
3052  case ReadBinaryBlobMode: type="rb"; break;
3053  case WriteBlobMode: type="w"; break;
3054  case WriteBinaryBlobMode: type="w+b"; break;
3055  case AppendBlobMode: type="a"; break;
3056  case AppendBinaryBlobMode: type="a+b"; break;
3057  }
3058  if (*type != 'r')
3059  blob_info->synchronize=image_info->synchronize;
3060  if (image_info->stream != (StreamHandler) NULL)
3061  {
3062  blob_info->stream=image_info->stream;
3063  if (*type == 'w')
3064  {
3065  blob_info->type=FifoStream;
3066  return(MagickTrue);
3067  }
3068  }
3069  /*
3070  Open image file.
3071  */
3072  *filename='\0';
3073  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3074  rights=ReadPolicyRights;
3075  if (*type == 'w')
3076  rights=WritePolicyRights;
3077  if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
3078  {
3079  errno=EPERM;
3081  "NotAuthorized","`%s'",filename);
3082  return(MagickFalse);
3083  }
3084  if ((LocaleCompare(filename,"-") == 0) ||
3085  ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
3086  {
3087  blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
3088 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3089  if (strchr(type,'b') != (char *) NULL)
3090  setmode(fileno(blob_info->file_info.file),_O_BINARY);
3091 #endif
3092  blob_info->type=StandardStream;
3093  blob_info->exempt=MagickTrue;
3094  return(SetStreamBuffering(image_info,image));
3095  }
3096  if (LocaleNCompare(filename,"fd:",3) == 0)
3097  {
3098  char
3099  fileMode[MagickPathExtent];
3100 
3101  *fileMode =(*type);
3102  fileMode[1]='\0';
3103  blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
3104 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
3105  if (strchr(type,'b') != (char *) NULL)
3106  setmode(fileno(blob_info->file_info.file),_O_BINARY);
3107 #endif
3108  blob_info->type=StandardStream;
3109  blob_info->exempt=MagickTrue;
3110  return(SetStreamBuffering(image_info,image));
3111  }
3112 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
3113  if (*filename == '|')
3114  {
3115  char
3116  fileMode[MagickPathExtent],
3117  *sanitize_command;
3118 
3119  /*
3120  Pipe image to or from a system command.
3121  */
3122 #if defined(SIGPIPE)
3123  if (*type == 'w')
3124  (void) signal(SIGPIPE,SIG_IGN);
3125 #endif
3126  *fileMode =(*type);
3127  fileMode[1]='\0';
3128  sanitize_command=SanitizeString(filename+1);
3129  blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,fileMode);
3130  sanitize_command=DestroyString(sanitize_command);
3131  if (blob_info->file_info.file == (FILE *) NULL)
3132  {
3133  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3134  return(MagickFalse);
3135  }
3136  blob_info->type=PipeStream;
3137  blob_info->exempt=MagickTrue;
3138  return(SetStreamBuffering(image_info,image));
3139  }
3140 #endif
3141  status=GetPathAttributes(filename,&blob_info->properties);
3142 #if defined(S_ISFIFO)
3143  if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
3144  {
3145  blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3146  if (blob_info->file_info.file == (FILE *) NULL)
3147  {
3148  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3149  return(MagickFalse);
3150  }
3151  blob_info->type=FileStream;
3152  blob_info->exempt=MagickTrue;
3153  return(SetStreamBuffering(image_info,image));
3154  }
3155 #endif
3156  GetPathComponent(image->filename,ExtensionPath,extension);
3157  if (*type == 'w')
3158  {
3159  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
3160  if ((image_info->adjoin == MagickFalse) ||
3161  (strchr(filename,'%') != (char *) NULL))
3162  {
3163  /*
3164  Form filename for multi-part images.
3165  */
3166  (void) InterpretImageFilename(image_info,image,image->filename,(int)
3167  image->scene,filename,exception);
3168  if ((LocaleCompare(filename,image->filename) == 0) &&
3169  ((GetPreviousImageInList(image) != (Image *) NULL) ||
3170  (GetNextImageInList(image) != (Image *) NULL)))
3171  {
3172  char
3173  path[MagickPathExtent];
3174 
3175  GetPathComponent(image->filename,RootPath,path);
3176  if (*extension == '\0')
3177  (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
3178  path,(double) image->scene);
3179  else
3180  (void) FormatLocaleString(filename,MagickPathExtent,
3181  "%s-%.20g.%s",path,(double) image->scene,extension);
3182  }
3183  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
3184 #if defined(macintosh)
3185  SetApplicationType(filename,image_info->magick,'8BIM');
3186 #endif
3187  }
3188  }
3189  if (image_info->file != (FILE *) NULL)
3190  {
3191  blob_info->file_info.file=image_info->file;
3192  blob_info->type=FileStream;
3193  blob_info->exempt=MagickTrue;
3194  }
3195  else
3196  if (*type == 'r')
3197  {
3198  blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3199  if (blob_info->file_info.file != (FILE *) NULL)
3200  {
3201  size_t
3202  count;
3203 
3204  unsigned char
3205  magick[3];
3206 
3207  blob_info->type=FileStream;
3208  (void) SetStreamBuffering(image_info,image);
3209  (void) ResetMagickMemory(magick,0,sizeof(magick));
3210  count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
3211  (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
3212 #if defined(MAGICKCORE_POSIX_SUPPORT)
3213  (void) fflush(blob_info->file_info.file);
3214 #endif
3216  " read %.20g magic header bytes",(double) count);
3217 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3218  if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
3219  ((int) magick[2] == 0x08))
3220  {
3221  if (blob_info->file_info.file != (FILE *) NULL)
3222  (void) fclose(blob_info->file_info.file);
3223  blob_info->file_info.file=(FILE *) NULL;
3224  blob_info->file_info.gzfile=gzopen(filename,type);
3225  if (blob_info->file_info.gzfile != (gzFile) NULL)
3226  blob_info->type=ZipStream;
3227  }
3228 #endif
3229 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3230  if (strncmp((char *) magick,"BZh",3) == 0)
3231  {
3232  if (blob_info->file_info.file != (FILE *) NULL)
3233  (void) fclose(blob_info->file_info.file);
3234  blob_info->file_info.file=(FILE *) NULL;
3235  blob_info->file_info.bzfile=BZ2_bzopen(filename,type);
3236  if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3237  blob_info->type=BZipStream;
3238  }
3239 #endif
3240  if (blob_info->type == FileStream)
3241  {
3242  const MagickInfo
3243  *magick_info;
3244 
3246  *sans_exception;
3247 
3248  size_t
3249  length;
3250 
3251  sans_exception=AcquireExceptionInfo();
3252  magick_info=GetMagickInfo(image_info->magick,sans_exception);
3253  sans_exception=DestroyExceptionInfo(sans_exception);
3254  length=(size_t) blob_info->properties.st_size;
3255  if ((magick_info != (const MagickInfo *) NULL) &&
3256  (GetMagickBlobSupport(magick_info) != MagickFalse) &&
3257  (length > MagickMaxBufferExtent) &&
3259  {
3260  void
3261  *blob;
3262 
3263  blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
3264  length);
3265  if (blob == (void *) NULL)
3267  else
3268  {
3269  /*
3270  Format supports blobs-- use memory-mapped I/O.
3271  */
3272  if (image_info->file != (FILE *) NULL)
3273  blob_info->exempt=MagickFalse;
3274  else
3275  {
3276  (void) fclose(blob_info->file_info.file);
3277  blob_info->file_info.file=(FILE *) NULL;
3278  }
3279  AttachBlob(blob_info,blob,length);
3280  blob_info->mapped=MagickTrue;
3281  }
3282  }
3283  }
3284  }
3285  }
3286  else
3287 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3288  if ((LocaleCompare(extension,"Z") == 0) ||
3289  (LocaleCompare(extension,"gz") == 0) ||
3290  (LocaleCompare(extension,"wmz") == 0) ||
3291  (LocaleCompare(extension,"svgz") == 0))
3292  {
3293  if (mode == WriteBinaryBlobMode)
3294  type="wb";
3295  blob_info->file_info.gzfile=gzopen(filename,type);
3296  if (blob_info->file_info.gzfile != (gzFile) NULL)
3297  blob_info->type=ZipStream;
3298  }
3299  else
3300 #endif
3301 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3302  if (LocaleCompare(extension,"bz2") == 0)
3303  {
3304  blob_info->file_info.bzfile=BZ2_bzopen(filename,type);
3305  if (blob_info->file_info.bzfile != (BZFILE *) NULL)
3306  blob_info->type=BZipStream;
3307  }
3308  else
3309 #endif
3310  {
3311  blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
3312  if (blob_info->file_info.file != (FILE *) NULL)
3313  {
3314  blob_info->type=FileStream;
3315  (void) SetStreamBuffering(image_info,image);
3316  }
3317  }
3318  blob_info->status=MagickFalse;
3319  if (blob_info->type != UndefinedStream)
3320  blob_info->size=GetBlobSize(image);
3321  else
3322  {
3323  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
3324  return(MagickFalse);
3325  }
3326  return(MagickTrue);
3327 }
3328 
3329 /*
3330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3331 % %
3332 % %
3333 % %
3334 + P i n g B l o b %
3335 % %
3336 % %
3337 % %
3338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3339 %
3340 % PingBlob() returns all the attributes of an image or image sequence except
3341 % for the pixels. It is much faster and consumes far less memory than
3342 % BlobToImage(). On failure, a NULL image is returned and exception
3343 % describes the reason for the failure.
3344 %
3345 % The format of the PingBlob method is:
3346 %
3347 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
3348 % const size_t length,ExceptionInfo *exception)
3349 %
3350 % A description of each parameter follows:
3351 %
3352 % o image_info: the image info.
3353 %
3354 % o blob: the address of a character stream in one of the image formats
3355 % understood by ImageMagick.
3356 %
3357 % o length: This size_t integer reflects the length in bytes of the blob.
3358 %
3359 % o exception: return any errors or warnings in this structure.
3360 %
3361 */
3362 
3363 #if defined(__cplusplus) || defined(c_plusplus)
3364 extern "C" {
3365 #endif
3366 
3367 static size_t PingStream(const Image *magick_unused(image),
3368  const void *magick_unused(pixels),const size_t columns)
3369 {
3370  magick_unreferenced(image);
3371  magick_unreferenced(pixels);
3372  return(columns);
3373 }
3374 
3375 #if defined(__cplusplus) || defined(c_plusplus)
3376 }
3377 #endif
3378 
3379 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3380  const size_t length,ExceptionInfo *exception)
3381 {
3382  Image
3383  *image;
3384 
3385  ImageInfo
3386  *ping_info;
3387 
3388  assert(image_info != (ImageInfo *) NULL);
3389  assert(image_info->signature == MagickCoreSignature);
3390  if (image_info->debug != MagickFalse)
3392  image_info->filename);
3393  assert(exception != (ExceptionInfo *) NULL);
3394  if ((blob == (const void *) NULL) || (length == 0))
3395  {
3396  (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3397  "UnrecognizedImageFormat","`%s'",image_info->magick);
3398  return((Image *) NULL);
3399  }
3400  ping_info=CloneImageInfo(image_info);
3401  ping_info->blob=(void *) AcquireQuantumMemory(length,sizeof(unsigned char));
3402  if (ping_info->blob == (const void *) NULL)
3403  {
3404  (void) ThrowMagickException(exception,GetMagickModule(),
3405  ResourceLimitFatalError,"MemoryAllocationFailed","`%s'","");
3406  return((Image *) NULL);
3407  }
3408  (void) memcpy(ping_info->blob,blob,length);
3409  ping_info->length=length;
3410  ping_info->ping=MagickTrue;
3411  image=ReadStream(ping_info,&PingStream,exception);
3412  ping_info->blob=(void *) RelinquishMagickMemory(ping_info->blob);
3413  ping_info=DestroyImageInfo(ping_info);
3414  return(image);
3415 }
3416 
3417 /*
3418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3419 % %
3420 % %
3421 % %
3422 + R e a d B l o b %
3423 % %
3424 % %
3425 % %
3426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3427 %
3428 % ReadBlob() reads data from the blob or image file and returns it. It
3429 % returns the number of bytes read. If length is zero, ReadBlob() returns
3430 % zero and has no other results. If length is greater than SSIZE_MAX, the
3431 % result is unspecified.
3432 %
3433 % The format of the ReadBlob method is:
3434 %
3435 % ssize_t ReadBlob(Image *image,const size_t length,void *data)
3436 %
3437 % A description of each parameter follows:
3438 %
3439 % o image: the image.
3440 %
3441 % o length: Specifies an integer representing the number of bytes to read
3442 % from the file.
3443 %
3444 % o data: Specifies an area to place the information requested from the
3445 % file.
3446 %
3447 */
3448 MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data)
3449 {
3450  BlobInfo
3451  *magick_restrict blob_info;
3452 
3453  int
3454  c;
3455 
3456  register unsigned char
3457  *q;
3458 
3459  ssize_t
3460  count;
3461 
3462  assert(image != (Image *) NULL);
3463  assert(image->signature == MagickCoreSignature);
3464  assert(image->blob != (BlobInfo *) NULL);
3465  assert(image->blob->type != UndefinedStream);
3466  if (length == 0)
3467  return(0);
3468  assert(data != (void *) NULL);
3469  blob_info=image->blob;
3470  count=0;
3471  q=(unsigned char *) data;
3472  switch (blob_info->type)
3473  {
3474  case UndefinedStream:
3475  break;
3476  case StandardStream:
3477  case FileStream:
3478  case PipeStream:
3479  {
3480  switch (length)
3481  {
3482  default:
3483  {
3484  count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3485  break;
3486  }
3487  case 4:
3488  {
3489  c=getc(blob_info->file_info.file);
3490  if (c == EOF)
3491  break;
3492  *q++=(unsigned char) c;
3493  count++;
3494  }
3495  case 3:
3496  {
3497  c=getc(blob_info->file_info.file);
3498  if (c == EOF)
3499  break;
3500  *q++=(unsigned char) c;
3501  count++;
3502  }
3503  case 2:
3504  {
3505  c=getc(blob_info->file_info.file);
3506  if (c == EOF)
3507  break;
3508  *q++=(unsigned char) c;
3509  count++;
3510  }
3511  case 1:
3512  {
3513  c=getc(blob_info->file_info.file);
3514  if (c == EOF)
3515  break;
3516  *q++=(unsigned char) c;
3517  count++;
3518  }
3519  case 0:
3520  break;
3521  }
3522  break;
3523  }
3524  case ZipStream:
3525  {
3526 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3527  switch (length)
3528  {
3529  default:
3530  {
3531  count=(ssize_t) gzread(blob_info->file_info.gzfile,q,
3532  (unsigned int) length);
3533  break;
3534  }
3535  case 4:
3536  {
3537  c=gzgetc(blob_info->file_info.gzfile);
3538  if (c == EOF)
3539  break;
3540  *q++=(unsigned char) c;
3541  count++;
3542  }
3543  case 3:
3544  {
3545  c=gzgetc(blob_info->file_info.gzfile);
3546  if (c == EOF)
3547  break;
3548  *q++=(unsigned char) c;
3549  count++;
3550  }
3551  case 2:
3552  {
3553  c=gzgetc(blob_info->file_info.gzfile);
3554  if (c == EOF)
3555  break;
3556  *q++=(unsigned char) c;
3557  count++;
3558  }
3559  case 1:
3560  {
3561  c=gzgetc(blob_info->file_info.gzfile);
3562  if (c == EOF)
3563  break;
3564  *q++=(unsigned char) c;
3565  count++;
3566  }
3567  case 0:
3568  break;
3569  }
3570 #endif
3571  break;
3572  }
3573  case BZipStream:
3574  {
3575 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3576  count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q,(int) length);
3577 #endif
3578  break;
3579  }
3580  case FifoStream:
3581  break;
3582  case BlobStream:
3583  {
3584  register const unsigned char
3585  *p;
3586 
3587  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3588  {
3589  blob_info->eof=MagickTrue;
3590  break;
3591  }
3592  p=blob_info->data+blob_info->offset;
3593  count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3594  blob_info->length-blob_info->offset);
3595  blob_info->offset+=count;
3596  if (count != (ssize_t) length)
3597  blob_info->eof=MagickTrue;
3598  (void) memcpy(q,p,(size_t) count);
3599  break;
3600  }
3601  case CustomStream:
3602  {
3603  if (blob_info->custom_stream->reader != (CustomStreamHandler) NULL)
3604  count=blob_info->custom_stream->reader(q,length,
3605  blob_info->custom_stream->data);
3606  break;
3607  }
3608  }
3609  return(count);
3610 }
3611 
3612 /*
3613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3614 % %
3615 % %
3616 % %
3617 + R e a d B l o b B y t e %
3618 % %
3619 % %
3620 % %
3621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3622 %
3623 % ReadBlobByte() reads a single byte from the image file and returns it.
3624 %
3625 % The format of the ReadBlobByte method is:
3626 %
3627 % int ReadBlobByte(Image *image)
3628 %
3629 % A description of each parameter follows.
3630 %
3631 % o image: the image.
3632 %
3633 */
3635 {
3636  BlobInfo
3637  *magick_restrict blob_info;
3638 
3639  register const unsigned char
3640  *p;
3641 
3642  unsigned char
3643  buffer[1];
3644 
3645  assert(image != (Image *) NULL);
3646  assert(image->signature == MagickCoreSignature);
3647  assert(image->blob != (BlobInfo *) NULL);
3648  assert(image->blob->type != UndefinedStream);
3649  blob_info=image->blob;
3650  switch (blob_info->type)
3651  {
3652  case StandardStream:
3653  case FileStream:
3654  case PipeStream:
3655  {
3656  int
3657  c;
3658 
3659  p=(const unsigned char *) buffer;
3660  c=getc(blob_info->file_info.file);
3661  if (c == EOF)
3662  return(EOF);
3663  *buffer=(unsigned char) c;
3664  break;
3665  }
3666  default:
3667  {
3668  ssize_t
3669  count;
3670 
3671  p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
3672  if (count != 1)
3673  return(EOF);
3674  break;
3675  }
3676  }
3677  return((int) (*p));
3678 }
3679 
3680 /*
3681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3682 % %
3683 % %
3684 % %
3685 + R e a d B l o b D o u b l e %
3686 % %
3687 % %
3688 % %
3689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3690 %
3691 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3692 % specified by the endian member of the image structure.
3693 %
3694 % The format of the ReadBlobDouble method is:
3695 %
3696 % double ReadBlobDouble(Image *image)
3697 %
3698 % A description of each parameter follows.
3699 %
3700 % o image: the image.
3701 %
3702 */
3704 {
3705  union
3706  {
3708  unsigned_value;
3709 
3710  double
3711  double_value;
3712  } quantum;
3713 
3714  quantum.double_value=0.0;
3715  quantum.unsigned_value=ReadBlobLongLong(image);
3716  return(quantum.double_value);
3717 }
3718 
3719 /*
3720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3721 % %
3722 % %
3723 % %
3724 + R e a d B l o b F l o a t %
3725 % %
3726 % %
3727 % %
3728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3729 %
3730 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3731 % specified by the endian member of the image structure.
3732 %
3733 % The format of the ReadBlobFloat method is:
3734 %
3735 % float ReadBlobFloat(Image *image)
3736 %
3737 % A description of each parameter follows.
3738 %
3739 % o image: the image.
3740 %
3741 */
3743 {
3744  union
3745  {
3746  unsigned int
3747  unsigned_value;
3748 
3749  float
3750  float_value;
3751  } quantum;
3752 
3753  quantum.float_value=0.0;
3754  quantum.unsigned_value=ReadBlobLong(image);
3755  return(quantum.float_value);
3756 }
3757 
3758 /*
3759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3760 % %
3761 % %
3762 % %
3763 + R e a d B l o b L o n g %
3764 % %
3765 % %
3766 % %
3767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3768 %
3769 % ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3770 % byte-order specified by the endian member of the image structure.
3771 %
3772 % The format of the ReadBlobLong method is:
3773 %
3774 % unsigned int ReadBlobLong(Image *image)
3775 %
3776 % A description of each parameter follows.
3777 %
3778 % o image: the image.
3779 %
3780 */
3781 MagickExport unsigned int ReadBlobLong(Image *image)
3782 {
3783  register const unsigned char
3784  *p;
3785 
3786  ssize_t
3787  count;
3788 
3789  unsigned char
3790  buffer[4];
3791 
3792  unsigned int
3793  value;
3794 
3795  assert(image != (Image *) NULL);
3796  assert(image->signature == MagickCoreSignature);
3797  *buffer='\0';
3798  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3799  if (count != 4)
3800  return(0UL);
3801  if (image->endian == LSBEndian)
3802  {
3803  value=(unsigned int) (*p++);
3804  value|=(unsigned int) (*p++) << 8;
3805  value|=(unsigned int) (*p++) << 16;
3806  value|=(unsigned int) (*p++) << 24;
3807  return(value);
3808  }
3809  value=(unsigned int) (*p++) << 24;
3810  value|=(unsigned int) (*p++) << 16;
3811  value|=(unsigned int) (*p++) << 8;
3812  value|=(unsigned int) (*p++);
3813  return(value);
3814 }
3815 
3816 /*
3817 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3818 % %
3819 % %
3820 % %
3821 + R e a d B l o b L o n g L o n g %
3822 % %
3823 % %
3824 % %
3825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3826 %
3827 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3828 % byte-order specified by the endian member of the image structure.
3829 %
3830 % The format of the ReadBlobLongLong method is:
3831 %
3832 % MagickSizeType ReadBlobLongLong(Image *image)
3833 %
3834 % A description of each parameter follows.
3835 %
3836 % o image: the image.
3837 %
3838 */
3840 {
3842  value;
3843 
3844  register const unsigned char
3845  *p;
3846 
3847  ssize_t
3848  count;
3849 
3850  unsigned char
3851  buffer[8];
3852 
3853  assert(image != (Image *) NULL);
3854  assert(image->signature == MagickCoreSignature);
3855  *buffer='\0';
3856  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3857  if (count != 8)
3858  return(MagickULLConstant(0));
3859  if (image->endian == LSBEndian)
3860  {
3861  value=(MagickSizeType) (*p++);
3862  value|=(MagickSizeType) (*p++) << 8;
3863  value|=(MagickSizeType) (*p++) << 16;
3864  value|=(MagickSizeType) (*p++) << 24;
3865  value|=(MagickSizeType) (*p++) << 32;
3866  value|=(MagickSizeType) (*p++) << 40;
3867  value|=(MagickSizeType) (*p++) << 48;
3868  value|=(MagickSizeType) (*p++) << 56;
3869  return(value);
3870  }
3871  value=(MagickSizeType) (*p++) << 56;
3872  value|=(MagickSizeType) (*p++) << 48;
3873  value|=(MagickSizeType) (*p++) << 40;
3874  value|=(MagickSizeType) (*p++) << 32;
3875  value|=(MagickSizeType) (*p++) << 24;
3876  value|=(MagickSizeType) (*p++) << 16;
3877  value|=(MagickSizeType) (*p++) << 8;
3878  value|=(MagickSizeType) (*p++);
3879  return(value);
3880 }
3881 
3882 /*
3883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3884 % %
3885 % %
3886 % %
3887 + R e a d B l o b S h o r t %
3888 % %
3889 % %
3890 % %
3891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3892 %
3893 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3894 % specified by the endian member of the image structure.
3895 %
3896 % The format of the ReadBlobShort method is:
3897 %
3898 % unsigned short ReadBlobShort(Image *image)
3899 %
3900 % A description of each parameter follows.
3901 %
3902 % o image: the image.
3903 %
3904 */
3905 MagickExport unsigned short ReadBlobShort(Image *image)
3906 {
3907  register const unsigned char
3908  *p;
3909 
3910  register unsigned short
3911  value;
3912 
3913  ssize_t
3914  count;
3915 
3916  unsigned char
3917  buffer[2];
3918 
3919  assert(image != (Image *) NULL);
3920  assert(image->signature == MagickCoreSignature);
3921  *buffer='\0';
3922  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3923  if (count != 2)
3924  return((unsigned short) 0U);
3925  if (image->endian == LSBEndian)
3926  {
3927  value=(unsigned short) (*p++);
3928  value|=(unsigned short) (*p++) << 8;
3929  return(value);
3930  }
3931  value=(unsigned short) ((unsigned short) (*p++) << 8);
3932  value|=(unsigned short) (*p++);
3933  return(value);
3934 }
3935 
3936 /*
3937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3938 % %
3939 % %
3940 % %
3941 + R e a d B l o b L S B L o n g %
3942 % %
3943 % %
3944 % %
3945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3946 %
3947 % ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3948 % least-significant byte first order.
3949 %
3950 % The format of the ReadBlobLSBLong method is:
3951 %
3952 % unsigned int ReadBlobLSBLong(Image *image)
3953 %
3954 % A description of each parameter follows.
3955 %
3956 % o image: the image.
3957 %
3958 */
3959 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3960 {
3961  register const unsigned char
3962  *p;
3963 
3964  register unsigned int
3965  value;
3966 
3967  ssize_t
3968  count;
3969 
3970  unsigned char
3971  buffer[4];
3972 
3973  assert(image != (Image *) NULL);
3974  assert(image->signature == MagickCoreSignature);
3975  *buffer='\0';
3976  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3977  if (count != 4)
3978  return(0U);
3979  value=(unsigned int) (*p++);
3980  value|=(unsigned int) (*p++) << 8;
3981  value|=(unsigned int) (*p++) << 16;
3982  value|=(unsigned int) (*p++) << 24;
3983  return(value);
3984 }
3985 
3986 /*
3987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3988 % %
3989 % %
3990 % %
3991 + R e a d B l o b L S B S i g n e d L o n g %
3992 % %
3993 % %
3994 % %
3995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3996 %
3997 % ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3998 % least-significant byte first order.
3999 %
4000 % The format of the ReadBlobLSBSignedLong method is:
4001 %
4002 % signed int ReadBlobLSBSignedLong(Image *image)
4003 %
4004 % A description of each parameter follows.
4005 %
4006 % o image: the image.
4007 %
4008 */
4010 {
4011  union
4012  {
4013  unsigned int
4014  unsigned_value;
4015 
4016  signed int
4017  signed_value;
4018  } quantum;
4019 
4020  quantum.unsigned_value=ReadBlobLSBLong(image);
4021  return(quantum.signed_value);
4022 }
4023 
4024 /*
4025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4026 % %
4027 % %
4028 % %
4029 + R e a d B l o b L S B S h o r t %
4030 % %
4031 % %
4032 % %
4033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4034 %
4035 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
4036 % least-significant byte first order.
4037 %
4038 % The format of the ReadBlobLSBShort method is:
4039 %
4040 % unsigned short ReadBlobLSBShort(Image *image)
4041 %
4042 % A description of each parameter follows.
4043 %
4044 % o image: the image.
4045 %
4046 */
4047 MagickExport unsigned short ReadBlobLSBShort(Image *image)
4048 {
4049  register const unsigned char
4050  *p;
4051 
4052  register unsigned short
4053  value;
4054 
4055  ssize_t
4056  count;
4057 
4058  unsigned char
4059  buffer[2];
4060 
4061  assert(image != (Image *) NULL);
4062  assert(image->signature == MagickCoreSignature);
4063  *buffer='\0';
4064  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4065  if (count != 2)
4066  return((unsigned short) 0U);
4067  value=(unsigned short) (*p++);
4068  value|=(unsigned short) (*p++) << 8;
4069  return(value);
4070 }
4071 
4072 /*
4073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4074 % %
4075 % %
4076 % %
4077 + R e a d B l o b L S B S i g n e d S h o r t %
4078 % %
4079 % %
4080 % %
4081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4082 %
4083 % ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
4084 % least-significant byte-order.
4085 %
4086 % The format of the ReadBlobLSBSignedShort method is:
4087 %
4088 % signed short ReadBlobLSBSignedShort(Image *image)
4089 %
4090 % A description of each parameter follows.
4091 %
4092 % o image: the image.
4093 %
4094 */
4096 {
4097  union
4098  {
4099  unsigned short
4100  unsigned_value;
4101 
4102  signed short
4103  signed_value;
4104  } quantum;
4105 
4106  quantum.unsigned_value=ReadBlobLSBShort(image);
4107  return(quantum.signed_value);
4108 }
4109 
4110 /*
4111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4112 % %
4113 % %
4114 % %
4115 + R e a d B l o b M S B L o n g %
4116 % %
4117 % %
4118 % %
4119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4120 %
4121 % ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
4122 % most-significant byte first order.
4123 %
4124 % The format of the ReadBlobMSBLong method is:
4125 %
4126 % unsigned int ReadBlobMSBLong(Image *image)
4127 %
4128 % A description of each parameter follows.
4129 %
4130 % o image: the image.
4131 %
4132 */
4133 MagickExport unsigned int ReadBlobMSBLong(Image *image)
4134 {
4135  register const unsigned char
4136  *p;
4137 
4138  register unsigned int
4139  value;
4140 
4141  ssize_t
4142  count;
4143 
4144  unsigned char
4145  buffer[4];
4146 
4147  assert(image != (Image *) NULL);
4148  assert(image->signature == MagickCoreSignature);
4149  *buffer='\0';
4150  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
4151  if (count != 4)
4152  return(0UL);
4153  value=(unsigned int) (*p++) << 24;
4154  value|=(unsigned int) (*p++) << 16;
4155  value|=(unsigned int) (*p++) << 8;
4156  value|=(unsigned int) (*p++);
4157  return(value);
4158 }
4159 
4160 /*
4161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4162 % %
4163 % %
4164 % %
4165 + R e a d B l o b M S B L o n g L o n g %
4166 % %
4167 % %
4168 % %
4169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4170 %
4171 % ReadBlobMSBLongLong() reads a unsigned long long value as a 64-bit quantity
4172 % in most-significant byte first order.
4173 %
4174 % The format of the ReadBlobMSBLongLong method is:
4175 %
4176 % unsigned int ReadBlobMSBLongLong(Image *image)
4177 %
4178 % A description of each parameter follows.
4179 %
4180 % o image: the image.
4181 %
4182 */
4184 {
4185  register const unsigned char
4186  *p;
4187 
4188  register MagickSizeType
4189  value;
4190 
4191  ssize_t
4192  count;
4193 
4194  unsigned char
4195  buffer[8];
4196 
4197  assert(image != (Image *) NULL);
4198  assert(image->signature == MagickCoreSignature);
4199  *buffer='\0';
4200  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
4201  if (count != 8)
4202  return(MagickULLConstant(0));
4203  value=(MagickSizeType) (*p++) << 56;
4204  value|=(MagickSizeType) (*p++) << 48;
4205  value|=(MagickSizeType) (*p++) << 40;
4206  value|=(MagickSizeType) (*p++) << 32;
4207  value|=(MagickSizeType) (*p++) << 24;
4208  value|=(MagickSizeType) (*p++) << 16;
4209  value|=(MagickSizeType) (*p++) << 8;
4210  value|=(MagickSizeType) (*p++);
4211  return(value);
4212 }
4213 
4214 /*
4215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4216 % %
4217 % %
4218 % %
4219 + R e a d B l o b M S B S h o r t %
4220 % %
4221 % %
4222 % %
4223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4224 %
4225 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
4226 % most-significant byte first order.
4227 %
4228 % The format of the ReadBlobMSBShort method is:
4229 %
4230 % unsigned short ReadBlobMSBShort(Image *image)
4231 %
4232 % A description of each parameter follows.
4233 %
4234 % o image: the image.
4235 %
4236 */
4237 MagickExport unsigned short ReadBlobMSBShort(Image *image)
4238 {
4239  register const unsigned char
4240  *p;
4241 
4242  register unsigned short
4243  value;
4244 
4245  ssize_t
4246  count;
4247 
4248  unsigned char
4249  buffer[2];
4250 
4251  assert(image != (Image *) NULL);
4252  assert(image->signature == MagickCoreSignature);
4253  *buffer='\0';
4254  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4255  if (count != 2)
4256  return((unsigned short) 0U);
4257  value=(unsigned short) ((*p++) << 8);
4258  value|=(unsigned short) (*p++);
4259  return((unsigned short) (value & 0xffff));
4260 }
4261 
4262 /*
4263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4264 % %
4265 % %
4266 % %
4267 + R e a d B l o b M S B S i g n e d L o n g %
4268 % %
4269 % %
4270 % %
4271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4272 %
4273 % ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4274 % most-significant byte-order.
4275 %
4276 % The format of the ReadBlobMSBSignedLong method is:
4277 %
4278 % signed int ReadBlobMSBSignedLong(Image *image)
4279 %
4280 % A description of each parameter follows.
4281 %
4282 % o image: the image.
4283 %
4284 */
4286 {
4287  union
4288  {
4289  unsigned int
4290  unsigned_value;
4291 
4292  signed int
4293  signed_value;
4294  } quantum;
4295 
4296  quantum.unsigned_value=ReadBlobMSBLong(image);
4297  return(quantum.signed_value);
4298 }
4299 
4300 /*
4301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4302 % %
4303 % %
4304 % %
4305 + R e a d B l o b M S B S i g n e d S h o r t %
4306 % %
4307 % %
4308 % %
4309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4310 %
4311 % ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4312 % most-significant byte-order.
4313 %
4314 % The format of the ReadBlobMSBSignedShort method is:
4315 %
4316 % signed short ReadBlobMSBSignedShort(Image *image)
4317 %
4318 % A description of each parameter follows.
4319 %
4320 % o image: the image.
4321 %
4322 */
4324 {
4325  union
4326  {
4327  unsigned short
4328  unsigned_value;
4329 
4330  signed short
4331  signed_value;
4332  } quantum;
4333 
4334  quantum.unsigned_value=ReadBlobMSBShort(image);
4335  return(quantum.signed_value);
4336 }
4337 
4338 /*
4339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4340 % %
4341 % %
4342 % %
4343 + R e a d B l o b S i g n e d L o n g %
4344 % %
4345 % %
4346 % %
4347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4348 %
4349 % ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4350 % byte-order specified by the endian member of the image structure.
4351 %
4352 % The format of the ReadBlobSignedLong method is:
4353 %
4354 % signed int ReadBlobSignedLong(Image *image)
4355 %
4356 % A description of each parameter follows.
4357 %
4358 % o image: the image.
4359 %
4360 */
4362 {
4363  union
4364  {
4365  unsigned int
4366  unsigned_value;
4367 
4368  signed int
4369  signed_value;
4370  } quantum;
4371 
4372  quantum.unsigned_value=ReadBlobLong(image);
4373  return(quantum.signed_value);
4374 }
4375 
4376 /*
4377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4378 % %
4379 % %
4380 % %
4381 + R e a d B l o b S i g n e d S h o r t %
4382 % %
4383 % %
4384 % %
4385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4386 %
4387 % ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4388 % byte-order specified by the endian member of the image structure.
4389 %
4390 % The format of the ReadBlobSignedShort method is:
4391 %
4392 % signed short ReadBlobSignedShort(Image *image)
4393 %
4394 % A description of each parameter follows.
4395 %
4396 % o image: the image.
4397 %
4398 */
4400 {
4401  union
4402  {
4403  unsigned short
4404  unsigned_value;
4405 
4406  signed short
4407  signed_value;
4408  } quantum;
4409 
4410  quantum.unsigned_value=ReadBlobShort(image);
4411  return(quantum.signed_value);
4412 }
4413 
4414 /*
4415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4416 % %
4417 % %
4418 % %
4419 + R e a d B l o b S t r e a m %
4420 % %
4421 % %
4422 % %
4423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4424 %
4425 % ReadBlobStream() reads data from the blob or image file and returns it. It
4426 % returns a pointer to the data buffer you supply or to the image memory
4427 % buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4428 % returns a count of zero and has no other results. If length is greater than
4429 % SSIZE_MAX, the result is unspecified.
4430 %
4431 % The format of the ReadBlobStream method is:
4432 %
4433 % const void *ReadBlobStream(Image *image,const size_t length,void *data,
4434 % ssize_t *count)
4435 %
4436 % A description of each parameter follows:
4437 %
4438 % o image: the image.
4439 %
4440 % o length: Specifies an integer representing the number of bytes to read
4441 % from the file.
4442 %
4443 % o count: returns the number of bytes read.
4444 %
4445 % o data: Specifies an area to place the information requested from the
4446 % file.
4447 %
4448 */
4449 MagickExport const void *ReadBlobStream(Image *image,const size_t length,
4450  void *data,ssize_t *count)
4451 {
4452  BlobInfo
4453  *magick_restrict blob_info;
4454 
4455  assert(image != (Image *) NULL);
4456  assert(image->signature == MagickCoreSignature);
4457  assert(image->blob != (BlobInfo *) NULL);
4458  assert(image->blob->type != UndefinedStream);
4459  assert(count != (ssize_t *) NULL);
4460  blob_info=image->blob;
4461  if (blob_info->type != BlobStream)
4462  {
4463  assert(data != NULL);
4464  *count=ReadBlob(image,length,(unsigned char *) data);
4465  return(data);
4466  }
4467  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4468  {
4469  *count=0;
4470  blob_info->eof=MagickTrue;
4471  return(data);
4472  }
4473  data=blob_info->data+blob_info->offset;
4474  *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4475  blob_info->length-blob_info->offset);
4476  blob_info->offset+=(*count);
4477  if (*count != (ssize_t) length)
4478  blob_info->eof=MagickTrue;
4479  return(data);
4480 }
4481 
4482 /*
4483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4484 % %
4485 % %
4486 % %
4487 + R e a d B l o b S t r i n g %
4488 % %
4489 % %
4490 % %
4491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4492 %
4493 % ReadBlobString() reads characters from a blob or file until a newline
4494 % character is read or an end-of-file condition is encountered.
4495 %
4496 % The format of the ReadBlobString method is:
4497 %
4498 % char *ReadBlobString(Image *image,char *string)
4499 %
4500 % A description of each parameter follows:
4501 %
4502 % o image: the image.
4503 %
4504 % o string: the address of a character buffer.
4505 %
4506 */
4507 MagickExport char *ReadBlobString(Image *image,char *string)
4508 {
4509  register const unsigned char
4510  *p;
4511 
4512  register ssize_t
4513  i;
4514 
4515  ssize_t
4516  count;
4517 
4518  unsigned char
4519  buffer[1];
4520 
4521  assert(image != (Image *) NULL);
4522  assert(image->signature == MagickCoreSignature);
4523  for (i=0; i < (MagickPathExtent-1L); i++)
4524  {
4525  p=(const unsigned char *) ReadBlobStream(image,1,buffer,&count);
4526  if (count != 1)
4527  {
4528  if (i == 0)
4529  return((char *) NULL);
4530  string[i]='\0';
4531  break;
4532  }
4533  string[i]=(char) (*p);
4534  if ((string[i] == '\r') || (string[i] == '\n'))
4535  break;
4536  }
4537  if (string[i] == '\r')
4538  (void) ReadBlobStream(image,1,buffer,&count);
4539  string[i]='\0';
4540  return(string);
4541 }
4542 
4543 /*
4544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4545 % %
4546 % %
4547 % %
4548 + R e f e r e n c e B l o b %
4549 % %
4550 % %
4551 % %
4552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4553 %
4554 % ReferenceBlob() increments the reference count associated with the pixel
4555 % blob returning a pointer to the blob.
4556 %
4557 % The format of the ReferenceBlob method is:
4558 %
4559 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
4560 %
4561 % A description of each parameter follows:
4562 %
4563 % o blob_info: the blob_info.
4564 %
4565 */
4567 {
4568  assert(blob != (BlobInfo *) NULL);
4569  assert(blob->signature == MagickCoreSignature);
4570  if (blob->debug != MagickFalse)
4571  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4573  blob->reference_count++;
4575  return(blob);
4576 }
4577 
4578 /*
4579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4580 % %
4581 % %
4582 % %
4583 + S e e k B l o b %
4584 % %
4585 % %
4586 % %
4587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4588 %
4589 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
4590 % and returns the resulting offset.
4591 %
4592 % The format of the SeekBlob method is:
4593 %
4594 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4595 % const int whence)
4596 %
4597 % A description of each parameter follows:
4598 %
4599 % o image: the image.
4600 %
4601 % o offset: Specifies an integer representing the offset in bytes.
4602 %
4603 % o whence: Specifies an integer representing how the offset is
4604 % treated relative to the beginning of the blob as follows:
4605 %
4606 % SEEK_SET Set position equal to offset bytes.
4607 % SEEK_CUR Set position to current location plus offset.
4608 % SEEK_END Set position to EOF plus offset.
4609 %
4610 */
4612  const MagickOffsetType offset,const int whence)
4613 {
4614  BlobInfo
4615  *magick_restrict blob_info;
4616 
4617  assert(image != (Image *) NULL);
4618  assert(image->signature == MagickCoreSignature);
4619  if (image->debug != MagickFalse)
4620  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4621  assert(image->blob != (BlobInfo *) NULL);
4622  assert(image->blob->type != UndefinedStream);
4623  blob_info=image->blob;
4624  switch (blob_info->type)
4625  {
4626  case UndefinedStream:
4627  break;
4628  case StandardStream:
4629  case PipeStream:
4630  return(-1);
4631  case FileStream:
4632  {
4633  if ((offset < 0) && (whence == SEEK_SET))
4634  return(-1);
4635  if (fseek(blob_info->file_info.file,offset,whence) < 0)
4636  return(-1);
4637  blob_info->offset=TellBlob(image);
4638  break;
4639  }
4640  case ZipStream:
4641  {
4642 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4643  if (gzseek(blob_info->file_info.gzfile,(off_t) offset,whence) < 0)
4644  return(-1);
4645 #endif
4646  blob_info->offset=TellBlob(image);
4647  break;
4648  }
4649  case BZipStream:
4650  return(-1);
4651  case FifoStream:
4652  return(-1);
4653  case BlobStream:
4654  {
4655  switch (whence)
4656  {
4657  case SEEK_SET:
4658  default:
4659  {
4660  if (offset < 0)
4661  return(-1);
4662  blob_info->offset=offset;
4663  break;
4664  }
4665  case SEEK_CUR:
4666  {
4667  if ((blob_info->offset+offset) < 0)
4668  return(-1);
4669  blob_info->offset+=offset;
4670  break;
4671  }
4672  case SEEK_END:
4673  {
4674  if (((MagickOffsetType) blob_info->length+offset) < 0)
4675  return(-1);
4676  blob_info->offset=blob_info->length+offset;
4677  break;
4678  }
4679  }
4680  break;
4681  }
4682  case CustomStream:
4683  {
4684  if (blob_info->custom_stream->seeker == (CustomStreamSeeker) NULL)
4685  return(-1);
4686  blob_info->offset=blob_info->custom_stream->seeker(offset,whence,
4687  blob_info->custom_stream->data);
4688  break;
4689  }
4690  }
4691  return(blob_info->offset);
4692 }
4693 
4694 /*
4695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4696 % %
4697 % %
4698 % %
4699 + S e t B l o b E x e m p t %
4700 % %
4701 % %
4702 % %
4703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4704 %
4705 % SetBlobExempt() sets the blob exempt status.
4706 %
4707 % The format of the SetBlobExempt method is:
4708 %
4709 % MagickBooleanType SetBlobExempt(const Image *image,
4710 % const MagickBooleanType exempt)
4711 %
4712 % A description of each parameter follows:
4713 %
4714 % o image: the image.
4715 %
4716 % o exempt: Set to true if this blob is exempt from being closed.
4717 %
4718 */
4720 {
4721  assert(image != (const Image *) NULL);
4722  assert(image->signature == MagickCoreSignature);
4723  if (image->debug != MagickFalse)
4724  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4725  image->blob->exempt=exempt;
4726 }
4727 
4728 /*
4729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4730 % %
4731 % %
4732 % %
4733 + S e t B l o b E x t e n t %
4734 % %
4735 % %
4736 % %
4737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4738 %
4739 % SetBlobExtent() ensures enough space is allocated for the blob. If the
4740 % method is successful, subsequent writes to bytes in the specified range are
4741 % guaranteed not to fail.
4742 %
4743 % The format of the SetBlobExtent method is:
4744 %
4745 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
4746 %
4747 % A description of each parameter follows:
4748 %
4749 % o image: the image.
4750 %
4751 % o extent: the blob maximum extent.
4752 %
4753 */
4755  const MagickSizeType extent)
4756 {
4757  BlobInfo
4758  *magick_restrict blob_info;
4759 
4760  assert(image != (Image *) NULL);
4761  assert(image->signature == MagickCoreSignature);
4762  if (image->debug != MagickFalse)
4763  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4764  assert(image->blob != (BlobInfo *) NULL);
4765  assert(image->blob->type != UndefinedStream);
4766  blob_info=image->blob;
4767  switch (blob_info->type)
4768  {
4769  case UndefinedStream:
4770  break;
4771  case StandardStream:
4772  return(MagickFalse);
4773  case FileStream:
4774  {
4776  offset;
4777 
4778  ssize_t
4779  count;
4780 
4781  if (extent != (MagickSizeType) ((off_t) extent))
4782  return(MagickFalse);
4783  offset=SeekBlob(image,0,SEEK_END);
4784  if (offset < 0)
4785  return(MagickFalse);
4786  if ((MagickSizeType) offset >= extent)
4787  break;
4788  offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4789  if (offset < 0)
4790  break;
4791  count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4792  blob_info->file_info.file);
4793 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4794  if (blob_info->synchronize != MagickFalse)
4795  {
4796  int
4797  file;
4798 
4799  file=fileno(blob_info->file_info.file);
4800  if ((file == -1) || (offset < 0))
4801  return(MagickFalse);
4802  (void) posix_fallocate(file,offset,extent-offset);
4803  }
4804 #endif
4805  offset=SeekBlob(image,offset,SEEK_SET);
4806  if (count != 1)
4807  return(MagickFalse);
4808  break;
4809  }
4810  case PipeStream:
4811  case ZipStream:
4812  return(MagickFalse);
4813  case BZipStream:
4814  return(MagickFalse);
4815  case FifoStream:
4816  return(MagickFalse);
4817  case BlobStream:
4818  {
4819  if (extent != (MagickSizeType) ((size_t) extent))
4820  return(MagickFalse);
4821  if (blob_info->mapped != MagickFalse)
4822  {
4824  offset;
4825 
4826  ssize_t
4827  count;
4828 
4829  (void) UnmapBlob(blob_info->data,blob_info->length);
4830  RelinquishMagickResource(MapResource,blob_info->length);
4831  if (extent != (MagickSizeType) ((off_t) extent))
4832  return(MagickFalse);
4833  offset=SeekBlob(image,0,SEEK_END);
4834  if (offset < 0)
4835  return(MagickFalse);
4836  if ((MagickSizeType) offset >= extent)
4837  break;
4838  offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4839  count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4840  blob_info->file_info.file);
4841 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4842  if (blob_info->synchronize != MagickFalse)
4843  {
4844  int
4845  file;
4846 
4847  file=fileno(blob_info->file_info.file);
4848  if ((file == -1) || (offset < 0))
4849  return(MagickFalse);
4850  (void) posix_fallocate(file,offset,extent-offset);
4851  }
4852 #endif
4853  offset=SeekBlob(image,offset,SEEK_SET);
4854  if (count != 1)
4855  return(MagickFalse);
4856  (void) AcquireMagickResource(MapResource,extent);
4857  blob_info->data=(unsigned char*) MapBlob(fileno(
4858  blob_info->file_info.file),WriteMode,0,(size_t) extent);
4859  blob_info->extent=(size_t) extent;
4860  blob_info->length=(size_t) extent;
4861  (void) SyncBlob(image);
4862  break;
4863  }
4864  blob_info->extent=(size_t) extent;
4865  blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
4866  blob_info->extent+1,sizeof(*blob_info->data));
4867  (void) SyncBlob(image);
4868  if (blob_info->data == (unsigned char *) NULL)
4869  {
4870  (void) DetachBlob(blob_info);
4871  return(MagickFalse);
4872  }
4873  break;
4874  }
4875  case CustomStream:
4876  break;
4877  }
4878  return(MagickTrue);
4879 }
4880 
4881 /*
4882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4883 % %
4884 % %
4885 % %
4886 + S e t C u s t o m S t r e a m D a t a %
4887 % %
4888 % %
4889 % %
4890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4891 %
4892 % SetCustomStreamData() sets the stream info data member.
4893 %
4894 % The format of the SetCustomStreamData method is:
4895 %
4896 % void SetCustomStreamData(CustomStreamInfo *custom_stream,void *)
4897 %
4898 % A description of each parameter follows:
4899 %
4900 % o custom_stream: the custom stream info.
4901 %
4902 % o data: an object containing information about the custom stream.
4903 %
4904 */
4906  void *data)
4907 {
4908  assert(custom_stream != (CustomStreamInfo *) NULL);
4909  assert(custom_stream->signature == MagickCoreSignature);
4910  custom_stream->data=data;
4911 }
4912 
4913 /*
4914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4915 % %
4916 % %
4917 % %
4918 + S e t C u s t o m S t r e a m R e a d e r %
4919 % %
4920 % %
4921 % %
4922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4923 %
4924 % SetCustomStreamReader() sets the stream info reader member.
4925 %
4926 % The format of the SetCustomStreamReader method is:
4927 %
4928 % void SetCustomStreamReader(CustomStreamInfo *custom_stream,
4929 % CustomStreamHandler reader)
4930 %
4931 % A description of each parameter follows:
4932 %
4933 % o custom_stream: the custom stream info.
4934 %
4935 % o reader: a function to read from the stream.
4936 %
4937 */
4939  CustomStreamHandler reader)
4940 {
4941  assert(custom_stream != (CustomStreamInfo *) NULL);
4942  assert(custom_stream->signature == MagickCoreSignature);
4943  custom_stream->reader=reader;
4944 }
4945 
4946 /*
4947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4948 % %
4949 % %
4950 % %
4951 + S e t C u s t o m S t r e a m S e e k e r %
4952 % %
4953 % %
4954 % %
4955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4956 %
4957 % SetCustomStreamSeeker() sets the stream info seeker member.
4958 %
4959 % The format of the SetCustomStreamReader method is:
4960 %
4961 % void SetCustomStreamSeeker(CustomStreamInfo *custom_stream,
4962 % CustomStreamSeeker seeker)
4963 %
4964 % A description of each parameter follows:
4965 %
4966 % o custom_stream: the custom stream info.
4967 %
4968 % o seeker: a function to seek in the custom stream.
4969 %
4970 */
4972  CustomStreamSeeker seeker)
4973 {
4974  assert(custom_stream != (CustomStreamInfo *) NULL);
4975  assert(custom_stream->signature == MagickCoreSignature);
4976  custom_stream->seeker=seeker;
4977 }
4978 
4979 /*
4980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4981 % %
4982 % %
4983 % %
4984 + S e t C u s t o m S t r e a m T e l l e r %
4985 % %
4986 % %
4987 % %
4988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4989 %
4990 % SetCustomStreamTeller() sets the stream info teller member.
4991 %
4992 % The format of the SetCustomStreamTeller method is:
4993 %
4994 % void SetCustomStreamTeller(CustomStreamInfo *custom_stream,
4995 % CustomStreamTeller *teller)
4996 %
4997 % A description of each parameter follows:
4998 %
4999 % o custom_stream: the custom stream info.
5000 %
5001 % o teller: a function to set the position in the stream.
5002 %
5003 */
5005  CustomStreamTeller teller)
5006 {
5007  assert(custom_stream != (CustomStreamInfo *) NULL);
5008  assert(custom_stream->signature == MagickCoreSignature);
5009  custom_stream->teller=teller;
5010 }
5011 
5012 /*
5013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5014 % %
5015 % %
5016 % %
5017 + S e t C u s t o m S t r e a m W r i t e r %
5018 % %
5019 % %
5020 % %
5021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5022 %
5023 % SetCustomStreamWriter() sets the stream info writer member.
5024 %
5025 % The format of the SetCustomStreamWriter method is:
5026 %
5027 % void SetCustomStreamWriter(CustomStreamInfo *custom_stream,
5028 % CustomStreamHandler *writer)
5029 %
5030 % A description of each parameter follows:
5031 %
5032 % o custom_stream: the custom stream info.
5033 %
5034 % o writer: a function to write to the custom stream.
5035 %
5036 */
5038  CustomStreamHandler writer)
5039 {
5040  assert(custom_stream != (CustomStreamInfo *) NULL);
5041  assert(custom_stream->signature == MagickCoreSignature);
5042  custom_stream->writer=writer;
5043 }
5044 
5045 /*
5046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5047 % %
5048 % %
5049 % %
5050 + S y n c B l o b %
5051 % %
5052 % %
5053 % %
5054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5055 %
5056 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
5057 % attributes if it is an blob.
5058 %
5059 % The format of the SyncBlob method is:
5060 %
5061 % int SyncBlob(Image *image)
5062 %
5063 % A description of each parameter follows:
5064 %
5065 % o image: the image.
5066 %
5067 */
5068 static int SyncBlob(Image *image)
5069 {
5070  BlobInfo
5071  *magick_restrict blob_info;
5072 
5073  int
5074  status;
5075 
5076  assert(image != (Image *) NULL);
5077  assert(image->signature == MagickCoreSignature);
5078  if (image->debug != MagickFalse)
5079  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5080  assert(image->blob != (BlobInfo *) NULL);
5081  assert(image->blob->type != UndefinedStream);
5082  blob_info=image->blob;
5083  status=0;
5084  switch (blob_info->type)
5085  {
5086  case UndefinedStream:
5087  case StandardStream:
5088  break;
5089  case FileStream:
5090  case PipeStream:
5091  {
5092  status=fflush(blob_info->file_info.file);
5093  break;
5094  }
5095  case ZipStream:
5096  {
5097 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5098  status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
5099 #endif
5100  break;
5101  }
5102  case BZipStream:
5103  {
5104 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5105  status=BZ2_bzflush(blob_info->file_info.bzfile);
5106 #endif
5107  break;
5108  }
5109  case FifoStream:
5110  break;
5111  case BlobStream:
5112  break;
5113  case CustomStream:
5114  break;
5115  }
5116  return(status);
5117 }
5118 
5119 /*
5120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5121 % %
5122 % %
5123 % %
5124 + T e l l B l o b %
5125 % %
5126 % %
5127 % %
5128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5129 %
5130 % TellBlob() obtains the current value of the blob or file position.
5131 %
5132 % The format of the TellBlob method is:
5133 %
5134 % MagickOffsetType TellBlob(const Image *image)
5135 %
5136 % A description of each parameter follows:
5137 %
5138 % o image: the image.
5139 %
5140 */
5142 {
5143  BlobInfo
5144  *magick_restrict blob_info;
5145 
5147  offset;
5148 
5149  assert(image != (Image *) NULL);
5150  assert(image->signature == MagickCoreSignature);
5151  if (image->debug != MagickFalse)
5152  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5153  assert(image->blob != (BlobInfo *) NULL);
5154  assert(image->blob->type != UndefinedStream);
5155  blob_info=image->blob;
5156  offset=(-1);
5157  switch (blob_info->type)
5158  {
5159  case UndefinedStream:
5160  case StandardStream:
5161  break;
5162  case FileStream:
5163  {
5164  offset=ftell(blob_info->file_info.file);
5165  break;
5166  }
5167  case PipeStream:
5168  break;
5169  case ZipStream:
5170  {
5171 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5172  offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
5173 #endif
5174  break;
5175  }
5176  case BZipStream:
5177  break;
5178  case FifoStream:
5179  break;
5180  case BlobStream:
5181  {
5182  offset=blob_info->offset;
5183  break;
5184  }
5185  case CustomStream:
5186  {
5187  if (blob_info->custom_stream->teller != (CustomStreamTeller) NULL)
5188  offset=blob_info->custom_stream->teller(blob_info->custom_stream->data);
5189  break;
5190  }
5191  }
5192  return(offset);
5193 }
5194 
5195 /*
5196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5197 % %
5198 % %
5199 % %
5200 + U n m a p B l o b %
5201 % %
5202 % %
5203 % %
5204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5205 %
5206 % UnmapBlob() deallocates the binary large object previously allocated with
5207 % the MapBlob method.
5208 %
5209 % The format of the UnmapBlob method is:
5210 %
5211 % MagickBooleanType UnmapBlob(void *map,const size_t length)
5212 %
5213 % A description of each parameter follows:
5214 %
5215 % o map: the address of the binary large object.
5216 %
5217 % o length: the length of the binary large object.
5218 %
5219 */
5220 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
5221 {
5222 #if defined(MAGICKCORE_HAVE_MMAP)
5223  int
5224  status;
5225 
5226  status=munmap(map,length);
5227  return(status == -1 ? MagickFalse : MagickTrue);
5228 #else
5229  (void) map;
5230  (void) length;
5231  return(MagickFalse);
5232 #endif
5233 }
5234 
5235 /*
5236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5237 % %
5238 % %
5239 % %
5240 + W r i t e B l o b %
5241 % %
5242 % %
5243 % %
5244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5245 %
5246 % WriteBlob() writes data to a blob or image file. It returns the number of
5247 % bytes written.
5248 %
5249 % The format of the WriteBlob method is:
5250 %
5251 % ssize_t WriteBlob(Image *image,const size_t length,const void *data)
5252 %
5253 % A description of each parameter follows:
5254 %
5255 % o image: the image.
5256 %
5257 % o length: Specifies an integer representing the number of bytes to
5258 % write to the file.
5259 %
5260 % o data: The address of the data to write to the blob or file.
5261 %
5262 */
5263 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
5264  const void *data)
5265 {
5266  BlobInfo
5267  *magick_restrict blob_info;
5268 
5269  int
5270  c;
5271 
5272  register const unsigned char
5273  *p;
5274 
5275  ssize_t
5276  count;
5277 
5278  assert(image != (Image *) NULL);
5279  assert(image->signature == MagickCoreSignature);
5280  assert(image->blob != (BlobInfo *) NULL);
5281  assert(image->blob->type != UndefinedStream);
5282  if (length == 0)
5283  return(0);
5284  assert(data != (const void *) NULL);
5285  blob_info=image->blob;
5286  count=0;
5287  p=(const unsigned char *) data;
5288  switch (blob_info->type)
5289  {
5290  case UndefinedStream:
5291  break;
5292  case StandardStream:
5293  case FileStream:
5294  case PipeStream:
5295  {
5296  switch (length)
5297  {
5298  default:
5299  {
5300  count=(ssize_t) fwrite((const char *) data,1,length,
5301  blob_info->file_info.file);
5302  break;
5303  }
5304  case 4:
5305  {
5306  c=putc((int) *p++,blob_info->file_info.file);
5307  if (c == EOF)
5308  break;
5309  count++;
5310  }
5311  case 3:
5312  {
5313  c=putc((int) *p++,blob_info->file_info.file);
5314  if (c == EOF)
5315  break;
5316  count++;
5317  }
5318  case 2:
5319  {
5320  c=putc((int) *p++,blob_info->file_info.file);
5321  if (c == EOF)
5322  break;
5323  count++;
5324  }
5325  case 1:
5326  {
5327  c=putc((int) *p++,blob_info->file_info.file);
5328  if (c == EOF)
5329  break;
5330  count++;
5331  }
5332  case 0:
5333  break;
5334  }
5335  break;
5336  }
5337  case ZipStream:
5338  {
5339 #if defined(MAGICKCORE_ZLIB_DELEGATE)
5340  switch (length)
5341  {
5342  default:
5343  {
5344  count=(ssize_t) gzwrite(blob_info->file_info.gzfile,(void *) data,
5345  (unsigned int) length);
5346  break;
5347  }
5348  case 4:
5349  {
5350  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5351  if (c == EOF)
5352  break;
5353  count++;
5354  }
5355  case 3:
5356  {
5357  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5358  if (c == EOF)
5359  break;
5360  count++;
5361  }
5362  case 2:
5363  {
5364  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5365  if (c == EOF)
5366  break;
5367  count++;
5368  }
5369  case 1:
5370  {
5371  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5372  if (c == EOF)
5373  break;
5374  count++;
5375  }
5376  case 0:
5377  break;
5378  }
5379 #endif
5380  break;
5381  }
5382  case BZipStream:
5383  {
5384 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5385  count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,(void *) data,
5386  (int) length);
5387 #endif
5388  break;
5389  }
5390  case FifoStream:
5391  {
5392  count=(ssize_t) blob_info->stream(image,data,length);
5393  break;
5394  }
5395  case BlobStream:
5396  {
5397  register unsigned char
5398  *q;
5399 
5400  if ((blob_info->offset+(MagickOffsetType) length) >=
5401  (MagickOffsetType) blob_info->extent)
5402  {
5403  if (blob_info->mapped != MagickFalse)
5404  return(0);
5405  blob_info->extent+=length+blob_info->quantum;
5406  blob_info->quantum<<=1;
5407  blob_info->data=(unsigned char *) ResizeQuantumMemory(
5408  blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5409  (void) SyncBlob(image);
5410  if (blob_info->data == (unsigned char *) NULL)
5411  {
5412  (void) DetachBlob(blob_info);
5413  return(0);
5414  }
5415  }
5416  q=blob_info->data+blob_info->offset;
5417  (void) memcpy(q,p,length);
5418  blob_info->offset+=length;
5419  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5420  blob_info->length=(size_t) blob_info->offset;
5421  count=(ssize_t) length;
5422  break;
5423  }
5424  case CustomStream:
5425  {
5426  if (blob_info->custom_stream->writer != (CustomStreamHandler) NULL)
5427  count=blob_info->custom_stream->writer((unsigned char *) data,
5428  length,blob_info->custom_stream->data);
5429  break;
5430  }
5431  }
5432  return(count);
5433 }
5434 
5435 /*
5436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5437 % %
5438 % %
5439 % %
5440 + W r i t e B l o b B y t e %
5441 % %
5442 % %
5443 % %
5444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5445 %
5446 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
5447 % written (either 0 or 1);
5448 %
5449 % The format of the WriteBlobByte method is:
5450 %
5451 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
5452 %
5453 % A description of each parameter follows.
5454 %
5455 % o image: the image.
5456 %
5457 % o value: Specifies the value to write.
5458 %
5459 */
5460 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5461 {
5462  BlobInfo
5463  *magick_restrict blob_info;
5464 
5465  ssize_t
5466  count;
5467 
5468  assert(image != (Image *) NULL);
5469  assert(image->signature == MagickCoreSignature);
5470  assert(image->blob != (BlobInfo *) NULL);
5471  assert(image->blob->type != UndefinedStream);
5472  blob_info=image->blob;
5473  count=0;
5474  switch (blob_info->type)
5475  {
5476  case StandardStream:
5477  case FileStream:
5478  case PipeStream:
5479  {
5480  int
5481  c;
5482 
5483  c=putc((int) value,blob_info->file_info.file);
5484  if (c == EOF)
5485  break;
5486  count++;
5487  break;
5488  }
5489  default:
5490  {
5491  count=WriteBlobStream(image,1,&value);
5492  break;
5493  }
5494  }
5495  return(count);
5496 }
5497 
5498 /*
5499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5500 % %
5501 % %
5502 % %
5503 + W r i t e B l o b F l o a t %
5504 % %
5505 % %
5506 % %
5507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5508 %
5509 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5510 % specified by the endian member of the image structure.
5511 %
5512 % The format of the WriteBlobFloat method is:
5513 %
5514 % ssize_t WriteBlobFloat(Image *image,const float value)
5515 %
5516 % A description of each parameter follows.
5517 %
5518 % o image: the image.
5519 %
5520 % o value: Specifies the value to write.
5521 %
5522 */
5523 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5524 {
5525  union
5526  {
5527  unsigned int
5528  unsigned_value;
5529 
5530  float
5531  float_value;
5532  } quantum;
5533 
5534  quantum.unsigned_value=0U;
5535  quantum.float_value=value;
5536  return(WriteBlobLong(image,quantum.unsigned_value));
5537 }
5538 
5539 /*
5540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5541 % %
5542 % %
5543 % %
5544 + W r i t e B l o b L o n g %
5545 % %
5546 % %
5547 % %
5548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5549 %
5550 % WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5551 % byte-order specified by the endian member of the image structure.
5552 %
5553 % The format of the WriteBlobLong method is:
5554 %
5555 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
5556 %
5557 % A description of each parameter follows.
5558 %
5559 % o image: the image.
5560 %
5561 % o value: Specifies the value to write.
5562 %
5563 */
5564 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5565 {
5566  unsigned char
5567  buffer[4];
5568 
5569  assert(image != (Image *) NULL);
5570  assert(image->signature == MagickCoreSignature);
5571  if (image->endian == LSBEndian)
5572  {
5573  buffer[0]=(unsigned char) value;
5574  buffer[1]=(unsigned char) (value >> 8);
5575  buffer[2]=(unsigned char) (value >> 16);
5576  buffer[3]=(unsigned char) (value >> 24);
5577  return(WriteBlobStream(image,4,buffer));
5578  }
5579  buffer[0]=(unsigned char) (value >> 24);
5580  buffer[1]=(unsigned char) (value >> 16);
5581  buffer[2]=(unsigned char) (value >> 8);
5582  buffer[3]=(unsigned char) value;
5583  return(WriteBlobStream(image,4,buffer));
5584 }
5585 
5586 /*
5587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5588 % %
5589 % %
5590 % %
5591 + W r i t e B l o b L o n g L o n g %
5592 % %
5593 % %
5594 % %
5595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5596 %
5597 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in the
5598 % byte-order specified by the endian member of the image structure.
5599 %
5600 % The format of the WriteBlobLongLong method is:
5601 %
5602 % ssize_t WriteBlobLongLong(Image *image,const MagickSizeType value)
5603 %
5604 % A description of each parameter follows.
5605 %
5606 % o value: Specifies the value to write.
5607 %
5608 % o image: the image.
5609 %
5610 */
5612 {
5613  unsigned char
5614  buffer[8];
5615 
5616  assert(image != (Image *) NULL);
5617  assert(image->signature == MagickCoreSignature);
5618  if (image->endian == LSBEndian)
5619  {
5620  buffer[0]=(unsigned char) value;
5621  buffer[1]=(unsigned char) (value >> 8);
5622  buffer[2]=(unsigned char) (value >> 16);
5623  buffer[3]=(unsigned char) (value >> 24);
5624  buffer[4]=(unsigned char) (value >> 32);
5625  buffer[5]=(unsigned char) (value >> 40);
5626  buffer[6]=(unsigned char) (value >> 48);
5627  buffer[7]=(unsigned char) (value >> 56);
5628  return(WriteBlobStream(image,8,buffer));
5629  }
5630  buffer[0]=(unsigned char) (value >> 56);
5631  buffer[1]=(unsigned char) (value >> 48);
5632  buffer[2]=(unsigned char) (value >> 40);
5633  buffer[3]=(unsigned char) (value >> 32);
5634  buffer[4]=(unsigned char) (value >> 24);
5635  buffer[5]=(unsigned char) (value >> 16);
5636  buffer[6]=(unsigned char) (value >> 8);
5637  buffer[7]=(unsigned char) value;
5638  return(WriteBlobStream(image,8,buffer));
5639 }
5640 
5641 /*
5642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5643 % %
5644 % %
5645 % %
5646 + W r i t e B l o b S h o r t %
5647 % %
5648 % %
5649 % %
5650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5651 %
5652 % WriteBlobShort() writes a short value as a 16-bit quantity in the
5653 % byte-order specified by the endian member of the image structure.
5654 %
5655 % The format of the WriteBlobShort method is:
5656 %
5657 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
5658 %
5659 % A description of each parameter follows.
5660 %
5661 % o image: the image.
5662 %
5663 % o value: Specifies the value to write.
5664 %
5665 */
5666 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5667 {
5668  unsigned char
5669  buffer[2];
5670 
5671  assert(image != (Image *) NULL);
5672  assert(image->signature == MagickCoreSignature);
5673  if (image->endian == LSBEndian)
5674  {
5675  buffer[0]=(unsigned char) value;
5676  buffer[1]=(unsigned char) (value >> 8);
5677  return(WriteBlobStream(image,2,buffer));
5678  }
5679  buffer[0]=(unsigned char) (value >> 8);
5680  buffer[1]=(unsigned char) value;
5681  return(WriteBlobStream(image,2,buffer));
5682 }
5683 
5684 /*
5685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5686 % %
5687 % %
5688 % %
5689 + W r i t e B l o b S i g n e d L o n g %
5690 % %
5691 % %
5692 % %
5693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5694 %
5695 % WriteBlobSignedLong() writes a signed value as a 32-bit quantity in the
5696 % byte-order specified by the endian member of the image structure.
5697 %
5698 % The format of the WriteBlobSignedLong method is:
5699 %
5700 % ssize_t WriteBlobSignedLong(Image *image,const signed int value)
5701 %
5702 % A description of each parameter follows.
5703 %
5704 % o image: the image.
5705 %
5706 % o value: Specifies the value to write.
5707 %
5708 */
5709 MagickExport ssize_t WriteBlobSignedLong(Image *image,const signed int value)
5710 {
5711  union
5712  {
5713  unsigned int
5714  unsigned_value;
5715 
5716  signed int
5717  signed_value;
5718  } quantum;
5719 
5720  unsigned char
5721  buffer[4];
5722 
5723  assert(image != (Image *) NULL);
5724  assert(image->signature == MagickCoreSignature);
5725  quantum.signed_value=value;
5726  if (image->endian == LSBEndian)
5727  {
5728  buffer[0]=(unsigned char) quantum.unsigned_value;
5729  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5730  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5731  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5732  return(WriteBlobStream(image,4,buffer));
5733  }
5734  buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5735  buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5736  buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5737  buffer[3]=(unsigned char) quantum.unsigned_value;
5738  return(WriteBlobStream(image,4,buffer));
5739 }
5740 
5741 /*
5742 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5743 % %
5744 % %
5745 % %
5746 + W r i t e B l o b L S B L o n g %
5747 % %
5748 % %
5749 % %
5750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5751 %
5752 % WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
5753 % least-significant byte first order.
5754 %
5755 % The format of the WriteBlobLSBLong method is:
5756 %
5757 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5758 %
5759 % A description of each parameter follows.
5760 %
5761 % o image: the image.
5762 %
5763 % o value: Specifies the value to write.
5764 %
5765 */
5766 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5767 {
5768  unsigned char
5769  buffer[4];
5770 
5771  assert(image != (Image *) NULL);
5772  assert(image->signature == MagickCoreSignature);
5773  buffer[0]=(unsigned char) value;
5774  buffer[1]=(unsigned char) (value >> 8);
5775  buffer[2]=(unsigned char) (value >> 16);
5776  buffer[3]=(unsigned char) (value >> 24);
5777  return(WriteBlobStream(image,4,buffer));
5778 }
5779 
5780 /*
5781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5782 % %
5783 % %
5784 % %
5785 + W r i t e B l o b L S B S h o r t %
5786 % %
5787 % %
5788 % %
5789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5790 %
5791 % WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
5792 % least-significant byte first order.
5793 %
5794 % The format of the WriteBlobLSBShort method is:
5795 %
5796 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5797 %
5798 % A description of each parameter follows.
5799 %
5800 % o image: the image.
5801 %
5802 % o value: Specifies the value to write.
5803 %
5804 */
5805 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5806 {
5807  unsigned char
5808  buffer[2];
5809 
5810  assert(image != (Image *) NULL);
5811  assert(image->signature == MagickCoreSignature);
5812  buffer[0]=(unsigned char) value;
5813  buffer[1]=(unsigned char) (value >> 8);
5814  return(WriteBlobStream(image,2,buffer));
5815 }
5816 
5817 /*
5818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5819 % %
5820 % %
5821 % %
5822 + W r i t e B l o b L S B S i g n e d L o n g %
5823 % %
5824 % %
5825 % %
5826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5827 %
5828 % WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
5829 % least-significant byte first order.
5830 %
5831 % The format of the WriteBlobLSBSignedLong method is:
5832 %
5833 % ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5834 %
5835 % A description of each parameter follows.
5836 %
5837 % o image: the image.
5838 %
5839 % o value: Specifies the value to write.
5840 %
5841 */
5842 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5843 {
5844  union
5845  {
5846  unsigned int
5847  unsigned_value;
5848 
5849  signed int
5850  signed_value;
5851  } quantum;
5852 
5853  unsigned char
5854  buffer[4];
5855 
5856  assert(image != (Image *) NULL);
5857  assert(image->signature == MagickCoreSignature);
5858  quantum.signed_value=value;
5859  buffer[0]=(unsigned char) quantum.unsigned_value;
5860  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5861  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5862  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5863  return(WriteBlobStream(image,4,buffer));
5864 }
5865 
5866 /*
5867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5868 % %
5869 % %
5870 % %
5871 + W r i t e B l o b L S B S i g n e d S h o r t %
5872 % %
5873 % %
5874 % %
5875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5876 %
5877 % WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
5878 % in least-significant byte first order.
5879 %
5880 % The format of the WriteBlobLSBSignedShort method is:
5881 %
5882 % ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
5883 %
5884 % A description of each parameter follows.
5885 %
5886 % o image: the image.
5887 %
5888 % o value: Specifies the value to write.
5889 %
5890 */
5892  const signed short value)
5893 {
5894  union
5895  {
5896  unsigned short
5897  unsigned_value;
5898 
5899  signed short
5900  signed_value;
5901  } quantum;
5902 
5903  unsigned char
5904  buffer[2];
5905 
5906  assert(image != (Image *) NULL);
5907  assert(image->signature == MagickCoreSignature);
5908  quantum.signed_value=value;
5909  buffer[0]=(unsigned char) quantum.unsigned_value;
5910  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5911  return(WriteBlobStream(image,2,buffer));
5912 }
5913 
5914 /*
5915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5916 % %
5917 % %
5918 % %
5919 + W r i t e B l o b M S B L o n g %
5920 % %
5921 % %
5922 % %
5923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5924 %
5925 % WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
5926 % most-significant byte first order.
5927 %
5928 % The format of the WriteBlobMSBLong method is:
5929 %
5930 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5931 %
5932 % A description of each parameter follows.
5933 %
5934 % o value: Specifies the value to write.
5935 %
5936 % o image: the image.
5937 %
5938 */
5939 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5940 {
5941  unsigned char
5942  buffer[4];
5943 
5944  assert(image != (Image *) NULL);
5945  assert(image->signature == MagickCoreSignature);
5946  buffer[0]=(unsigned char) (value >> 24);
5947  buffer[1]=(unsigned char) (value >> 16);
5948  buffer[2]=(unsigned char) (value >> 8);
5949  buffer[3]=(unsigned char) value;
5950  return(WriteBlobStream(image,4,buffer));
5951 }
5952 
5953 /*
5954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5955 % %
5956 % %
5957 % %
5958 + W r i t e B l o b M S B S i g n e d S h o r t %
5959 % %
5960 % %
5961 % %
5962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5963 %
5964 % WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5965 % in most-significant byte first order.
5966 %
5967 % The format of the WriteBlobMSBSignedShort method is:
5968 %
5969 % ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5970 %
5971 % A description of each parameter follows.
5972 %
5973 % o image: the image.
5974 %
5975 % o value: Specifies the value to write.
5976 %
5977 */
5979  const signed short value)
5980 {
5981  union
5982  {
5983  unsigned short
5984  unsigned_value;
5985 
5986  signed short
5987  signed_value;
5988  } quantum;
5989 
5990  unsigned char
5991  buffer[2];
5992 
5993  assert(image != (Image *) NULL);
5994  assert(image->signature == MagickCoreSignature);
5995  quantum.signed_value=value;
5996  buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5997  buffer[1]=(unsigned char) quantum.unsigned_value;
5998  return(WriteBlobStream(image,2,buffer));
5999 }
6000 
6001 /*
6002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6003 % %
6004 % %
6005 % %
6006 + W r i t e B l o b M S B S h o r t %
6007 % %
6008 % %
6009 % %
6010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6011 %
6012 % WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
6013 % most-significant byte first order.
6014 %
6015 % The format of the WriteBlobMSBShort method is:
6016 %
6017 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6018 %
6019 % A description of each parameter follows.
6020 %
6021 % o value: Specifies the value to write.
6022 %
6023 % o file: Specifies the file to write the data to.
6024 %
6025 */
6026 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
6027 {
6028  unsigned char
6029  buffer[2];
6030 
6031  assert(image != (Image *) NULL);
6032  assert(image->signature == MagickCoreSignature);
6033  buffer[0]=(unsigned char) (value >> 8);
6034  buffer[1]=(unsigned char) value;
6035  return(WriteBlobStream(image,2,buffer));
6036 }
6037 
6038 /*
6039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6040 % %
6041 % %
6042 % %
6043 + W r i t e B l o b S t r i n g %
6044 % %
6045 % %
6046 % %
6047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6048 %
6049 % WriteBlobString() write a string to a blob. It returns the number of
6050 % characters written.
6051 %
6052 % The format of the WriteBlobString method is:
6053 %
6054 % ssize_t WriteBlobString(Image *image,const char *string)
6055 %
6056 % A description of each parameter follows.
6057 %
6058 % o image: the image.
6059 %
6060 % o string: Specifies the string to write.
6061 %
6062 */
6063 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
6064 {
6065  assert(image != (Image *) NULL);
6066  assert(image->signature == MagickCoreSignature);
6067  assert(string != (const char *) NULL);
6068  return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
6069 }
#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:5037
CustomStreamInfo * custom_stream
Definition: blob.c:150
MagickExport ssize_t WriteBlobLong(Image *image, const unsigned int value)
Definition: blob.c:5564
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:5460
char magick[MagickPathExtent]
Definition: image.h:471
MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain, const PolicyRights rights, const char *pattern)
Definition: policy.c:589