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