MagickCore  6.9.12-67
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-2021 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=RelinquishMagickMemory(blob);
1776  else
1777  blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
1778  }
1779  }
1780  }
1781  else
1782  {
1783  char
1784  unique[MagickPathExtent];
1785 
1786  int
1787  file;
1788 
1789  /*
1790  Write file to disk in blob image format.
1791  */
1792  file=AcquireUniqueFileResource(unique);
1793  if (file == -1)
1794  {
1795  ThrowFileException(exception,BlobError,"UnableToWriteBlob",
1796  image_info->filename);
1797  }
1798  else
1799  {
1800  blob_info->file=fdopen(file,"wb");
1801  if (blob_info->file != (FILE *) NULL)
1802  {
1803  (void) FormatLocaleString(image->filename,MagickPathExtent,
1804  "%s:%s",image->magick,unique);
1805  status=WriteImage(blob_info,image);
1806  (void) CloseBlob(image);
1807  (void) fclose(blob_info->file);
1808  if (status == MagickFalse)
1809  InheritException(exception,&image->exception);
1810  else
1811  blob=FileToBlob(unique,~0UL,length,exception);
1812  }
1813  (void) RelinquishUniqueFileResource(unique);
1814  }
1815  }
1816  blob_info=DestroyImageInfo(blob_info);
1817  return(blob);
1818 }
1819 
1820 /*
1821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1822 % %
1823 % %
1824 % %
1825 % I m a g e T o F i l e %
1826 % %
1827 % %
1828 % %
1829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1830 %
1831 % ImageToFile() writes an image to a file. It returns MagickFalse if an error
1832 % occurs otherwise MagickTrue.
1833 %
1834 % The format of the ImageToFile method is:
1835 %
1836 % MagickBooleanType ImageToFile(Image *image,char *filename,
1837 % ExceptionInfo *exception)
1838 %
1839 % A description of each parameter follows:
1840 %
1841 % o image: the image.
1842 %
1843 % o filename: Write the image to this file.
1844 %
1845 % o exception: return any errors or warnings in this structure.
1846 %
1847 */
1848 MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
1849  ExceptionInfo *exception)
1850 {
1851  int
1852  file;
1853 
1854  const unsigned char
1855  *p;
1856 
1857  size_t
1858  i;
1859 
1860  size_t
1861  length,
1862  quantum;
1863 
1864  ssize_t
1865  count;
1866 
1867  struct stat
1868  file_stats;
1869 
1870  unsigned char
1871  *buffer;
1872 
1873  assert(image != (Image *) NULL);
1874  assert(image->signature == MagickCoreSignature);
1875  assert(image->blob != (BlobInfo *) NULL);
1876  assert(image->blob->type != UndefinedStream);
1877  assert(filename != (const char *) NULL);
1878  if (IsEventLogging() != MagickFalse)
1879  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1880  if (*filename == '\0')
1881  file=AcquireUniqueFileResource(filename);
1882  else
1883  if (LocaleCompare(filename,"-") == 0)
1884  file=fileno(stdout);
1885  else
1886  file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,S_MODE);
1887  if (file == -1)
1888  {
1889  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1890  return(MagickFalse);
1891  }
1892  quantum=(size_t) MagickMaxBufferExtent;
1893  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1894  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
1895  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
1896  if (buffer == (unsigned char *) NULL)
1897  {
1898  file=close(file)-1;
1899  (void) ThrowMagickException(exception,GetMagickModule(),
1900  ResourceLimitError,"MemoryAllocationError","`%s'",filename);
1901  return(MagickFalse);
1902  }
1903  length=0;
1904  p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1905  for (i=0; count > 0; )
1906  {
1907  length=(size_t) count;
1908  for (i=0; i < length; i+=count)
1909  {
1910  count=write(file,p+i,(size_t) (length-i));
1911  if (count <= 0)
1912  {
1913  count=0;
1914  if (errno != EINTR)
1915  break;
1916  }
1917  }
1918  if (i < length)
1919  break;
1920  p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count);
1921  }
1922  if (LocaleCompare(filename,"-") != 0)
1923  file=close(file);
1924  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1925  if ((file == -1) || (i < length))
1926  {
1927  if (file != -1)
1928  file=close(file);
1929  ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
1930  return(MagickFalse);
1931  }
1932  return(MagickTrue);
1933 }
1934 
1935 /*
1936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1937 % %
1938 % %
1939 % %
1940 % I m a g e s T o B l o b %
1941 % %
1942 % %
1943 % %
1944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1945 %
1946 % ImagesToBlob() implements direct to memory image formats. It returns the
1947 % image sequence as a blob and its length. The magick member of the ImageInfo
1948 % structure determines the format of the returned blob (GIF, JPEG, PNG, etc.)
1949 %
1950 % Note, some image formats do not permit multiple images to the same image
1951 % stream (e.g. JPEG). in this instance, just the first image of the
1952 % sequence is returned as a blob.
1953 %
1954 % The format of the ImagesToBlob method is:
1955 %
1956 % unsigned char *ImagesToBlob(const ImageInfo *image_info,Image *images,
1957 % size_t *length,ExceptionInfo *exception)
1958 %
1959 % A description of each parameter follows:
1960 %
1961 % o image_info: the image info.
1962 %
1963 % o images: the image list.
1964 %
1965 % o length: return the actual length of the blob.
1966 %
1967 % o exception: return any errors or warnings in this structure.
1968 %
1969 */
1970 MagickExport unsigned char *ImagesToBlob(const ImageInfo *image_info,
1971  Image *images,size_t *length,ExceptionInfo *exception)
1972 {
1973  const MagickInfo
1974  *magick_info;
1975 
1976  ImageInfo
1977  *blob_info;
1978 
1979  MagickBooleanType
1980  status;
1981 
1982  unsigned char
1983  *blob;
1984 
1985  assert(image_info != (const ImageInfo *) NULL);
1986  assert(image_info->signature == MagickCoreSignature);
1987  assert(images != (Image *) NULL);
1988  assert(images->signature == MagickCoreSignature);
1989  assert(exception != (ExceptionInfo *) NULL);
1990  if (IsEventLogging() != MagickFalse)
1991  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1992  image_info->filename);
1993  *length=0;
1994  blob=(unsigned char *) NULL;
1995  blob_info=CloneImageInfo(image_info);
1996  (void) SetImageInfo(blob_info,(unsigned int) GetImageListLength(images),
1997  exception);
1998  if (*blob_info->magick != '\0')
1999  (void) CopyMagickString(images->magick,blob_info->magick,MagickPathExtent);
2000  magick_info=GetMagickInfo(images->magick,exception);
2001  if (magick_info == (const MagickInfo *) NULL)
2002  {
2003  (void) ThrowMagickException(exception,GetMagickModule(),
2004  MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
2005  images->magick);
2006  blob_info=DestroyImageInfo(blob_info);
2007  return(blob);
2008  }
2009  if (GetMagickAdjoin(magick_info) == MagickFalse)
2010  {
2011  blob_info=DestroyImageInfo(blob_info);
2012  return(ImageToBlob(image_info,images,length,exception));
2013  }
2014  (void) CopyMagickString(blob_info->magick,images->magick,MagickPathExtent);
2015  if (GetMagickBlobSupport(magick_info) != MagickFalse)
2016  {
2017  /*
2018  Native blob support for this images format.
2019  */
2020  blob_info->length=0;
2021  blob_info->blob=(void *) AcquireQuantumMemory(MagickMaxBlobExtent,
2022  sizeof(unsigned char));
2023  if (blob_info->blob == (void *) NULL)
2024  (void) ThrowMagickException(exception,GetMagickModule(),
2025  ResourceLimitError,"MemoryAllocationFailed","`%s'",images->filename);
2026  else
2027  {
2028  (void) CloseBlob(images);
2029  images->blob->exempt=MagickTrue;
2030  *images->filename='\0';
2031  status=WriteImages(blob_info,images,images->filename,exception);
2032  *length=images->blob->length;
2033  blob=DetachBlob(images->blob);
2034  if (blob != (void *) NULL)
2035  {
2036  if (status == MagickFalse)
2037  blob=RelinquishMagickMemory(blob);
2038  else
2039  blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char));
2040  }
2041  }
2042  }
2043  else
2044  {
2045  char
2046  filename[MagickPathExtent],
2047  unique[MagickPathExtent];
2048 
2049  int
2050  file;
2051 
2052  /*
2053  Write file to disk in blob images format.
2054  */
2055  file=AcquireUniqueFileResource(unique);
2056  if (file == -1)
2057  {
2058  ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",
2059  image_info->filename);
2060  }
2061  else
2062  {
2063  blob_info->file=fdopen(file,"wb");
2064  if (blob_info->file != (FILE *) NULL)
2065  {
2066  (void) FormatLocaleString(filename,MagickPathExtent,"%s:%s",
2067  images->magick,unique);
2068  status=WriteImages(blob_info,images,filename,exception);
2069  (void) CloseBlob(images);
2070  (void) fclose(blob_info->file);
2071  if (status == MagickFalse)
2072  InheritException(exception,&images->exception);
2073  else
2074  blob=FileToBlob(unique,~0UL,length,exception);
2075  }
2076  (void) RelinquishUniqueFileResource(unique);
2077  }
2078  }
2079  blob_info=DestroyImageInfo(blob_info);
2080  return(blob);
2081 }
2082 /*
2083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2084 % %
2085 % %
2086 % %
2087 % I n j e c t I m a g e B l o b %
2088 % %
2089 % %
2090 % %
2091 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2092 %
2093 % InjectImageBlob() injects the image with a copy of itself in the specified
2094 % format (e.g. inject JPEG into a PDF image).
2095 %
2096 % The format of the InjectImageBlob method is:
2097 %
2098 % MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2099 % Image *image,Image *inject_image,const char *format,
2100 % ExceptionInfo *exception)
2101 %
2102 % A description of each parameter follows:
2103 %
2104 % o image_info: the image info..
2105 %
2106 % o image: the image.
2107 %
2108 % o inject_image: inject into the image stream.
2109 %
2110 % o format: the image format.
2111 %
2112 % o exception: return any errors or warnings in this structure.
2113 %
2114 */
2115 MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
2116  Image *image,Image *inject_image,const char *format,ExceptionInfo *exception)
2117 {
2118  char
2119  filename[MagickPathExtent];
2120 
2121  FILE
2122  *unique_file;
2123 
2124  Image
2125  *byte_image;
2126 
2127  ImageInfo
2128  *write_info;
2129 
2130  int
2131  file;
2132 
2133  MagickBooleanType
2134  status;
2135 
2136  size_t
2137  quantum;
2138 
2139  struct stat
2140  file_stats;
2141 
2142  unsigned char
2143  *buffer;
2144 
2145  /*
2146  Write inject image to a temporary file.
2147  */
2148  assert(image_info != (ImageInfo *) NULL);
2149  assert(image_info->signature == MagickCoreSignature);
2150  assert(image != (Image *) NULL);
2151  assert(image->signature == MagickCoreSignature);
2152  assert(inject_image != (Image *) NULL);
2153  assert(inject_image->signature == MagickCoreSignature);
2154  assert(exception != (ExceptionInfo *) NULL);
2155  if (IsEventLogging() != MagickFalse)
2156  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2157  unique_file=(FILE *) NULL;
2158  file=AcquireUniqueFileResource(filename);
2159  if (file != -1)
2160  unique_file=fdopen(file,"wb");
2161  if ((file == -1) || (unique_file == (FILE *) NULL))
2162  {
2163  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2164  ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
2165  image->filename);
2166  return(MagickFalse);
2167  }
2168  byte_image=CloneImage(inject_image,0,0,MagickFalse,exception);
2169  if (byte_image == (Image *) NULL)
2170  {
2171  (void) fclose(unique_file);
2172  (void) RelinquishUniqueFileResource(filename);
2173  return(MagickFalse);
2174  }
2175  (void) FormatLocaleString(byte_image->filename,MagickPathExtent,"%s:%s",
2176  format,filename);
2177  DestroyBlob(byte_image);
2178  byte_image->blob=CloneBlobInfo((BlobInfo *) NULL);
2179  write_info=CloneImageInfo(image_info);
2180  SetImageInfoFile(write_info,unique_file);
2181  status=WriteImage(write_info,byte_image);
2182  write_info=DestroyImageInfo(write_info);
2183  byte_image=DestroyImage(byte_image);
2184  (void) fclose(unique_file);
2185  if (status == MagickFalse)
2186  {
2187  (void) RelinquishUniqueFileResource(filename);
2188  return(MagickFalse);
2189  }
2190  /*
2191  Inject into image stream.
2192  */
2193  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
2194  if (file == -1)
2195  {
2196  (void) RelinquishUniqueFileResource(filename);
2197  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2198  image_info->filename);
2199  return(MagickFalse);
2200  }
2201  quantum=(size_t) MagickMaxBufferExtent;
2202  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
2203  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
2204  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
2205  if (buffer == (unsigned char *) NULL)
2206  {
2207  (void) RelinquishUniqueFileResource(filename);
2208  file=close(file);
2209  ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2210  image->filename);
2211  }
2212  for ( ; ; )
2213  {
2214  ssize_t count = read(file,buffer,quantum);
2215  if (count <= 0)
2216  {
2217  count=0;
2218  if (errno != EINTR)
2219  break;
2220  }
2221  status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue :
2222  MagickFalse;
2223  }
2224  file=close(file);
2225  if (file == -1)
2226  ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename);
2227  (void) RelinquishUniqueFileResource(filename);
2228  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
2229  return(status);
2230 }
2231 
2232 /*
2233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2234 % %
2235 % %
2236 % %
2237 % I s B l o b E x e m p t %
2238 % %
2239 % %
2240 % %
2241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2242 %
2243 % IsBlobExempt() returns true if the blob is exempt.
2244 %
2245 % The format of the IsBlobExempt method is:
2246 %
2247 % MagickBooleanType IsBlobExempt(const Image *image)
2248 %
2249 % A description of each parameter follows:
2250 %
2251 % o image: the image.
2252 %
2253 */
2254 MagickExport MagickBooleanType IsBlobExempt(const Image *image)
2255 {
2256  assert(image != (const Image *) NULL);
2257  assert(image->signature == MagickCoreSignature);
2258  if (IsEventLogging() != MagickFalse)
2259  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2260  return(image->blob->exempt);
2261 }
2262 
2263 /*
2264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2265 % %
2266 % %
2267 % %
2268 + I s B l o b S e e k a b l e %
2269 % %
2270 % %
2271 % %
2272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2273 %
2274 % IsBlobSeekable() returns true if the blob is seekable.
2275 %
2276 % The format of the IsBlobSeekable method is:
2277 %
2278 % MagickBooleanType IsBlobSeekable(const Image *image)
2279 %
2280 % A description of each parameter follows:
2281 %
2282 % o image: the image.
2283 %
2284 */
2285 MagickExport MagickBooleanType IsBlobSeekable(const Image *image)
2286 {
2287  BlobInfo
2288  *magick_restrict blob_info;
2289 
2290  assert(image != (const Image *) NULL);
2291  assert(image->signature == MagickCoreSignature);
2292  if (IsEventLogging() != MagickFalse)
2293  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2294  blob_info=image->blob;
2295  switch (blob_info->type)
2296  {
2297  case BlobStream:
2298  return(MagickTrue);
2299  case FileStream:
2300  {
2301  int
2302  status;
2303 
2304  if (blob_info->file_info.file == (FILE *) NULL)
2305  return(MagickFalse);
2306  status=fseek(blob_info->file_info.file,0,SEEK_CUR);
2307  return(status == -1 ? MagickFalse : MagickTrue);
2308  }
2309  case ZipStream:
2310  {
2311 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2312  MagickOffsetType
2313  offset;
2314 
2315  if (blob_info->file_info.gzfile == (gzFile) NULL)
2316  return(MagickFalse);
2317  offset=gzseek(blob_info->file_info.gzfile,0,SEEK_CUR);
2318  return(offset < 0 ? MagickFalse : MagickTrue);
2319 #else
2320  break;
2321 #endif
2322  }
2323  case UndefinedStream:
2324  case BZipStream:
2325  case FifoStream:
2326  case PipeStream:
2327  case StandardStream:
2328  break;
2329  default:
2330  break;
2331  }
2332  return(MagickFalse);
2333 }
2334 
2335 /*
2336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2337 % %
2338 % %
2339 % %
2340 % I s B l o b T e m p o r a r y %
2341 % %
2342 % %
2343 % %
2344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2345 %
2346 % IsBlobTemporary() returns true if the blob is temporary.
2347 %
2348 % The format of the IsBlobTemporary method is:
2349 %
2350 % MagickBooleanType IsBlobTemporary(const Image *image)
2351 %
2352 % A description of each parameter follows:
2353 %
2354 % o image: the image.
2355 %
2356 */
2357 MagickExport MagickBooleanType IsBlobTemporary(const Image *image)
2358 {
2359  assert(image != (const Image *) NULL);
2360  assert(image->signature == MagickCoreSignature);
2361  if (IsEventLogging() != MagickFalse)
2362  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2363  return(image->blob->temporary);
2364 }
2365 
2366 /*
2367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2368 % %
2369 % %
2370 % %
2371 + M a p B l o b %
2372 % %
2373 % %
2374 % %
2375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2376 %
2377 % MapBlob() creates a mapping from a file to a binary large object.
2378 %
2379 % The format of the MapBlob method is:
2380 %
2381 % unsigned char *MapBlob(int file,const MapMode mode,
2382 % const MagickOffsetType offset,const size_t length)
2383 %
2384 % A description of each parameter follows:
2385 %
2386 % o file: map this file descriptor.
2387 %
2388 % o mode: ReadMode, WriteMode, or IOMode.
2389 %
2390 % o offset: starting at this offset within the file.
2391 %
2392 % o length: the length of the mapping is returned in this pointer.
2393 %
2394 */
2395 MagickExport unsigned char *MapBlob(int file,const MapMode mode,
2396  const MagickOffsetType offset,const size_t length)
2397 {
2398 #if defined(MAGICKCORE_HAVE_MMAP)
2399  int
2400  flags,
2401  protection;
2402 
2403  unsigned char
2404  *map;
2405 
2406  /*
2407  Map file.
2408  */
2409  flags=0;
2410  if (file == -1)
2411 #if defined(MAP_ANONYMOUS)
2412  flags|=MAP_ANONYMOUS;
2413 #else
2414  return((unsigned char *) NULL);
2415 #endif
2416  switch (mode)
2417  {
2418  case ReadMode:
2419  default:
2420  {
2421  protection=PROT_READ;
2422  flags|=MAP_PRIVATE;
2423  break;
2424  }
2425  case WriteMode:
2426  {
2427  protection=PROT_WRITE;
2428  flags|=MAP_SHARED;
2429  break;
2430  }
2431  case IOMode:
2432  {
2433  protection=PROT_READ | PROT_WRITE;
2434  flags|=MAP_SHARED;
2435  break;
2436  }
2437  }
2438 #if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
2439  map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,offset);
2440 #else
2441  map=(unsigned char *) mmap((char *) NULL,length,protection,flags |
2442  MAP_HUGETLB,file,offset);
2443  if (map == (unsigned char *) MAP_FAILED)
2444  map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file,
2445  offset);
2446 #endif
2447  if (map == (unsigned char *) MAP_FAILED)
2448  return((unsigned char *) NULL);
2449  return(map);
2450 #else
2451  (void) file;
2452  (void) mode;
2453  (void) offset;
2454  (void) length;
2455  return((unsigned char *) NULL);
2456 #endif
2457 }
2458 
2459 /*
2460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2461 % %
2462 % %
2463 % %
2464 + M S B O r d e r L o n g %
2465 % %
2466 % %
2467 % %
2468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2469 %
2470 % MSBOrderLong() converts a least-significant byte first buffer of integers to
2471 % most-significant byte first.
2472 %
2473 % The format of the MSBOrderLong method is:
2474 %
2475 % void MSBOrderLong(unsigned char *buffer,const size_t length)
2476 %
2477 % A description of each parameter follows.
2478 %
2479 % o buffer: Specifies a pointer to a buffer of integers.
2480 %
2481 % o length: Specifies the length of the buffer.
2482 %
2483 */
2484 MagickExport void MSBOrderLong(unsigned char *buffer,const size_t length)
2485 {
2486  int
2487  c;
2488 
2489  unsigned char
2490  *p,
2491  *q;
2492 
2493  assert(buffer != (unsigned char *) NULL);
2494  q=buffer+length;
2495  while (buffer < q)
2496  {
2497  p=buffer+3;
2498  c=(int) (*p);
2499  *p=(*buffer);
2500  *buffer++=(unsigned char) c;
2501  p=buffer+1;
2502  c=(int) (*p);
2503  *p=(*buffer);
2504  *buffer++=(unsigned char) c;
2505  buffer+=2;
2506  }
2507 }
2508 
2509 /*
2510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2511 % %
2512 % %
2513 % %
2514 + M S B O r d e r S h o r t %
2515 % %
2516 % %
2517 % %
2518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2519 %
2520 % MSBOrderShort() converts a least-significant byte first buffer of integers
2521 % to most-significant byte first.
2522 %
2523 % The format of the MSBOrderShort method is:
2524 %
2525 % void MSBOrderShort(unsigned char *p,const size_t length)
2526 %
2527 % A description of each parameter follows.
2528 %
2529 % o p: Specifies a pointer to a buffer of integers.
2530 %
2531 % o length: Specifies the length of the buffer.
2532 %
2533 */
2534 MagickExport void MSBOrderShort(unsigned char *p,const size_t length)
2535 {
2536  int
2537  c;
2538 
2539  unsigned char
2540  *q;
2541 
2542  assert(p != (unsigned char *) NULL);
2543  q=p+length;
2544  while (p < q)
2545  {
2546  c=(int) (*p);
2547  *p=(*(p+1));
2548  p++;
2549  *p++=(unsigned char) c;
2550  }
2551 }
2552 
2553 /*
2554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2555 % %
2556 % %
2557 % %
2558 + O p e n B l o b %
2559 % %
2560 % %
2561 % %
2562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2563 %
2564 % OpenBlob() opens a file associated with the image. A file name of '-' sets
2565 % the file to stdin for type 'r' and stdout for type 'w'. If the filename
2566 % suffix is '.gz' or '.Z', the image is decompressed for type 'r' and
2567 % compressed for type 'w'. If the filename prefix is '|', it is piped to or
2568 % from a system command.
2569 %
2570 % The format of the OpenBlob method is:
2571 %
2572 % MagickBooleanType OpenBlob(const ImageInfo *image_info,Image *image,
2573 % const BlobMode mode,ExceptionInfo *exception)
2574 %
2575 % A description of each parameter follows:
2576 %
2577 % o image_info: the image info.
2578 %
2579 % o image: the image.
2580 %
2581 % o mode: the mode for opening the file.
2582 %
2583 */
2584 
2585 static inline MagickBooleanType SetStreamBuffering(const ImageInfo *image_info,
2586  Image *image)
2587 {
2588  const char
2589  *option;
2590 
2591  int
2592  status;
2593 
2594  size_t
2595  size;
2596 
2597  size=MagickMinBufferExtent;
2598  option=GetImageOption(image_info,"stream:buffer-size");
2599  if (option != (const char *) NULL)
2600  size=StringToUnsignedLong(option);
2601  status=setvbuf(image->blob->file_info.file,(char *) NULL,size == 0 ?
2602  _IONBF : _IOFBF,size);
2603  return(status == 0 ? MagickTrue : MagickFalse);
2604 }
2605 
2606 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2607 static inline gzFile gzopen_utf8(const char *path,const char *mode)
2608 {
2609 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
2610  return(gzopen(path,mode));
2611 #else
2612  gzFile
2613  file;
2614 
2615  wchar_t
2616  *path_wide;
2617 
2618  path_wide=create_wchar_path(path);
2619  if (path_wide == (wchar_t *) NULL)
2620  return((gzFile) NULL);
2621  file=gzopen_w(path_wide,mode);
2622  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
2623  return(file);
2624 #endif
2625 }
2626 #endif
2627 
2628 MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
2629  Image *image,const BlobMode mode,ExceptionInfo *exception)
2630 {
2631  BlobInfo
2632  *magick_restrict blob_info;
2633 
2634  char
2635  extension[MagickPathExtent],
2636  filename[MagickPathExtent];
2637 
2638  const char
2639  *type;
2640 
2641  MagickBooleanType
2642  status;
2643 
2644  PolicyRights
2645  rights;
2646 
2647  assert(image_info != (ImageInfo *) NULL);
2648  assert(image_info->signature == MagickCoreSignature);
2649  assert(image != (Image *) NULL);
2650  assert(image->signature == MagickCoreSignature);
2651  if (IsEventLogging() != MagickFalse)
2652  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2653  image_info->filename);
2654  blob_info=image->blob;
2655  if (image_info->blob != (void *) NULL)
2656  {
2657  if (image_info->stream != (StreamHandler) NULL)
2658  blob_info->stream=(StreamHandler) image_info->stream;
2659  AttachBlob(blob_info,image_info->blob,image_info->length);
2660  return(MagickTrue);
2661  }
2662  (void) DetachBlob(blob_info);
2663  blob_info->mode=mode;
2664  switch (mode)
2665  {
2666  default: type="r"; break;
2667  case ReadBlobMode: type="r"; break;
2668  case ReadBinaryBlobMode: type="rb"; break;
2669  case WriteBlobMode: type="w"; break;
2670  case WriteBinaryBlobMode: type="w+b"; break;
2671  case AppendBlobMode: type="a"; break;
2672  case AppendBinaryBlobMode: type="a+b"; break;
2673  }
2674  if (*type != 'r')
2675  blob_info->synchronize=image_info->synchronize;
2676  if (image_info->stream != (StreamHandler) NULL)
2677  {
2678  blob_info->stream=(StreamHandler) image_info->stream;
2679  if (*type == 'w')
2680  {
2681  blob_info->type=FifoStream;
2682  return(MagickTrue);
2683  }
2684  }
2685  /*
2686  Open image file.
2687  */
2688  *filename='\0';
2689  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2690  rights=ReadPolicyRights;
2691  if (*type == 'w')
2692  rights=WritePolicyRights;
2693  if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)
2694  {
2695  errno=EPERM;
2696  (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2697  "NotAuthorized","`%s'",filename);
2698  return(MagickFalse);
2699  }
2700  if ((LocaleCompare(filename,"-") == 0) ||
2701  ((*filename == '\0') && (image_info->file == (FILE *) NULL)))
2702  {
2703  blob_info->file_info.file=(*type == 'r') ? stdin : stdout;
2704 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2705  if (strchr(type,'b') != (char *) NULL)
2706  (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
2707 #endif
2708  blob_info->type=StandardStream;
2709  blob_info->exempt=MagickTrue;
2710  return(SetStreamBuffering(image_info,image));
2711  }
2712  if ((LocaleNCompare(filename,"fd:",3) == 0) &&
2713  (IsGeometry(filename+3) != MagickFalse))
2714  {
2715  char
2716  fileMode[MagickPathExtent];
2717 
2718  *fileMode=(*type);
2719  fileMode[1]='\0';
2720  blob_info->file_info.file=fdopen(StringToLong(filename+3),fileMode);
2721  if (blob_info->file_info.file == (FILE *) NULL)
2722  {
2723  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2724  return(MagickFalse);
2725  }
2726 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
2727  if (strchr(type,'b') != (char *) NULL)
2728  (void) setmode(fileno(blob_info->file_info.file),_O_BINARY);
2729 #endif
2730  blob_info->type=FileStream;
2731  blob_info->exempt=MagickTrue;
2732  return(SetStreamBuffering(image_info,image));
2733  }
2734 #if defined(MAGICKCORE_HAVE_POPEN) && defined(MAGICKCORE_PIPES_SUPPORT)
2735  if (*filename == '|')
2736  {
2737  char
2738  fileMode[MagickPathExtent],
2739  *sanitize_command;
2740 
2741  /*
2742  Pipe image to or from a system command.
2743  */
2744 #if defined(SIGPIPE)
2745  if (*type == 'w')
2746  (void) signal(SIGPIPE,SIG_IGN);
2747 #endif
2748  *fileMode=(*type);
2749  fileMode[1]='\0';
2750  sanitize_command=SanitizeString(filename+1);
2751  blob_info->file_info.file=(FILE *) popen_utf8(sanitize_command,
2752  fileMode);
2753  sanitize_command=DestroyString(sanitize_command);
2754  if (blob_info->file_info.file == (FILE *) NULL)
2755  {
2756  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2757  return(MagickFalse);
2758  }
2759  blob_info->type=PipeStream;
2760  blob_info->exempt=MagickTrue;
2761  return(SetStreamBuffering(image_info,image));
2762  }
2763 #endif
2764  status=GetPathAttributes(filename,&blob_info->properties);
2765 #if defined(S_ISFIFO)
2766  if ((status != MagickFalse) && S_ISFIFO(blob_info->properties.st_mode))
2767  {
2768  blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2769  if (blob_info->file_info.file == (FILE *) NULL)
2770  {
2771  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2772  return(MagickFalse);
2773  }
2774  blob_info->type=FileStream;
2775  blob_info->exempt=MagickTrue;
2776  return(SetStreamBuffering(image_info,image));
2777  }
2778 #endif
2779  GetPathComponent(image->filename,ExtensionPath,extension);
2780  if (*type == 'w')
2781  {
2782  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
2783  if ((image_info->adjoin == MagickFalse) ||
2784  (strchr(filename,'%') != (char *) NULL))
2785  {
2786  /*
2787  Form filename for multi-part images.
2788  */
2789  (void) InterpretImageFilename(image_info,image,image->filename,(int)
2790  image->scene,filename);
2791  if ((LocaleCompare(filename,image->filename) == 0) &&
2792  ((GetPreviousImageInList(image) != (Image *) NULL) ||
2793  (GetNextImageInList(image) != (Image *) NULL)))
2794  {
2795  char
2796  path[MagickPathExtent];
2797 
2798  GetPathComponent(image->filename,RootPath,path);
2799  if (*extension == '\0')
2800  (void) FormatLocaleString(filename,MagickPathExtent,"%s-%.20g",
2801  path,(double) image->scene);
2802  else
2803  (void) FormatLocaleString(filename,MagickPathExtent,
2804  "%s-%.20g.%s",path,(double) image->scene,extension);
2805  }
2806  (void) CopyMagickString(image->filename,filename,MagickPathExtent);
2807 #if defined(macintosh)
2808  SetApplicationType(filename,image_info->magick,'8BIM');
2809 #endif
2810  }
2811  }
2812  if (image_info->file != (FILE *) NULL)
2813  {
2814  blob_info->file_info.file=image_info->file;
2815  blob_info->type=FileStream;
2816  blob_info->exempt=MagickTrue;
2817  }
2818  else
2819  if (*type == 'r')
2820  {
2821  blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2822  if (blob_info->file_info.file != (FILE *) NULL)
2823  {
2824  size_t
2825  count;
2826 
2827  unsigned char
2828  magick[3];
2829 
2830  blob_info->type=FileStream;
2831  (void) fstat(fileno(blob_info->file_info.file),
2832  &blob_info->properties);
2833  (void) SetStreamBuffering(image_info,image);
2834  (void) memset(magick,0,sizeof(magick));
2835  count=fread(magick,1,sizeof(magick),blob_info->file_info.file);
2836  (void) fseek(blob_info->file_info.file,-((off_t) count),SEEK_CUR);
2837 #if defined(MAGICKCORE_POSIX_SUPPORT)
2838  (void) fflush(blob_info->file_info.file);
2839 #endif
2840  (void) LogMagickEvent(BlobEvent,GetMagickModule(),
2841  " read %.20g magic header bytes",(double) count);
2842 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2843  if (((int) magick[0] == 0x1F) && ((int) magick[1] == 0x8B) &&
2844  ((int) magick[2] == 0x08))
2845  {
2846  gzFile
2847  gzfile = gzopen_utf8(filename,"rb");
2848 
2849  if (gzfile != (gzFile) NULL)
2850  {
2851  if (blob_info->file_info.file != (FILE *) NULL)
2852  (void) fclose(blob_info->file_info.file);
2853  blob_info->file_info.file=(FILE *) NULL;
2854  blob_info->file_info.gzfile=gzfile;
2855  blob_info->type=ZipStream;
2856  }
2857  }
2858 #endif
2859 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2860  if (strncmp((char *) magick,"BZh",3) == 0)
2861  {
2862  BZFILE
2863  *bzfile = BZ2_bzopen(filename,"r");
2864 
2865  if (bzfile != (BZFILE *) NULL)
2866  {
2867  if (blob_info->file_info.file != (FILE *) NULL)
2868  (void) fclose(blob_info->file_info.file);
2869  blob_info->file_info.file=(FILE *) NULL;
2870  blob_info->file_info.bzfile=bzfile;
2871  blob_info->type=BZipStream;
2872  }
2873  }
2874 #endif
2875  if (blob_info->type == FileStream)
2876  {
2877  const MagickInfo
2878  *magick_info;
2879 
2881  *sans_exception;
2882 
2883  size_t
2884  length;
2885 
2886  sans_exception=AcquireExceptionInfo();
2887  magick_info=GetMagickInfo(image_info->magick,sans_exception);
2888  sans_exception=DestroyExceptionInfo(sans_exception);
2889  length=(size_t) blob_info->properties.st_size;
2890  if ((magick_info != (const MagickInfo *) NULL) &&
2891  (GetMagickBlobSupport(magick_info) != MagickFalse) &&
2892  (length > MagickMaxBufferExtent) &&
2893  (AcquireMagickResource(MapResource,length) != MagickFalse))
2894  {
2895  void
2896  *blob;
2897 
2898  blob=MapBlob(fileno(blob_info->file_info.file),ReadMode,0,
2899  length);
2900  if (blob == (void *) NULL)
2901  RelinquishMagickResource(MapResource,length);
2902  else
2903  {
2904  /*
2905  Format supports blobs-- use memory-mapped I/O.
2906  */
2907  if (image_info->file != (FILE *) NULL)
2908  blob_info->exempt=MagickFalse;
2909  else
2910  {
2911  (void) fclose(blob_info->file_info.file);
2912  blob_info->file_info.file=(FILE *) NULL;
2913  }
2914  AttachBlob(blob_info,blob,length);
2915  blob_info->mapped=MagickTrue;
2916  }
2917  }
2918  }
2919  }
2920  }
2921  else
2922 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2923  if ((LocaleCompare(extension,"Z") == 0) ||
2924  (LocaleCompare(extension,"gz") == 0) ||
2925  (LocaleCompare(extension,"wmz") == 0) ||
2926  (LocaleCompare(extension,"svgz") == 0))
2927  {
2928  blob_info->file_info.gzfile=gzopen_utf8(filename,"wb");
2929  if (blob_info->file_info.gzfile != (gzFile) NULL)
2930  blob_info->type=ZipStream;
2931  }
2932  else
2933 #endif
2934 #if defined(MAGICKCORE_BZLIB_DELEGATE)
2935  if (LocaleCompare(extension,"bz2") == 0)
2936  {
2937  if (mode == WriteBinaryBlobMode)
2938  type="w";
2939  blob_info->file_info.bzfile=BZ2_bzopen(filename,"w");
2940  if (blob_info->file_info.bzfile != (BZFILE *) NULL)
2941  blob_info->type=BZipStream;
2942  }
2943  else
2944 #endif
2945  {
2946  blob_info->file_info.file=(FILE *) fopen_utf8(filename,type);
2947  if (blob_info->file_info.file != (FILE *) NULL)
2948  {
2949  blob_info->type=FileStream;
2950  (void) SetStreamBuffering(image_info,image);
2951  }
2952  }
2953  blob_info->status=MagickFalse;
2954  blob_info->error_number=0;
2955  if (blob_info->type != UndefinedStream)
2956  blob_info->size=GetBlobSize(image);
2957  else
2958  {
2959  ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);
2960  return(MagickFalse);
2961  }
2962  return(MagickTrue);
2963 }
2964 
2965 /*
2966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2967 % %
2968 % %
2969 % %
2970 + P i n g B l o b %
2971 % %
2972 % %
2973 % %
2974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2975 %
2976 % PingBlob() returns all the attributes of an image or image sequence except
2977 % for the pixels. It is much faster and consumes far less memory than
2978 % BlobToImage(). On failure, a NULL image is returned and exception
2979 % describes the reason for the failure.
2980 %
2981 % The format of the PingBlob method is:
2982 %
2983 % Image *PingBlob(const ImageInfo *image_info,const void *blob,
2984 % const size_t length,ExceptionInfo *exception)
2985 %
2986 % A description of each parameter follows:
2987 %
2988 % o image_info: the image info.
2989 %
2990 % o blob: the address of a character stream in one of the image formats
2991 % understood by ImageMagick.
2992 %
2993 % o length: This size_t integer reflects the length in bytes of the blob.
2994 %
2995 % o exception: return any errors or warnings in this structure.
2996 %
2997 */
2998 
2999 #if defined(__cplusplus) || defined(c_plusplus)
3000 extern "C" {
3001 #endif
3002 
3003 static size_t PingStream(const Image *magick_unused(image),
3004  const void *magick_unused(pixels),const size_t columns)
3005 {
3006  magick_unreferenced(image);
3007  magick_unreferenced(pixels);
3008 
3009  return(columns);
3010 }
3011 
3012 #if defined(__cplusplus) || defined(c_plusplus)
3013 }
3014 #endif
3015 
3016 MagickExport Image *PingBlob(const ImageInfo *image_info,const void *blob,
3017  const size_t length,ExceptionInfo *exception)
3018 {
3019  const MagickInfo
3020  *magick_info;
3021 
3022  Image
3023  *image;
3024 
3025  ImageInfo
3026  *clone_info,
3027  *ping_info;
3028 
3029  MagickBooleanType
3030  status;
3031 
3032  assert(image_info != (ImageInfo *) NULL);
3033  assert(image_info->signature == MagickCoreSignature);
3034  assert(exception != (ExceptionInfo *) NULL);
3035  if (IsEventLogging() != MagickFalse)
3036  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3037  image_info->filename);
3038  if ((blob == (const void *) NULL) || (length == 0))
3039  {
3040  (void) ThrowMagickException(exception,GetMagickModule(),BlobError,
3041  "ZeroLengthBlobNotPermitted","`%s'",image_info->filename);
3042  return((Image *) NULL);
3043  }
3044  ping_info=CloneImageInfo(image_info);
3045  ping_info->blob=(void *) blob;
3046  ping_info->length=length;
3047  ping_info->ping=MagickTrue;
3048  if (*ping_info->magick == '\0')
3049  (void) SetImageInfo(ping_info,0,exception);
3050  magick_info=GetMagickInfo(ping_info->magick,exception);
3051  if (magick_info == (const MagickInfo *) NULL)
3052  {
3053  (void) ThrowMagickException(exception,GetMagickModule(),
3054  MissingDelegateError,"NoDecodeDelegateForThisImageFormat","`%s'",
3055  ping_info->magick);
3056  ping_info=DestroyImageInfo(ping_info);
3057  return((Image *) NULL);
3058  }
3059  if (GetMagickBlobSupport(magick_info) != MagickFalse)
3060  {
3061  char
3062  filename[MagickPathExtent];
3063 
3064  /*
3065  Native blob support for this image format.
3066  */
3067  (void) CopyMagickString(filename,ping_info->filename,MagickPathExtent);
3068  (void) FormatLocaleString(ping_info->filename,MagickPathExtent,"%s:%s",
3069  ping_info->magick,filename);
3070  image=ReadStream(ping_info,&PingStream,exception);
3071  if (image != (Image *) NULL)
3072  (void) DetachBlob(image->blob);
3073  ping_info=DestroyImageInfo(ping_info);
3074  return(image);
3075  }
3076  /*
3077  Write blob to a temporary file on disk.
3078  */
3079  ping_info->blob=(void *) NULL;
3080  ping_info->length=0;
3081  *ping_info->filename='\0';
3082  status=BlobToFile(ping_info->filename,blob,length,exception);
3083  if (status == MagickFalse)
3084  {
3085  (void) RelinquishUniqueFileResource(ping_info->filename);
3086  ping_info=DestroyImageInfo(ping_info);
3087  return((Image *) NULL);
3088  }
3089  clone_info=CloneImageInfo(ping_info);
3090  (void) FormatLocaleString(clone_info->filename,MagickPathExtent,"%s:%s",
3091  ping_info->magick,ping_info->filename);
3092  image=ReadStream(clone_info,&PingStream,exception);
3093  if (image != (Image *) NULL)
3094  {
3095  Image
3096  *images;
3097 
3098  /*
3099  Restore original filenames and image format.
3100  */
3101  for (images=GetFirstImageInList(image); images != (Image *) NULL; )
3102  {
3103  (void) CopyMagickString(images->filename,image_info->filename,
3104  MagickPathExtent);
3105  (void) CopyMagickString(images->magick_filename,image_info->filename,
3106  MagickPathExtent);
3107  (void) CopyMagickString(images->magick,magick_info->name,
3108  MagickPathExtent);
3109  images=GetNextImageInList(images);
3110  }
3111  }
3112  clone_info=DestroyImageInfo(clone_info);
3113  (void) RelinquishUniqueFileResource(ping_info->filename);
3114  ping_info=DestroyImageInfo(ping_info);
3115  return(image);
3116 }
3117 
3118 /*
3119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3120 % %
3121 % %
3122 % %
3123 + R e a d B l o b %
3124 % %
3125 % %
3126 % %
3127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3128 %
3129 % ReadBlob() reads data from the blob or image file and returns it. It
3130 % returns the number of bytes read. If length is zero, ReadBlob() returns
3131 % zero and has no other results. If length is greater than MAGICK_SSIZE_MAX, the
3132 % result is unspecified.
3133 %
3134 % The format of the ReadBlob method is:
3135 %
3136 % ssize_t ReadBlob(Image *image,const size_t length,unsigned char *data)
3137 %
3138 % A description of each parameter follows:
3139 %
3140 % o image: the image.
3141 %
3142 % o length: Specifies an integer representing the number of bytes to read
3143 % from the file.
3144 %
3145 % o data: Specifies an area to place the information requested from the
3146 % file.
3147 %
3148 */
3149 MagickExport ssize_t ReadBlob(Image *image,const size_t length,
3150  unsigned char *data)
3151 {
3152  BlobInfo
3153  *magick_restrict blob_info;
3154 
3155  int
3156  c;
3157 
3158  unsigned char
3159  *q;
3160 
3161  ssize_t
3162  count;
3163 
3164  assert(image != (Image *) NULL);
3165  assert(image->signature == MagickCoreSignature);
3166  assert(image->blob != (BlobInfo *) NULL);
3167  assert(image->blob->type != UndefinedStream);
3168  if (length == 0)
3169  return(0);
3170  assert(data != (void *) NULL);
3171  blob_info=image->blob;
3172  count=0;
3173  q=data;
3174  switch (blob_info->type)
3175  {
3176  case UndefinedStream:
3177  break;
3178  case StandardStream:
3179  case FileStream:
3180  case PipeStream:
3181  {
3182  switch (length)
3183  {
3184  default:
3185  {
3186  count=(ssize_t) fread(q,1,length,blob_info->file_info.file);
3187  break;
3188  }
3189  case 4:
3190  {
3191  c=getc(blob_info->file_info.file);
3192  if (c == EOF)
3193  break;
3194  *q++=(unsigned char) c;
3195  count++;
3196  }
3197  case 3:
3198  {
3199  c=getc(blob_info->file_info.file);
3200  if (c == EOF)
3201  break;
3202  *q++=(unsigned char) c;
3203  count++;
3204  }
3205  case 2:
3206  {
3207  c=getc(blob_info->file_info.file);
3208  if (c == EOF)
3209  break;
3210  *q++=(unsigned char) c;
3211  count++;
3212  }
3213  case 1:
3214  {
3215  c=getc(blob_info->file_info.file);
3216  if (c == EOF)
3217  break;
3218  *q++=(unsigned char) c;
3219  count++;
3220  }
3221  case 0:
3222  break;
3223  }
3224  if ((count != (ssize_t) length) &&
3225  (ferror(blob_info->file_info.file) != 0))
3226  ThrowBlobException(blob_info);
3227  break;
3228  }
3229  case ZipStream:
3230  {
3231 #if defined(MAGICKCORE_ZLIB_DELEGATE)
3232  int
3233  status;
3234 
3235  switch (length)
3236  {
3237  default:
3238  {
3239  ssize_t
3240  i;
3241 
3242  for (i=0; i < (ssize_t) length; i+=count)
3243  {
3244  count=(ssize_t) gzread(blob_info->file_info.gzfile,q+i,
3245  (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3246  if (count <= 0)
3247  {
3248  count=0;
3249  if (errno != EINTR)
3250  break;
3251  }
3252  }
3253  count=i;
3254  break;
3255  }
3256  case 4:
3257  {
3258  c=gzgetc(blob_info->file_info.gzfile);
3259  if (c == EOF)
3260  break;
3261  *q++=(unsigned char) c;
3262  count++;
3263  }
3264  case 3:
3265  {
3266  c=gzgetc(blob_info->file_info.gzfile);
3267  if (c == EOF)
3268  break;
3269  *q++=(unsigned char) c;
3270  count++;
3271  }
3272  case 2:
3273  {
3274  c=gzgetc(blob_info->file_info.gzfile);
3275  if (c == EOF)
3276  break;
3277  *q++=(unsigned char) c;
3278  count++;
3279  }
3280  case 1:
3281  {
3282  c=gzgetc(blob_info->file_info.gzfile);
3283  if (c == EOF)
3284  break;
3285  *q++=(unsigned char) c;
3286  count++;
3287  }
3288  case 0:
3289  break;
3290  }
3291  status=Z_OK;
3292  (void) gzerror(blob_info->file_info.gzfile,&status);
3293  if ((count != (ssize_t) length) && (status != Z_OK))
3294  ThrowBlobException(blob_info);
3295  if (blob_info->eof == MagickFalse)
3296  blob_info->eof=gzeof(blob_info->file_info.gzfile) != 0 ? MagickTrue :
3297  MagickFalse;
3298 #endif
3299  break;
3300  }
3301  case BZipStream:
3302  {
3303 #if defined(MAGICKCORE_BZLIB_DELEGATE)
3304  int
3305  status;
3306 
3307  ssize_t
3308  i;
3309 
3310  for (i=0; i < (ssize_t) length; i+=count)
3311  {
3312  count=(ssize_t) BZ2_bzread(blob_info->file_info.bzfile,q+i,
3313  (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
3314  if (count <= 0)
3315  {
3316  count=0;
3317  if (errno != EINTR)
3318  break;
3319  }
3320  }
3321  count=i;
3322  status=BZ_OK;
3323  (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
3324  if ((count != (ssize_t) length) && (status != BZ_OK))
3325  ThrowBlobException(blob_info);
3326 #endif
3327  break;
3328  }
3329  case FifoStream:
3330  break;
3331  case BlobStream:
3332  {
3333  const unsigned char
3334  *p;
3335 
3336  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3337  {
3338  blob_info->eof=MagickTrue;
3339  break;
3340  }
3341  p=blob_info->data+blob_info->offset;
3342  count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
3343  blob_info->length-blob_info->offset);
3344  blob_info->offset+=count;
3345  if (count != (ssize_t) length)
3346  blob_info->eof=MagickTrue;
3347  (void) memcpy(q,p,(size_t) count);
3348  break;
3349  }
3350  }
3351  return(count);
3352 }
3353 
3354 /*
3355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3356 % %
3357 % %
3358 % %
3359 + R e a d B l o b B y t e %
3360 % %
3361 % %
3362 % %
3363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3364 %
3365 % ReadBlobByte() reads a single byte from the image file and returns it.
3366 %
3367 % The format of the ReadBlobByte method is:
3368 %
3369 % int ReadBlobByte(Image *image)
3370 %
3371 % A description of each parameter follows.
3372 %
3373 % o image: the image.
3374 %
3375 */
3376 MagickExport int ReadBlobByte(Image *image)
3377 {
3378  BlobInfo
3379  *magick_restrict blob_info;
3380 
3381  int
3382  c;
3383 
3384  assert(image != (Image *) NULL);
3385  assert(image->signature == MagickCoreSignature);
3386  assert(image->blob != (BlobInfo *) NULL);
3387  assert(image->blob->type != UndefinedStream);
3388  blob_info=image->blob;
3389  switch (blob_info->type)
3390  {
3391  case StandardStream:
3392  case FileStream:
3393  case PipeStream:
3394  {
3395  c=getc(blob_info->file_info.file);
3396  if (c == EOF)
3397  {
3398  if (ferror(blob_info->file_info.file) != 0)
3399  ThrowBlobException(blob_info);
3400  return(EOF);
3401  }
3402  break;
3403  }
3404  case BlobStream:
3405  {
3406  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
3407  {
3408  blob_info->eof=MagickTrue;
3409  return(EOF);
3410  }
3411  c=(int) (*((unsigned char *) blob_info->data+blob_info->offset));
3412  blob_info->offset++;
3413  break;
3414  }
3415  default:
3416  {
3417  ssize_t
3418  count;
3419 
3420  unsigned char
3421  buffer[1];
3422 
3423  count=ReadBlob(image,1,buffer);
3424  if (count != 1)
3425  return(EOF);
3426  c=(int) *buffer;
3427  break;
3428  }
3429  }
3430  return(c);
3431 }
3432 
3433 /*
3434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3435 % %
3436 % %
3437 % %
3438 + R e a d B l o b D o u b l e %
3439 % %
3440 % %
3441 % %
3442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3443 %
3444 % ReadBlobDouble() reads a double value as a 64-bit quantity in the byte-order
3445 % specified by the endian member of the image structure.
3446 %
3447 % The format of the ReadBlobDouble method is:
3448 %
3449 % double ReadBlobDouble(Image *image)
3450 %
3451 % A description of each parameter follows.
3452 %
3453 % o image: the image.
3454 %
3455 */
3456 MagickExport double ReadBlobDouble(Image *image)
3457 {
3458  union
3459  {
3460  MagickSizeType
3461  unsigned_value;
3462 
3463  double
3464  double_value;
3465  } quantum;
3466 
3467  quantum.double_value=0.0;
3468  quantum.unsigned_value=ReadBlobLongLong(image);
3469  return(quantum.double_value);
3470 }
3471 
3472 /*
3473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3474 % %
3475 % %
3476 % %
3477 + R e a d B l o b F l o a t %
3478 % %
3479 % %
3480 % %
3481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3482 %
3483 % ReadBlobFloat() reads a float value as a 32-bit quantity in the byte-order
3484 % specified by the endian member of the image structure.
3485 %
3486 % The format of the ReadBlobFloat method is:
3487 %
3488 % float ReadBlobFloat(Image *image)
3489 %
3490 % A description of each parameter follows.
3491 %
3492 % o image: the image.
3493 %
3494 */
3495 MagickExport float ReadBlobFloat(Image *image)
3496 {
3497  union
3498  {
3499  unsigned int
3500  unsigned_value;
3501 
3502  float
3503  float_value;
3504  } quantum;
3505 
3506  quantum.float_value=0.0;
3507  quantum.unsigned_value=ReadBlobLong(image);
3508  return(quantum.float_value);
3509 }
3510 
3511 /*
3512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3513 % %
3514 % %
3515 % %
3516 + R e a d B l o b L o n g %
3517 % %
3518 % %
3519 % %
3520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3521 %
3522 % ReadBlobLong() reads a unsigned int value as a 32-bit quantity in the
3523 % byte-order specified by the endian member of the image structure.
3524 %
3525 % The format of the ReadBlobLong method is:
3526 %
3527 % unsigned int ReadBlobLong(Image *image)
3528 %
3529 % A description of each parameter follows.
3530 %
3531 % o image: the image.
3532 %
3533 */
3534 MagickExport unsigned int ReadBlobLong(Image *image)
3535 {
3536  const unsigned char
3537  *p;
3538 
3539  ssize_t
3540  count;
3541 
3542  unsigned char
3543  buffer[4];
3544 
3545  unsigned int
3546  value;
3547 
3548  assert(image != (Image *) NULL);
3549  assert(image->signature == MagickCoreSignature);
3550  *buffer='\0';
3551  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3552  if (count != 4)
3553  return(0UL);
3554  if (image->endian == LSBEndian)
3555  {
3556  value=(unsigned int) (*p++);
3557  value|=(unsigned int) (*p++) << 8;
3558  value|=(unsigned int) (*p++) << 16;
3559  value|=(unsigned int) (*p++) << 24;
3560  return(value);
3561  }
3562  value=(unsigned int) (*p++) << 24;
3563  value|=(unsigned int) (*p++) << 16;
3564  value|=(unsigned int) (*p++) << 8;
3565  value|=(unsigned int) (*p++);
3566  return(value);
3567 }
3568 
3569 /*
3570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3571 % %
3572 % %
3573 % %
3574 + R e a d B l o b L o n g L o n g %
3575 % %
3576 % %
3577 % %
3578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3579 %
3580 % ReadBlobLongLong() reads a long long value as a 64-bit quantity in the
3581 % byte-order specified by the endian member of the image structure.
3582 %
3583 % The format of the ReadBlobLongLong method is:
3584 %
3585 % MagickSizeType ReadBlobLongLong(Image *image)
3586 %
3587 % A description of each parameter follows.
3588 %
3589 % o image: the image.
3590 %
3591 */
3592 MagickExport MagickSizeType ReadBlobLongLong(Image *image)
3593 {
3594  MagickSizeType
3595  value;
3596 
3597  const unsigned char
3598  *p;
3599 
3600  ssize_t
3601  count;
3602 
3603  unsigned char
3604  buffer[8];
3605 
3606  assert(image != (Image *) NULL);
3607  assert(image->signature == MagickCoreSignature);
3608  *buffer='\0';
3609  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3610  if (count != 8)
3611  return(MagickULLConstant(0));
3612  if (image->endian == LSBEndian)
3613  {
3614  value=(MagickSizeType) (*p++);
3615  value|=(MagickSizeType) (*p++) << 8;
3616  value|=(MagickSizeType) (*p++) << 16;
3617  value|=(MagickSizeType) (*p++) << 24;
3618  value|=(MagickSizeType) (*p++) << 32;
3619  value|=(MagickSizeType) (*p++) << 40;
3620  value|=(MagickSizeType) (*p++) << 48;
3621  value|=(MagickSizeType) (*p++) << 56;
3622  return(value);
3623  }
3624  value=(MagickSizeType) (*p++) << 56;
3625  value|=(MagickSizeType) (*p++) << 48;
3626  value|=(MagickSizeType) (*p++) << 40;
3627  value|=(MagickSizeType) (*p++) << 32;
3628  value|=(MagickSizeType) (*p++) << 24;
3629  value|=(MagickSizeType) (*p++) << 16;
3630  value|=(MagickSizeType) (*p++) << 8;
3631  value|=(MagickSizeType) (*p++);
3632  return(value);
3633 }
3634 
3635 /*
3636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3637 % %
3638 % %
3639 % %
3640 + R e a d B l o b S h o r t %
3641 % %
3642 % %
3643 % %
3644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3645 %
3646 % ReadBlobShort() reads a short value as a 16-bit quantity in the byte-order
3647 % specified by the endian member of the image structure.
3648 %
3649 % The format of the ReadBlobShort method is:
3650 %
3651 % unsigned short ReadBlobShort(Image *image)
3652 %
3653 % A description of each parameter follows.
3654 %
3655 % o image: the image.
3656 %
3657 */
3658 MagickExport unsigned short ReadBlobShort(Image *image)
3659 {
3660  const unsigned char
3661  *p;
3662 
3663  unsigned short
3664  value;
3665 
3666  ssize_t
3667  count;
3668 
3669  unsigned char
3670  buffer[2];
3671 
3672  assert(image != (Image *) NULL);
3673  assert(image->signature == MagickCoreSignature);
3674  *buffer='\0';
3675  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3676  if (count != 2)
3677  return((unsigned short) 0U);
3678  if (image->endian == LSBEndian)
3679  {
3680  value=(unsigned short) (*p++);
3681  value|=(unsigned short) (*p++) << 8;
3682  return(value);
3683  }
3684  value=(unsigned short) ((unsigned short) (*p++) << 8);
3685  value|=(unsigned short) (*p++);
3686  return(value);
3687 }
3688 
3689 /*
3690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3691 % %
3692 % %
3693 % %
3694 + R e a d B l o b L S B L o n g %
3695 % %
3696 % %
3697 % %
3698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3699 %
3700 % ReadBlobLSBLong() reads a unsigned int value as a 32-bit quantity in
3701 % least-significant byte first order.
3702 %
3703 % The format of the ReadBlobLSBLong method is:
3704 %
3705 % unsigned int ReadBlobLSBLong(Image *image)
3706 %
3707 % A description of each parameter follows.
3708 %
3709 % o image: the image.
3710 %
3711 */
3712 MagickExport unsigned int ReadBlobLSBLong(Image *image)
3713 {
3714  const unsigned char
3715  *p;
3716 
3717  unsigned int
3718  value;
3719 
3720  ssize_t
3721  count;
3722 
3723  unsigned char
3724  buffer[4];
3725 
3726  assert(image != (Image *) NULL);
3727  assert(image->signature == MagickCoreSignature);
3728  *buffer='\0';
3729  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3730  if (count != 4)
3731  return(0U);
3732  value=(unsigned int) (*p++);
3733  value|=(unsigned int) (*p++) << 8;
3734  value|=(unsigned int) (*p++) << 16;
3735  value|=(unsigned int) (*p++) << 24;
3736  return(value);
3737 }
3738 
3739 /*
3740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3741 % %
3742 % %
3743 % %
3744 + R e a d B l o b L S B S i g n e d L o n g %
3745 % %
3746 % %
3747 % %
3748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3749 %
3750 % ReadBlobLSBSignedLong() reads a signed int value as a 32-bit quantity in
3751 % least-significant byte first order.
3752 %
3753 % The format of the ReadBlobLSBSignedLong method is:
3754 %
3755 % signed int ReadBlobLSBSignedLong(Image *image)
3756 %
3757 % A description of each parameter follows.
3758 %
3759 % o image: the image.
3760 %
3761 */
3762 MagickExport signed int ReadBlobLSBSignedLong(Image *image)
3763 {
3764  union
3765  {
3766  unsigned int
3767  unsigned_value;
3768 
3769  signed int
3770  signed_value;
3771  } quantum;
3772 
3773  quantum.unsigned_value=ReadBlobLSBLong(image);
3774  return(quantum.signed_value);
3775 }
3776 
3777 /*
3778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3779 % %
3780 % %
3781 % %
3782 + R e a d B l o b L S B S h o r t %
3783 % %
3784 % %
3785 % %
3786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3787 %
3788 % ReadBlobLSBShort() reads a short value as a 16-bit quantity in
3789 % least-significant byte first order.
3790 %
3791 % The format of the ReadBlobLSBShort method is:
3792 %
3793 % unsigned short ReadBlobLSBShort(Image *image)
3794 %
3795 % A description of each parameter follows.
3796 %
3797 % o image: the image.
3798 %
3799 */
3800 MagickExport unsigned short ReadBlobLSBShort(Image *image)
3801 {
3802  const unsigned char
3803  *p;
3804 
3805  unsigned short
3806  value;
3807 
3808  ssize_t
3809  count;
3810 
3811  unsigned char
3812  buffer[2];
3813 
3814  assert(image != (Image *) NULL);
3815  assert(image->signature == MagickCoreSignature);
3816  *buffer='\0';
3817  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
3818  if (count != 2)
3819  return((unsigned short) 0U);
3820  value=(unsigned short) (*p++);
3821  value|=(unsigned short) (*p++) << 8;
3822  return(value);
3823 }
3824 
3825 /*
3826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3827 % %
3828 % %
3829 % %
3830 + R e a d B l o b L S B S i g n e d S h o r t %
3831 % %
3832 % %
3833 % %
3834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3835 %
3836 % ReadBlobLSBSignedShort() reads a signed short value as a 16-bit quantity in
3837 % least-significant byte-order.
3838 %
3839 % The format of the ReadBlobLSBSignedShort method is:
3840 %
3841 % signed short ReadBlobLSBSignedShort(Image *image)
3842 %
3843 % A description of each parameter follows.
3844 %
3845 % o image: the image.
3846 %
3847 */
3848 MagickExport signed short ReadBlobLSBSignedShort(Image *image)
3849 {
3850  union
3851  {
3852  unsigned short
3853  unsigned_value;
3854 
3855  signed short
3856  signed_value;
3857  } quantum;
3858 
3859  quantum.unsigned_value=ReadBlobLSBShort(image);
3860  return(quantum.signed_value);
3861 }
3862 
3863 /*
3864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3865 % %
3866 % %
3867 % %
3868 + R e a d B l o b M S B L o n g %
3869 % %
3870 % %
3871 % %
3872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3873 %
3874 % ReadBlobMSBLong() reads a unsigned int value as a 32-bit quantity in
3875 % most-significant byte first order.
3876 %
3877 % The format of the ReadBlobMSBLong method is:
3878 %
3879 % unsigned int ReadBlobMSBLong(Image *image)
3880 %
3881 % A description of each parameter follows.
3882 %
3883 % o image: the image.
3884 %
3885 */
3886 MagickExport unsigned int ReadBlobMSBLong(Image *image)
3887 {
3888  const unsigned char
3889  *p;
3890 
3891  unsigned int
3892  value;
3893 
3894  ssize_t
3895  count;
3896 
3897  unsigned char
3898  buffer[4];
3899 
3900  assert(image != (Image *) NULL);
3901  assert(image->signature == MagickCoreSignature);
3902  *buffer='\0';
3903  p=(const unsigned char *) ReadBlobStream(image,4,buffer,&count);
3904  if (count != 4)
3905  return(0UL);
3906  value=(unsigned int) (*p++) << 24;
3907  value|=(unsigned int) (*p++) << 16;
3908  value|=(unsigned int) (*p++) << 8;
3909  value|=(unsigned int) (*p++);
3910  return(value);
3911 }
3912 
3913 /*
3914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3915 % %
3916 % %
3917 % %
3918 + R e a d B l o b M S B L o n g L o n g %
3919 % %
3920 % %
3921 % %
3922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3923 %
3924 % ReadBlobMSBLongLong() reads a unsigned long int value as a 64-bit quantity
3925 % in most-significant byte first order.
3926 %
3927 % The format of the ReadBlobMSBLongLong method is:
3928 %
3929 % unsigned int ReadBlobMSBLongLong(Image *image)
3930 %
3931 % A description of each parameter follows.
3932 %
3933 % o image: the image.
3934 %
3935 */
3936 MagickExport MagickSizeType ReadBlobMSBLongLong(Image *image)
3937 {
3938  const unsigned char
3939  *p;
3940 
3941  MagickSizeType
3942  value;
3943 
3944  ssize_t
3945  count;
3946 
3947  unsigned char
3948  buffer[8];
3949 
3950  assert(image != (Image *) NULL);
3951  assert(image->signature == MagickCoreSignature);
3952  *buffer='\0';
3953  p=(const unsigned char *) ReadBlobStream(image,8,buffer,&count);
3954  if (count != 8)
3955  return(MagickULLConstant(0));
3956  value=(MagickSizeType) (*p++) << 56;
3957  value|=(MagickSizeType) (*p++) << 48;
3958  value|=(MagickSizeType) (*p++) << 40;
3959  value|=(MagickSizeType) (*p++) << 32;
3960  value|=(MagickSizeType) (*p++) << 24;
3961  value|=(MagickSizeType) (*p++) << 16;
3962  value|=(MagickSizeType) (*p++) << 8;
3963  value|=(MagickSizeType) (*p++);
3964  return(value);
3965 }
3966 
3967 /*
3968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3969 % %
3970 % %
3971 % %
3972 + R e a d B l o b M S B S h o r t %
3973 % %
3974 % %
3975 % %
3976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3977 %
3978 % ReadBlobMSBShort() reads a short value as a 16-bit quantity in
3979 % most-significant byte first order.
3980 %
3981 % The format of the ReadBlobMSBShort method is:
3982 %
3983 % unsigned short ReadBlobMSBShort(Image *image)
3984 %
3985 % A description of each parameter follows.
3986 %
3987 % o image: the image.
3988 %
3989 */
3990 MagickExport unsigned short ReadBlobMSBShort(Image *image)
3991 {
3992  const unsigned char
3993  *p;
3994 
3995  unsigned short
3996  value;
3997 
3998  ssize_t
3999  count;
4000 
4001  unsigned char
4002  buffer[2];
4003 
4004  assert(image != (Image *) NULL);
4005  assert(image->signature == MagickCoreSignature);
4006  *buffer='\0';
4007  p=(const unsigned char *) ReadBlobStream(image,2,buffer,&count);
4008  if (count != 2)
4009  return((unsigned short) 0U);
4010  value=(unsigned short) ((*p++) << 8);
4011  value|=(unsigned short) (*p++);
4012  return(value);
4013 }
4014 
4015 /*
4016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4017 % %
4018 % %
4019 % %
4020 + R e a d B l o b M S B S i g n e d L o n g %
4021 % %
4022 % %
4023 % %
4024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4025 %
4026 % ReadBlobMSBSignedLong() reads a signed int value as a 32-bit quantity in
4027 % most-significant byte-order.
4028 %
4029 % The format of the ReadBlobMSBSignedLong method is:
4030 %
4031 % signed int ReadBlobMSBSignedLong(Image *image)
4032 %
4033 % A description of each parameter follows.
4034 %
4035 % o image: the image.
4036 %
4037 */
4038 MagickExport signed int ReadBlobMSBSignedLong(Image *image)
4039 {
4040  union
4041  {
4042  unsigned int
4043  unsigned_value;
4044 
4045  signed int
4046  signed_value;
4047  } quantum;
4048 
4049  quantum.unsigned_value=ReadBlobMSBLong(image);
4050  return(quantum.signed_value);
4051 }
4052 
4053 /*
4054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4055 % %
4056 % %
4057 % %
4058 + R e a d B l o b M S B S i g n e d S h o r t %
4059 % %
4060 % %
4061 % %
4062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4063 %
4064 % ReadBlobMSBSignedShort() reads a signed short value as a 16-bit quantity in
4065 % most-significant byte-order.
4066 %
4067 % The format of the ReadBlobMSBSignedShort method is:
4068 %
4069 % signed short ReadBlobMSBSignedShort(Image *image)
4070 %
4071 % A description of each parameter follows.
4072 %
4073 % o image: the image.
4074 %
4075 */
4076 MagickExport signed short ReadBlobMSBSignedShort(Image *image)
4077 {
4078  union
4079  {
4080  unsigned short
4081  unsigned_value;
4082 
4083  signed short
4084  signed_value;
4085  } quantum;
4086 
4087  quantum.unsigned_value=ReadBlobMSBShort(image);
4088  return(quantum.signed_value);
4089 }
4090 
4091 /*
4092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4093 % %
4094 % %
4095 % %
4096 + R e a d B l o b S i g n e d L o n g %
4097 % %
4098 % %
4099 % %
4100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4101 %
4102 % ReadBlobSignedLong() reads a signed int value as a 32-bit quantity in the
4103 % byte-order specified by the endian member of the image structure.
4104 %
4105 % The format of the ReadBlobSignedLong method is:
4106 %
4107 % signed int ReadBlobSignedLong(Image *image)
4108 %
4109 % A description of each parameter follows.
4110 %
4111 % o image: the image.
4112 %
4113 */
4114 MagickExport signed int ReadBlobSignedLong(Image *image)
4115 {
4116  union
4117  {
4118  unsigned int
4119  unsigned_value;
4120 
4121  signed int
4122  signed_value;
4123  } quantum;
4124 
4125  quantum.unsigned_value=ReadBlobLong(image);
4126  return(quantum.signed_value);
4127 }
4128 
4129 /*
4130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4131 % %
4132 % %
4133 % %
4134 + R e a d B l o b S i g n e d S h o r t %
4135 % %
4136 % %
4137 % %
4138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4139 %
4140 % ReadBlobSignedShort() reads a signed short value as a 16-bit quantity in the
4141 % byte-order specified by the endian member of the image structure.
4142 %
4143 % The format of the ReadBlobSignedShort method is:
4144 %
4145 % signed short ReadBlobSignedShort(Image *image)
4146 %
4147 % A description of each parameter follows.
4148 %
4149 % o image: the image.
4150 %
4151 */
4152 MagickExport signed short ReadBlobSignedShort(Image *image)
4153 {
4154  union
4155  {
4156  unsigned short
4157  unsigned_value;
4158 
4159  signed short
4160  signed_value;
4161  } quantum;
4162 
4163  quantum.unsigned_value=ReadBlobShort(image);
4164  return(quantum.signed_value);
4165 }
4166 
4167 /*
4168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4169 % %
4170 % %
4171 % %
4172 + R e a d B l o b S t r e a m %
4173 % %
4174 % %
4175 % %
4176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4177 %
4178 % ReadBlobStream() reads data from the blob or image file and returns it. It
4179 % returns a pointer to the data buffer you supply or to the image memory
4180 % buffer if its supported (zero-copy). If length is zero, ReadBlobStream()
4181 % returns a count of zero and has no other results. If length is greater than
4182 % MAGICK_SSIZE_MAX, the result is unspecified.
4183 %
4184 % The format of the ReadBlobStream method is:
4185 %
4186 % const void *ReadBlobStream(Image *image,const size_t length,
4187 % void *magick_restrict data,ssize_t *count)
4188 %
4189 % A description of each parameter follows:
4190 %
4191 % o image: the image.
4192 %
4193 % o length: Specifies an integer representing the number of bytes to read
4194 % from the file.
4195 %
4196 % o count: returns the number of bytes read.
4197 %
4198 % o data: Specifies an area to place the information requested from the
4199 % file.
4200 %
4201 */
4202 MagickExport magick_hot_spot const void *ReadBlobStream(Image *image,
4203  const size_t length,void *magick_restrict data,ssize_t *count)
4204 {
4205  BlobInfo
4206  *magick_restrict blob_info;
4207 
4208  assert(image != (Image *) NULL);
4209  assert(image->signature == MagickCoreSignature);
4210  assert(image->blob != (BlobInfo *) NULL);
4211  assert(image->blob->type != UndefinedStream);
4212  assert(count != (ssize_t *) NULL);
4213  blob_info=image->blob;
4214  if (blob_info->type != BlobStream)
4215  {
4216  assert(data != NULL);
4217  *count=ReadBlob(image,length,(unsigned char *) data);
4218  return(data);
4219  }
4220  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
4221  {
4222  *count=0;
4223  blob_info->eof=MagickTrue;
4224  return(data);
4225  }
4226  data=blob_info->data+blob_info->offset;
4227  *count=(ssize_t) MagickMin((MagickOffsetType) length,(MagickOffsetType)
4228  blob_info->length-blob_info->offset);
4229  blob_info->offset+=(*count);
4230  if (*count != (ssize_t) length)
4231  blob_info->eof=MagickTrue;
4232  return(data);
4233 }
4234 
4235 /*
4236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4237 % %
4238 % %
4239 % %
4240 + R e a d B l o b S t r i n g %
4241 % %
4242 % %
4243 % %
4244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4245 %
4246 % ReadBlobString() reads characters from a blob or file until a newline
4247 % character is read or an end-of-file condition is encountered.
4248 %
4249 % The format of the ReadBlobString method is:
4250 %
4251 % char *ReadBlobString(Image *image,char *string)
4252 %
4253 % A description of each parameter follows:
4254 %
4255 % o image: the image.
4256 %
4257 % o string: the address of a character buffer.
4258 %
4259 */
4260 MagickExport char *ReadBlobString(Image *image,char *string)
4261 {
4262  BlobInfo
4263  *magick_restrict blob_info;
4264 
4265  int
4266  c = -1;
4267 
4268  ssize_t
4269  i = 0;
4270 
4271  assert(image != (Image *) NULL);
4272  assert(image->signature == MagickCoreSignature);
4273  assert(image->blob != (BlobInfo *) NULL);
4274  assert(image->blob->type != UndefinedStream);
4275  if (IsEventLogging() != MagickFalse)
4276  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4277  *string='\0';
4278  blob_info=image->blob;
4279  switch (blob_info->type)
4280  {
4281  case UndefinedStream:
4282  break;
4283  case StandardStream:
4284  case FileStream:
4285  {
4286  char *p = fgets(string,MagickPathExtent,blob_info->file_info.file);
4287  if (p == (char *) NULL)
4288  {
4289  if (ferror(blob_info->file_info.file) != 0)
4290  ThrowBlobException(blob_info);
4291  return((char *) NULL);
4292  }
4293  i=strlen(string);
4294  break;
4295  }
4296  case ZipStream:
4297  {
4298 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4299  char *p = gzgets(blob_info->file_info.gzfile,string,MagickPathExtent);
4300  if (p == (char *) NULL)
4301  {
4302  int status = Z_OK;
4303  (void) gzerror(blob_info->file_info.gzfile,&status);
4304  if (status != Z_OK)
4305  ThrowBlobException(blob_info);
4306  return((char *) NULL);
4307  }
4308  i=strlen(string);
4309  break;
4310 #endif
4311  }
4312  default:
4313  {
4314  do
4315  {
4316  c=ReadBlobByte(image);
4317  if (c == EOF)
4318  {
4319  blob_info->eof=MagickTrue;
4320  break;
4321  }
4322  string[i++]=c;
4323  if (c == '\n')
4324  break;
4325  } while (i < (MaxTextExtent-2));
4326  string[i]='\0';
4327  break;
4328  }
4329  }
4330  /*
4331  Strip trailing newline.
4332  */
4333  if ((string[i] == '\r') || (string[i] == '\n'))
4334  string[i]='\0';
4335  if (i >= 1)
4336  if ((string[i-1] == '\r') || (string[i-1] == '\n'))
4337  string[i-1]='\0';
4338  if ((*string == '\0') && (blob_info->eof != MagickFalse))
4339  return((char *) NULL);
4340  return(string);
4341 }
4342 
4343 /*
4344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4345 % %
4346 % %
4347 % %
4348 + R e f e r e n c e B l o b %
4349 % %
4350 % %
4351 % %
4352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4353 %
4354 % ReferenceBlob() increments the reference count associated with the pixel
4355 % blob returning a pointer to the blob.
4356 %
4357 % The format of the ReferenceBlob method is:
4358 %
4359 % BlobInfo ReferenceBlob(BlobInfo *blob_info)
4360 %
4361 % A description of each parameter follows:
4362 %
4363 % o blob_info: the blob_info.
4364 %
4365 */
4366 MagickExport BlobInfo *ReferenceBlob(BlobInfo *blob)
4367 {
4368  assert(blob != (BlobInfo *) NULL);
4369  assert(blob->signature == MagickCoreSignature);
4370  if (IsEventLogging() != MagickFalse)
4371  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4372  LockSemaphoreInfo(blob->semaphore);
4373  blob->reference_count++;
4374  UnlockSemaphoreInfo(blob->semaphore);
4375  return(blob);
4376 }
4377 
4378 /*
4379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4380 % %
4381 % %
4382 % %
4383 + S e e k B l o b %
4384 % %
4385 % %
4386 % %
4387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4388 %
4389 % SeekBlob() sets the offset in bytes from the beginning of a blob or file
4390 % and returns the resulting offset.
4391 %
4392 % The format of the SeekBlob method is:
4393 %
4394 % MagickOffsetType SeekBlob(Image *image,const MagickOffsetType offset,
4395 % const int whence)
4396 %
4397 % A description of each parameter follows:
4398 %
4399 % o image: the image.
4400 %
4401 % o offset: Specifies an integer representing the offset in bytes.
4402 %
4403 % o whence: Specifies an integer representing how the offset is
4404 % treated relative to the beginning of the blob as follows:
4405 %
4406 % SEEK_SET Set position equal to offset bytes.
4407 % SEEK_CUR Set position to current location plus offset.
4408 % SEEK_END Set position to EOF plus offset.
4409 %
4410 */
4411 MagickExport MagickOffsetType SeekBlob(Image *image,
4412  const MagickOffsetType offset,const int whence)
4413 {
4414  BlobInfo
4415  *magick_restrict blob_info;
4416 
4417  assert(image != (Image *) NULL);
4418  assert(image->signature == MagickCoreSignature);
4419  assert(image->blob != (BlobInfo *) NULL);
4420  assert(image->blob->type != UndefinedStream);
4421  if (IsEventLogging() != MagickFalse)
4422  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4423  blob_info=image->blob;
4424  switch (blob_info->type)
4425  {
4426  case UndefinedStream:
4427  break;
4428  case StandardStream:
4429  case PipeStream:
4430  return(-1);
4431  case FileStream:
4432  {
4433  if ((offset < 0) && (whence == SEEK_SET))
4434  return(-1);
4435  if (fseek(blob_info->file_info.file,offset,whence) < 0)
4436  return(-1);
4437  blob_info->offset=TellBlob(image);
4438  break;
4439  }
4440  case ZipStream:
4441  {
4442 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4443  if (gzseek(blob_info->file_info.gzfile,offset,whence) < 0)
4444  return(-1);
4445 #endif
4446  blob_info->offset=TellBlob(image);
4447  break;
4448  }
4449  case BZipStream:
4450  return(-1);
4451  case FifoStream:
4452  return(-1);
4453  case BlobStream:
4454  {
4455  switch (whence)
4456  {
4457  case SEEK_SET:
4458  default:
4459  {
4460  if (offset < 0)
4461  return(-1);
4462  blob_info->offset=offset;
4463  break;
4464  }
4465  case SEEK_CUR:
4466  {
4467  if (((offset > 0) && (blob_info->offset > (MAGICK_SSIZE_MAX-offset))) ||
4468  ((offset < 0) && (blob_info->offset < (MAGICK_SSIZE_MIN-offset))))
4469  {
4470  errno=EOVERFLOW;
4471  return(-1);
4472  }
4473  if ((blob_info->offset+offset) < 0)
4474  return(-1);
4475  blob_info->offset+=offset;
4476  break;
4477  }
4478  case SEEK_END:
4479  {
4480  if (((MagickOffsetType) blob_info->length+offset) < 0)
4481  return(-1);
4482  blob_info->offset=blob_info->length+offset;
4483  break;
4484  }
4485  }
4486  if (blob_info->offset < (MagickOffsetType) ((off_t) blob_info->length))
4487  {
4488  blob_info->eof=MagickFalse;
4489  break;
4490  }
4491  if (blob_info->offset >= (MagickOffsetType) ((off_t) blob_info->extent))
4492  return(-1);
4493  break;
4494  }
4495  }
4496  return(blob_info->offset);
4497 }
4498 
4499 /*
4500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4501 % %
4502 % %
4503 % %
4504 + S e t B l o b E x e m p t %
4505 % %
4506 % %
4507 % %
4508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4509 %
4510 % SetBlobExempt() sets the blob exempt status.
4511 %
4512 % The format of the SetBlobExempt method is:
4513 %
4514 % MagickBooleanType SetBlobExempt(const Image *image,
4515 % const MagickBooleanType exempt)
4516 %
4517 % A description of each parameter follows:
4518 %
4519 % o image: the image.
4520 %
4521 % o exempt: Set to true if this blob is exempt from being closed.
4522 %
4523 */
4524 MagickExport void SetBlobExempt(Image *image,const MagickBooleanType exempt)
4525 {
4526  assert(image != (const Image *) NULL);
4527  assert(image->signature == MagickCoreSignature);
4528  if (IsEventLogging() != MagickFalse)
4529  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4530  image->blob->exempt=exempt;
4531 }
4532 
4533 /*
4534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4535 % %
4536 % %
4537 % %
4538 + S e t B l o b E x t e n t %
4539 % %
4540 % %
4541 % %
4542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4543 %
4544 % SetBlobExtent() ensures enough space is allocated for the blob. If the
4545 % method is successful, subsequent writes to bytes in the specified range are
4546 % guaranteed not to fail.
4547 %
4548 % The format of the SetBlobExtent method is:
4549 %
4550 % MagickBooleanType SetBlobExtent(Image *image,const MagickSizeType extent)
4551 %
4552 % A description of each parameter follows:
4553 %
4554 % o image: the image.
4555 %
4556 % o extent: the blob maximum extent.
4557 %
4558 */
4559 MagickExport MagickBooleanType SetBlobExtent(Image *image,
4560  const MagickSizeType extent)
4561 {
4562  BlobInfo
4563  *magick_restrict blob_info;
4564 
4565  assert(image != (Image *) NULL);
4566  assert(image->signature == MagickCoreSignature);
4567  assert(image->blob != (BlobInfo *) NULL);
4568  assert(image->blob->type != UndefinedStream);
4569  if (IsEventLogging() != MagickFalse)
4570  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4571  blob_info=image->blob;
4572  switch (blob_info->type)
4573  {
4574  case UndefinedStream:
4575  break;
4576  case StandardStream:
4577  return(MagickFalse);
4578  case FileStream:
4579  {
4580  MagickOffsetType
4581  offset;
4582 
4583  ssize_t
4584  count;
4585 
4586  if (extent != (MagickSizeType) ((off_t) extent))
4587  return(MagickFalse);
4588  offset=SeekBlob(image,0,SEEK_END);
4589  if (offset < 0)
4590  return(MagickFalse);
4591  if ((MagickSizeType) offset >= extent)
4592  break;
4593  offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4594  if (offset < 0)
4595  break;
4596  count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4597  blob_info->file_info.file);
4598 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4599  if (blob_info->synchronize != MagickFalse)
4600  {
4601  int
4602  file;
4603 
4604  file=fileno(blob_info->file_info.file);
4605  if ((file == -1) || (offset < 0))
4606  return(MagickFalse);
4607  (void) posix_fallocate(file,offset,extent-offset);
4608  }
4609 #endif
4610  offset=SeekBlob(image,offset,SEEK_SET);
4611  if (count != 1)
4612  return(MagickFalse);
4613  break;
4614  }
4615  case PipeStream:
4616  case ZipStream:
4617  return(MagickFalse);
4618  case BZipStream:
4619  return(MagickFalse);
4620  case FifoStream:
4621  return(MagickFalse);
4622  case BlobStream:
4623  {
4624  if (extent != (MagickSizeType) ((size_t) extent))
4625  return(MagickFalse);
4626  if (blob_info->mapped != MagickFalse)
4627  {
4628  MagickOffsetType
4629  offset;
4630 
4631  ssize_t
4632  count;
4633 
4634  (void) UnmapBlob(blob_info->data,blob_info->length);
4635  RelinquishMagickResource(MapResource,blob_info->length);
4636  if (extent != (MagickSizeType) ((off_t) extent))
4637  return(MagickFalse);
4638  offset=SeekBlob(image,0,SEEK_END);
4639  if (offset < 0)
4640  return(MagickFalse);
4641  if ((MagickSizeType) offset >= extent)
4642  break;
4643  offset=SeekBlob(image,(MagickOffsetType) extent-1,SEEK_SET);
4644  count=(ssize_t) fwrite((const unsigned char *) "",1,1,
4645  blob_info->file_info.file);
4646 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
4647  if (blob_info->synchronize != MagickFalse)
4648  {
4649  int
4650  file;
4651 
4652  file=fileno(blob_info->file_info.file);
4653  if ((file == -1) || (offset < 0))
4654  return(MagickFalse);
4655  (void) posix_fallocate(file,offset,extent-offset);
4656  }
4657 #endif
4658  offset=SeekBlob(image,offset,SEEK_SET);
4659  if (count != 1)
4660  return(MagickFalse);
4661  (void) AcquireMagickResource(MapResource,extent);
4662  blob_info->data=(unsigned char*) MapBlob(fileno(
4663  blob_info->file_info.file),WriteMode,0,(size_t) extent);
4664  blob_info->extent=(size_t) extent;
4665  blob_info->length=(size_t) extent;
4666  (void) SyncBlob(image);
4667  break;
4668  }
4669  blob_info->extent=(size_t) extent;
4670  blob_info->data=(unsigned char *) ResizeQuantumMemory(blob_info->data,
4671  blob_info->extent+1,sizeof(*blob_info->data));
4672  (void) SyncBlob(image);
4673  if (blob_info->data == (unsigned char *) NULL)
4674  {
4675  (void) DetachBlob(blob_info);
4676  return(MagickFalse);
4677  }
4678  break;
4679  }
4680  }
4681  return(MagickTrue);
4682 }
4683 
4684 /*
4685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4686 % %
4687 % %
4688 % %
4689 + S y n c B l o b %
4690 % %
4691 % %
4692 % %
4693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4694 %
4695 % SyncBlob() flushes the datastream if it is a file or synchronizes the data
4696 % attributes if it is an blob.
4697 %
4698 % The format of the SyncBlob method is:
4699 %
4700 % int SyncBlob(Image *image)
4701 %
4702 % A description of each parameter follows:
4703 %
4704 % o image: the image.
4705 %
4706 */
4707 static int SyncBlob(Image *image)
4708 {
4709  BlobInfo
4710  *magick_restrict blob_info;
4711 
4712  int
4713  status;
4714 
4715  assert(image != (Image *) NULL);
4716  assert(image->signature == MagickCoreSignature);
4717  assert(image->blob != (BlobInfo *) NULL);
4718  assert(image->blob->type != UndefinedStream);
4719  if (IsEventLogging() != MagickFalse)
4720  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4721  blob_info=image->blob;
4722  status=0;
4723  switch (blob_info->type)
4724  {
4725  case UndefinedStream:
4726  case StandardStream:
4727  break;
4728  case FileStream:
4729  case PipeStream:
4730  {
4731  status=fflush(blob_info->file_info.file);
4732  break;
4733  }
4734  case ZipStream:
4735  {
4736 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4737  status=gzflush(blob_info->file_info.gzfile,Z_SYNC_FLUSH);
4738 #endif
4739  break;
4740  }
4741  case BZipStream:
4742  {
4743 #if defined(MAGICKCORE_BZLIB_DELEGATE)
4744  status=BZ2_bzflush(blob_info->file_info.bzfile);
4745 #endif
4746  break;
4747  }
4748  case FifoStream:
4749  break;
4750  case BlobStream:
4751  break;
4752  }
4753  return(status);
4754 }
4755 
4756 /*
4757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4758 % %
4759 % %
4760 % %
4761 + T e l l B l o b %
4762 % %
4763 % %
4764 % %
4765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4766 %
4767 % TellBlob() obtains the current value of the blob or file position.
4768 %
4769 % The format of the TellBlob method is:
4770 %
4771 % MagickOffsetType TellBlob(const Image *image)
4772 %
4773 % A description of each parameter follows:
4774 %
4775 % o image: the image.
4776 %
4777 */
4778 MagickExport MagickOffsetType TellBlob(const Image *image)
4779 {
4780  BlobInfo
4781  *magick_restrict blob_info;
4782 
4783  MagickOffsetType
4784  offset;
4785 
4786  assert(image != (Image *) NULL);
4787  assert(image->signature == MagickCoreSignature);
4788  assert(image->blob != (BlobInfo *) NULL);
4789  assert(image->blob->type != UndefinedStream);
4790  if (IsEventLogging() != MagickFalse)
4791  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4792  blob_info=image->blob;
4793  offset=(-1);
4794  switch (blob_info->type)
4795  {
4796  case UndefinedStream:
4797  case StandardStream:
4798  break;
4799  case FileStream:
4800  {
4801  offset=ftell(blob_info->file_info.file);
4802  break;
4803  }
4804  case PipeStream:
4805  break;
4806  case ZipStream:
4807  {
4808 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4809  offset=(MagickOffsetType) gztell(blob_info->file_info.gzfile);
4810 #endif
4811  break;
4812  }
4813  case BZipStream:
4814  break;
4815  case FifoStream:
4816  break;
4817  case BlobStream:
4818  {
4819  offset=blob_info->offset;
4820  break;
4821  }
4822  }
4823  return(offset);
4824 }
4825 
4826 /*
4827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4828 % %
4829 % %
4830 % %
4831 + U n m a p B l o b %
4832 % %
4833 % %
4834 % %
4835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4836 %
4837 % UnmapBlob() deallocates the binary large object previously allocated with
4838 % the MapBlob method.
4839 %
4840 % The format of the UnmapBlob method is:
4841 %
4842 % MagickBooleanType UnmapBlob(void *map,const size_t length)
4843 %
4844 % A description of each parameter follows:
4845 %
4846 % o map: the address of the binary large object.
4847 %
4848 % o length: the length of the binary large object.
4849 %
4850 */
4851 MagickExport MagickBooleanType UnmapBlob(void *map,const size_t length)
4852 {
4853 #if defined(MAGICKCORE_HAVE_MMAP)
4854  int
4855  status;
4856 
4857  status=munmap(map,length);
4858  return(status == -1 ? MagickFalse : MagickTrue);
4859 #else
4860  (void) map;
4861  (void) length;
4862  return(MagickFalse);
4863 #endif
4864 }
4865 
4866 /*
4867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4868 % %
4869 % %
4870 % %
4871 + W r i t e B l o b %
4872 % %
4873 % %
4874 % %
4875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4876 %
4877 % WriteBlob() writes data to a blob or image file. It returns the number of
4878 % bytes written.
4879 %
4880 % The format of the WriteBlob method is:
4881 %
4882 % ssize_t WriteBlob(Image *image,const size_t length,
4883 % const unsigned char *data)
4884 %
4885 % A description of each parameter follows:
4886 %
4887 % o image: the image.
4888 %
4889 % o length: Specifies an integer representing the number of bytes to
4890 % write to the file.
4891 %
4892 % o data: The address of the data to write to the blob or file.
4893 %
4894 */
4895 MagickExport ssize_t WriteBlob(Image *image,const size_t length,
4896  const unsigned char *data)
4897 {
4898  BlobInfo
4899  *magick_restrict blob_info;
4900 
4901  int
4902  c;
4903 
4904  const unsigned char
4905  *p;
4906 
4907  unsigned char
4908  *q;
4909 
4910  ssize_t
4911  count;
4912 
4913  assert(image != (Image *) NULL);
4914  assert(image->signature == MagickCoreSignature);
4915  assert(image->blob != (BlobInfo *) NULL);
4916  assert(image->blob->type != UndefinedStream);
4917  if (length == 0)
4918  return(0);
4919  assert(data != (const unsigned char *) NULL);
4920  blob_info=image->blob;
4921  count=0;
4922  p=(const unsigned char *) data;
4923  q=(unsigned char *) data;
4924  switch (blob_info->type)
4925  {
4926  case UndefinedStream:
4927  break;
4928  case StandardStream:
4929  case FileStream:
4930  case PipeStream:
4931  {
4932  switch (length)
4933  {
4934  default:
4935  {
4936  count=(ssize_t) fwrite((const char *) data,1,length,
4937  blob_info->file_info.file);
4938  break;
4939  }
4940  case 4:
4941  {
4942  c=putc((int) *p++,blob_info->file_info.file);
4943  if (c == EOF)
4944  break;
4945  count++;
4946  }
4947  case 3:
4948  {
4949  c=putc((int) *p++,blob_info->file_info.file);
4950  if (c == EOF)
4951  break;
4952  count++;
4953  }
4954  case 2:
4955  {
4956  c=putc((int) *p++,blob_info->file_info.file);
4957  if (c == EOF)
4958  break;
4959  count++;
4960  }
4961  case 1:
4962  {
4963  c=putc((int) *p++,blob_info->file_info.file);
4964  if (c == EOF)
4965  break;
4966  count++;
4967  }
4968  case 0:
4969  break;
4970  }
4971  if ((count != (ssize_t) length) &&
4972  (ferror(blob_info->file_info.file) != 0))
4973  ThrowBlobException(blob_info);
4974  break;
4975  }
4976  case ZipStream:
4977  {
4978 #if defined(MAGICKCORE_ZLIB_DELEGATE)
4979  int
4980  status;
4981 
4982  switch (length)
4983  {
4984  default:
4985  {
4986  ssize_t
4987  i;
4988 
4989  for (i=0; i < (ssize_t) length; i+=count)
4990  {
4991  count=(ssize_t) gzwrite(blob_info->file_info.gzfile,q+i,
4992  (unsigned int) MagickMin(length-i,MagickMaxBufferExtent));
4993  if (count <= 0)
4994  {
4995  count=0;
4996  if (errno != EINTR)
4997  break;
4998  }
4999  }
5000  count=i;
5001  break;
5002  }
5003  case 4:
5004  {
5005  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5006  if (c == EOF)
5007  break;
5008  count++;
5009  }
5010  case 3:
5011  {
5012  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5013  if (c == EOF)
5014  break;
5015  count++;
5016  }
5017  case 2:
5018  {
5019  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5020  if (c == EOF)
5021  break;
5022  count++;
5023  }
5024  case 1:
5025  {
5026  c=gzputc(blob_info->file_info.gzfile,(int) *p++);
5027  if (c == EOF)
5028  break;
5029  count++;
5030  }
5031  case 0:
5032  break;
5033  }
5034  status=Z_OK;
5035  (void) gzerror(blob_info->file_info.gzfile,&status);
5036  if ((count != (ssize_t) length) && (status != Z_OK))
5037  ThrowBlobException(blob_info);
5038 #endif
5039  break;
5040  }
5041  case BZipStream:
5042  {
5043 #if defined(MAGICKCORE_BZLIB_DELEGATE)
5044  int
5045  status;
5046 
5047  ssize_t
5048  i;
5049 
5050  for (i=0; i < (ssize_t) length; i+=count)
5051  {
5052  count=(ssize_t) BZ2_bzwrite(blob_info->file_info.bzfile,q+i,
5053  (int) MagickMin(length-i,MagickMaxBufferExtent));
5054  if (count <= 0)
5055  {
5056  count=0;
5057  if (errno != EINTR)
5058  break;
5059  }
5060  }
5061  count=i;
5062  status=BZ_OK;
5063  (void) BZ2_bzerror(blob_info->file_info.bzfile,&status);
5064  if ((count != (ssize_t) length) && (status != BZ_OK))
5065  ThrowBlobException(blob_info);
5066 #endif
5067  break;
5068  }
5069  case FifoStream:
5070  {
5071  count=(ssize_t) blob_info->stream(image,data,length);
5072  break;
5073  }
5074  case BlobStream:
5075  {
5076  if ((blob_info->offset+(MagickOffsetType) length) >=
5077  (MagickOffsetType) blob_info->extent)
5078  {
5079  if (blob_info->mapped != MagickFalse)
5080  return(0);
5081  blob_info->extent+=length+blob_info->quantum;
5082  blob_info->quantum<<=1;
5083  blob_info->data=(unsigned char *) ResizeQuantumMemory(
5084  blob_info->data,blob_info->extent+1,sizeof(*blob_info->data));
5085  (void) SyncBlob(image);
5086  if (blob_info->data == (unsigned char *) NULL)
5087  {
5088  (void) DetachBlob(blob_info);
5089  return(0);
5090  }
5091  }
5092  q=blob_info->data+blob_info->offset;
5093  (void) memcpy(q,p,length);
5094  blob_info->offset+=length;
5095  if (blob_info->offset >= (MagickOffsetType) blob_info->length)
5096  blob_info->length=(size_t) blob_info->offset;
5097  count=(ssize_t) length;
5098  }
5099  }
5100  if (count != (ssize_t) length)
5101  ThrowBlobException(blob_info);
5102  return(count);
5103 }
5104 
5105 /*
5106 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5107 % %
5108 % %
5109 % %
5110 + W r i t e B l o b B y t e %
5111 % %
5112 % %
5113 % %
5114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5115 %
5116 % WriteBlobByte() write an integer to a blob. It returns the number of bytes
5117 % written (either 0 or 1);
5118 %
5119 % The format of the WriteBlobByte method is:
5120 %
5121 % ssize_t WriteBlobByte(Image *image,const unsigned char value)
5122 %
5123 % A description of each parameter follows.
5124 %
5125 % o image: the image.
5126 %
5127 % o value: Specifies the value to write.
5128 %
5129 */
5130 MagickExport ssize_t WriteBlobByte(Image *image,const unsigned char value)
5131 {
5132  BlobInfo
5133  *magick_restrict blob_info;
5134 
5135  ssize_t
5136  count;
5137 
5138  assert(image != (Image *) NULL);
5139  assert(image->signature == MagickCoreSignature);
5140  assert(image->blob != (BlobInfo *) NULL);
5141  assert(image->blob->type != UndefinedStream);
5142  blob_info=image->blob;
5143  count=0;
5144  switch (blob_info->type)
5145  {
5146  case StandardStream:
5147  case FileStream:
5148  case PipeStream:
5149  {
5150  int
5151  c;
5152 
5153  c=putc((int) value,blob_info->file_info.file);
5154  if (c == EOF)
5155  {
5156  if (ferror(blob_info->file_info.file) != 0)
5157  ThrowBlobException(blob_info);
5158  break;
5159  }
5160  count++;
5161  break;
5162  }
5163  default:
5164  {
5165  count=WriteBlobStream(image,1,&value);
5166  break;
5167  }
5168  }
5169  return(count);
5170 }
5171 
5172 /*
5173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5174 % %
5175 % %
5176 % %
5177 + W r i t e B l o b F l o a t %
5178 % %
5179 % %
5180 % %
5181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5182 %
5183 % WriteBlobFloat() writes a float value as a 32-bit quantity in the byte-order
5184 % specified by the endian member of the image structure.
5185 %
5186 % The format of the WriteBlobFloat method is:
5187 %
5188 % ssize_t WriteBlobFloat(Image *image,const float value)
5189 %
5190 % A description of each parameter follows.
5191 %
5192 % o image: the image.
5193 %
5194 % o value: Specifies the value to write.
5195 %
5196 */
5197 MagickExport ssize_t WriteBlobFloat(Image *image,const float value)
5198 {
5199  union
5200  {
5201  unsigned int
5202  unsigned_value;
5203 
5204  float
5205  float_value;
5206  } quantum;
5207 
5208  quantum.unsigned_value=0U;
5209  quantum.float_value=value;
5210  return(WriteBlobLong(image,quantum.unsigned_value));
5211 }
5212 
5213 /*
5214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5215 % %
5216 % %
5217 % %
5218 + W r i t e B l o b L o n g %
5219 % %
5220 % %
5221 % %
5222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5223 %
5224 % WriteBlobLong() writes a unsigned int value as a 32-bit quantity in the
5225 % byte-order specified by the endian member of the image structure.
5226 %
5227 % The format of the WriteBlobLong method is:
5228 %
5229 % ssize_t WriteBlobLong(Image *image,const unsigned int value)
5230 %
5231 % A description of each parameter follows.
5232 %
5233 % o image: the image.
5234 %
5235 % o value: Specifies the value to write.
5236 %
5237 */
5238 MagickExport ssize_t WriteBlobLong(Image *image,const unsigned int value)
5239 {
5240  unsigned char
5241  buffer[4];
5242 
5243  assert(image != (Image *) NULL);
5244  assert(image->signature == MagickCoreSignature);
5245  if (image->endian == LSBEndian)
5246  {
5247  buffer[0]=(unsigned char) value;
5248  buffer[1]=(unsigned char) (value >> 8);
5249  buffer[2]=(unsigned char) (value >> 16);
5250  buffer[3]=(unsigned char) (value >> 24);
5251  return(WriteBlobStream(image,4,buffer));
5252  }
5253  buffer[0]=(unsigned char) (value >> 24);
5254  buffer[1]=(unsigned char) (value >> 16);
5255  buffer[2]=(unsigned char) (value >> 8);
5256  buffer[3]=(unsigned char) value;
5257  return(WriteBlobStream(image,4,buffer));
5258 }
5259 
5260 /*
5261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5262 % %
5263 % %
5264 % %
5265 + W r i t e B l o b S h o r t %
5266 % %
5267 % %
5268 % %
5269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5270 %
5271 % WriteBlobShort() writes a short value as a 16-bit quantity in the
5272 % byte-order specified by the endian member of the image structure.
5273 %
5274 % The format of the WriteBlobShort method is:
5275 %
5276 % ssize_t WriteBlobShort(Image *image,const unsigned short value)
5277 %
5278 % A description of each parameter follows.
5279 %
5280 % o image: the image.
5281 %
5282 % o value: Specifies the value to write.
5283 %
5284 */
5285 MagickExport ssize_t WriteBlobShort(Image *image,const unsigned short value)
5286 {
5287  unsigned char
5288  buffer[2];
5289 
5290  assert(image != (Image *) NULL);
5291  assert(image->signature == MagickCoreSignature);
5292  if (image->endian == LSBEndian)
5293  {
5294  buffer[0]=(unsigned char) value;
5295  buffer[1]=(unsigned char) (value >> 8);
5296  return(WriteBlobStream(image,2,buffer));
5297  }
5298  buffer[0]=(unsigned char) (value >> 8);
5299  buffer[1]=(unsigned char) value;
5300  return(WriteBlobStream(image,2,buffer));
5301 }
5302 
5303 /*
5304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5305 % %
5306 % %
5307 % %
5308 + W r i t e B l o b L S B L o n g %
5309 % %
5310 % %
5311 % %
5312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5313 %
5314 % WriteBlobLSBLong() writes a unsigned int value as a 32-bit quantity in
5315 % least-significant byte first order.
5316 %
5317 % The format of the WriteBlobLSBLong method is:
5318 %
5319 % ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5320 %
5321 % A description of each parameter follows.
5322 %
5323 % o image: the image.
5324 %
5325 % o value: Specifies the value to write.
5326 %
5327 */
5328 MagickExport ssize_t WriteBlobLSBLong(Image *image,const unsigned int value)
5329 {
5330  unsigned char
5331  buffer[4];
5332 
5333  assert(image != (Image *) NULL);
5334  assert(image->signature == MagickCoreSignature);
5335  buffer[0]=(unsigned char) value;
5336  buffer[1]=(unsigned char) (value >> 8);
5337  buffer[2]=(unsigned char) (value >> 16);
5338  buffer[3]=(unsigned char) (value >> 24);
5339  return(WriteBlobStream(image,4,buffer));
5340 }
5341 
5342 /*
5343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5344 % %
5345 % %
5346 % %
5347 + W r i t e B l o b L S B S h o r t %
5348 % %
5349 % %
5350 % %
5351 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5352 %
5353 % WriteBlobLSBShort() writes a unsigned short value as a 16-bit quantity in
5354 % least-significant byte first order.
5355 %
5356 % The format of the WriteBlobLSBShort method is:
5357 %
5358 % ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5359 %
5360 % A description of each parameter follows.
5361 %
5362 % o image: the image.
5363 %
5364 % o value: Specifies the value to write.
5365 %
5366 */
5367 MagickExport ssize_t WriteBlobLSBShort(Image *image,const unsigned short value)
5368 {
5369  unsigned char
5370  buffer[2];
5371 
5372  assert(image != (Image *) NULL);
5373  assert(image->signature == MagickCoreSignature);
5374  buffer[0]=(unsigned char) value;
5375  buffer[1]=(unsigned char) (value >> 8);
5376  return(WriteBlobStream(image,2,buffer));
5377 }
5378 
5379 /*
5380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5381 % %
5382 % %
5383 % %
5384 + W r i t e B l o b L S B S i g n e d L o n g %
5385 % %
5386 % %
5387 % %
5388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5389 %
5390 % WriteBlobLSBSignedLong() writes a signed value as a 32-bit quantity in
5391 % least-significant byte first order.
5392 %
5393 % The format of the WriteBlobLSBSignedLong method is:
5394 %
5395 % ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5396 %
5397 % A description of each parameter follows.
5398 %
5399 % o image: the image.
5400 %
5401 % o value: Specifies the value to write.
5402 %
5403 */
5404 MagickExport ssize_t WriteBlobLSBSignedLong(Image *image,const signed int value)
5405 {
5406  union
5407  {
5408  unsigned int
5409  unsigned_value;
5410 
5411  signed int
5412  signed_value;
5413  } quantum;
5414 
5415  unsigned char
5416  buffer[4];
5417 
5418  assert(image != (Image *) NULL);
5419  assert(image->signature == MagickCoreSignature);
5420  quantum.signed_value=value;
5421  buffer[0]=(unsigned char) quantum.unsigned_value;
5422  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5423  buffer[2]=(unsigned char) (quantum.unsigned_value >> 16);
5424  buffer[3]=(unsigned char) (quantum.unsigned_value >> 24);
5425  return(WriteBlobStream(image,4,buffer));
5426 }
5427 
5428 /*
5429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5430 % %
5431 % %
5432 % %
5433 + W r i t e B l o b L S B S i g n e d S h o r t %
5434 % %
5435 % %
5436 % %
5437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5438 %
5439 % WriteBlobLSBSignedShort() writes a signed short value as a 16-bit quantity
5440 % in least-significant byte first order.
5441 %
5442 % The format of the WriteBlobLSBSignedShort method is:
5443 %
5444 % ssize_t WriteBlobLSBSignedShort(Image *image,const signed short value)
5445 %
5446 % A description of each parameter follows.
5447 %
5448 % o image: the image.
5449 %
5450 % o value: Specifies the value to write.
5451 %
5452 */
5453 MagickExport ssize_t WriteBlobLSBSignedShort(Image *image,
5454  const signed short value)
5455 {
5456  union
5457  {
5458  unsigned short
5459  unsigned_value;
5460 
5461  signed short
5462  signed_value;
5463  } quantum;
5464 
5465  unsigned char
5466  buffer[2];
5467 
5468  assert(image != (Image *) NULL);
5469  assert(image->signature == MagickCoreSignature);
5470  quantum.signed_value=value;
5471  buffer[0]=(unsigned char) quantum.unsigned_value;
5472  buffer[1]=(unsigned char) (quantum.unsigned_value >> 8);
5473  return(WriteBlobStream(image,2,buffer));
5474 }
5475 
5476 /*
5477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5478 % %
5479 % %
5480 % %
5481 + W r i t e B l o b M S B L o n g %
5482 % %
5483 % %
5484 % %
5485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5486 %
5487 % WriteBlobMSBLong() writes a unsigned int value as a 32-bit quantity in
5488 % most-significant byte first order.
5489 %
5490 % The format of the WriteBlobMSBLong method is:
5491 %
5492 % ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5493 %
5494 % A description of each parameter follows.
5495 %
5496 % o value: Specifies the value to write.
5497 %
5498 % o image: the image.
5499 %
5500 */
5501 MagickExport ssize_t WriteBlobMSBLong(Image *image,const unsigned int value)
5502 {
5503  unsigned char
5504  buffer[4];
5505 
5506  assert(image != (Image *) NULL);
5507  assert(image->signature == MagickCoreSignature);
5508  buffer[0]=(unsigned char) (value >> 24);
5509  buffer[1]=(unsigned char) (value >> 16);
5510  buffer[2]=(unsigned char) (value >> 8);
5511  buffer[3]=(unsigned char) value;
5512  return(WriteBlobStream(image,4,buffer));
5513 }
5514 
5515 /*
5516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5517 % %
5518 % %
5519 % %
5520 + W r i t e B l o b M S B L o n g L o n g %
5521 % %
5522 % %
5523 % %
5524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5525 %
5526 % WriteBlobMSBLongLong() writes a long long value as a 64-bit quantity in
5527 % most-significant byte first order.
5528 %
5529 % The format of the WriteBlobMSBLongLong method is:
5530 %
5531 % ssize_t WriteBlobMSBLongLong(Image *image,const MagickSizeType value)
5532 %
5533 % A description of each parameter follows.
5534 %
5535 % o value: Specifies the value to write.
5536 %
5537 % o image: the image.
5538 %
5539 */
5540 MagickExport ssize_t WriteBlobMSBLongLong(Image *image,
5541  const MagickSizeType value)
5542 {
5543  unsigned char
5544  buffer[8];
5545 
5546  assert(image != (Image *) NULL);
5547  assert(image->signature == MagickCoreSignature);
5548  buffer[0]=(unsigned char) (value >> 56);
5549  buffer[1]=(unsigned char) (value >> 48);
5550  buffer[2]=(unsigned char) (value >> 40);
5551  buffer[3]=(unsigned char) (value >> 32);
5552  buffer[4]=(unsigned char) (value >> 24);
5553  buffer[5]=(unsigned char) (value >> 16);
5554  buffer[6]=(unsigned char) (value >> 8);
5555  buffer[7]=(unsigned char) value;
5556  return(WriteBlobStream(image,8,buffer));
5557 }
5558 
5559 /*
5560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5561 % %
5562 % %
5563 % %
5564 + W r i t e B l o b M S B S h o r t %
5565 % %
5566 % %
5567 % %
5568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5569 %
5570 % WriteBlobMSBShort() writes a unsigned short value as a 16-bit quantity in
5571 % most-significant byte first order.
5572 %
5573 % The format of the WriteBlobMSBShort method is:
5574 %
5575 % ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5576 %
5577 % A description of each parameter follows.
5578 %
5579 % o value: Specifies the value to write.
5580 %
5581 % o file: Specifies the file to write the data to.
5582 %
5583 */
5584 MagickExport ssize_t WriteBlobMSBShort(Image *image,const unsigned short value)
5585 {
5586  unsigned char
5587  buffer[2];
5588 
5589  assert(image != (Image *) NULL);
5590  assert(image->signature == MagickCoreSignature);
5591  buffer[0]=(unsigned char) (value >> 8);
5592  buffer[1]=(unsigned char) value;
5593  return(WriteBlobStream(image,2,buffer));
5594 }
5595 
5596 /*
5597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5598 % %
5599 % %
5600 % %
5601 + W r i t e B l o b M S B S i g n e d L o n g %
5602 % %
5603 % %
5604 % %
5605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5606 %
5607 % WriteBlobMSBSignedLong() writes a signed value as a 32-bit quantity in
5608 % most-significant byte first order.
5609 %
5610 % The format of the WriteBlobMSBSignedLong method is:
5611 %
5612 % ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5613 %
5614 % A description of each parameter follows.
5615 %
5616 % o image: the image.
5617 %
5618 % o value: Specifies the value to write.
5619 %
5620 */
5621 MagickExport ssize_t WriteBlobMSBSignedLong(Image *image,const signed int value)
5622 {
5623  union
5624  {
5625  unsigned int
5626  unsigned_value;
5627 
5628  signed int
5629  signed_value;
5630  } quantum;
5631 
5632  unsigned char
5633  buffer[4];
5634 
5635  assert(image != (Image *) NULL);
5636  assert(image->signature == MagickCoreSignature);
5637  quantum.signed_value=value;
5638  buffer[0]=(unsigned char) (quantum.unsigned_value >> 24);
5639  buffer[1]=(unsigned char) (quantum.unsigned_value >> 16);
5640  buffer[2]=(unsigned char) (quantum.unsigned_value >> 8);
5641  buffer[3]=(unsigned char) quantum.unsigned_value;
5642  return(WriteBlobStream(image,4,buffer));
5643 }
5644 
5645 /*
5646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5647 % %
5648 % %
5649 % %
5650 + W r i t e B l o b M S B S i g n e d S h o r t %
5651 % %
5652 % %
5653 % %
5654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5655 %
5656 % WriteBlobMSBSignedShort() writes a signed short value as a 16-bit quantity
5657 % in most-significant byte first order.
5658 %
5659 % The format of the WriteBlobMSBSignedShort method is:
5660 %
5661 % ssize_t WriteBlobMSBSignedShort(Image *image,const signed short value)
5662 %
5663 % A description of each parameter follows.
5664 %
5665 % o image: the image.
5666 %
5667 % o value: Specifies the value to write.
5668 %
5669 */
5670 MagickExport ssize_t WriteBlobMSBSignedShort(Image *image,
5671  const signed short value)
5672 {
5673  union
5674  {
5675  unsigned short
5676  unsigned_value;
5677 
5678  signed short
5679  signed_value;
5680  } quantum;
5681 
5682  unsigned char
5683  buffer[2];
5684 
5685  assert(image != (Image *) NULL);
5686  assert(image->signature == MagickCoreSignature);
5687  quantum.signed_value=value;
5688  buffer[0]=(unsigned char) (quantum.unsigned_value >> 8);
5689  buffer[1]=(unsigned char) quantum.unsigned_value;
5690  return(WriteBlobStream(image,2,buffer));
5691 }
5692 
5693 /*
5694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5695 % %
5696 % %
5697 % %
5698 + W r i t e B l o b S t r i n g %
5699 % %
5700 % %
5701 % %
5702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5703 %
5704 % WriteBlobString() write a string to a blob. It returns the number of
5705 % characters written.
5706 %
5707 % The format of the WriteBlobString method is:
5708 %
5709 % ssize_t WriteBlobString(Image *image,const char *string)
5710 %
5711 % A description of each parameter follows.
5712 %
5713 % o image: the image.
5714 %
5715 % o string: Specifies the string to write.
5716 %
5717 */
5718 MagickExport ssize_t WriteBlobString(Image *image,const char *string)
5719 {
5720  assert(image != (Image *) NULL);
5721  assert(image->signature == MagickCoreSignature);
5722  assert(string != (const char *) NULL);
5723  return(WriteBlobStream(image,strlen(string),(const unsigned char *) string));
5724 }
Definition: image.h:152
Definition: blob.c:99