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