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