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