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