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