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