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