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