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