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