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