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