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