1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % DDDD PPPP X X % 7 % D D P P X X % 8 % D D PPPP XXX % 9 % D D P X X % 10 % DDDD P X X % 11 % % 12 % % 13 % Read/Write SMTPE DPX Image Format % 14 % % 15 % Software Design % 16 % Cristy % 17 % March 2001 % 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 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/attribute.h" 45 #include "MagickCore/artifact.h" 46 #include "MagickCore/blob.h" 47 #include "MagickCore/blob-private.h" 48 #include "MagickCore/cache.h" 49 #include "MagickCore/colorspace.h" 50 #include "MagickCore/exception.h" 51 #include "MagickCore/exception-private.h" 52 #include "MagickCore/geometry.h" 53 #include "MagickCore/image.h" 54 #include "MagickCore/image-private.h" 55 #include "MagickCore/list.h" 56 #include "MagickCore/magick.h" 57 #include "MagickCore/memory_.h" 58 #include "MagickCore/module.h" 59 #include "MagickCore/monitor.h" 60 #include "MagickCore/monitor-private.h" 61 #include "MagickCore/option.h" 62 #include "MagickCore/pixel-accessor.h" 63 #include "MagickCore/profile.h" 64 #include "MagickCore/property.h" 65 #include "MagickCore/quantum-private.h" 66 #include "MagickCore/static.h" 67 #include "MagickCore/string_.h" 68 #include "MagickCore/string-private.h" 69 70 /* 72 Define declaration. 73 */ 74 #define MaxNumberImageElements 8 75 76 /* 78 Typedef declaration. 79 */ 80 typedef enum 81 { 82 UserDefinedColorimetric = 0, 83 PrintingDensityColorimetric = 1, 84 LinearColorimetric = 2, 85 LogarithmicColorimetric = 3, 86 UnspecifiedVideoColorimetric = 4, 87 SMTPE_274MColorimetric = 5, 88 ITU_R709Colorimetric = 6, 89 ITU_R601_625LColorimetric = 7, 90 ITU_R601_525LColorimetric = 8, 91 NTSCCompositeVideoColorimetric = 9, 92 PALCompositeVideoColorimetric = 10, 93 ZDepthLinearColorimetric = 11, 94 DepthHomogeneousColorimetric = 12 95 } DPXColorimetric; 96 97 typedef enum 98 { 99 UndefinedComponentType = 0, 100 RedComponentType = 1, 101 GreenComponentType = 2, 102 BlueComponentType = 3, 103 AlphaComponentType = 4, 104 LumaComponentType = 6, 105 ColorDifferenceCbCrComponentType = 7, 106 DepthComponentType = 8, 107 CompositeVideoComponentType = 9, 108 RGBComponentType = 50, 109 RGBAComponentType = 51, 110 ABGRComponentType = 52, 111 CbYCrY422ComponentType = 100, 112 CbYACrYA4224ComponentType = 101, 113 CbYCr444ComponentType = 102, 114 CbYCrA4444ComponentType = 103, 115 UserDef2ElementComponentType = 150, 116 UserDef3ElementComponentType = 151, 117 UserDef4ElementComponentType = 152, 118 UserDef5ElementComponentType = 153, 119 UserDef6ElementComponentType = 154, 120 UserDef7ElementComponentType = 155, 121 UserDef8ElementComponentType = 156 122 } DPXComponentType; 123 124 typedef enum 125 { 126 TransferCharacteristicUserDefined = 0, 127 TransferCharacteristicPrintingDensity = 1, 128 TransferCharacteristicLinear = 2, 129 TransferCharacteristicLogarithmic = 3, 130 TransferCharacteristicUnspecifiedVideo = 4, 131 TransferCharacteristicSMTPE274M = 5, /* 1920x1080 TV */ 132 TransferCharacteristicITU_R709 = 6, /* ITU R709 */ 133 TransferCharacteristicITU_R601_625L = 7, /* 625 Line */ 134 TransferCharacteristicITU_R601_525L = 8, /* 525 Line */ 135 TransferCharacteristicNTSCCompositeVideo = 9, 136 TransferCharacteristicPALCompositeVideo = 10, 137 TransferCharacteristicZDepthLinear = 11, 138 TransferCharacteristicZDepthHomogeneous = 12 139 } DPXTransferCharacteristic; 140 141 typedef struct _DPXFileInfo 142 { 143 unsigned int 144 magic, 145 image_offset; 146 147 char 148 version[8]; 149 150 unsigned int 151 file_size, 152 ditto_key, 153 generic_size, 154 industry_size, 155 user_size; 156 157 char 158 filename[100], 159 timestamp[24], 160 creator[100], 161 project[200], 162 copyright[200]; 163 164 unsigned int 165 encrypt_key; 166 167 char 168 reserve[104]; 169 } DPXFileInfo; 170 171 typedef struct _DPXFilmInfo 172 { 173 char 174 id[2], 175 type[2], 176 offset[2], 177 prefix[6], 178 count[4], 179 format[32]; 180 181 unsigned int 182 frame_position, 183 sequence_extent, 184 held_count; 185 186 float 187 frame_rate, 188 shutter_angle; 189 190 char 191 frame_id[32], 192 slate[100], 193 reserve[56]; 194 } DPXFilmInfo; 195 196 typedef struct _DPXImageElement 197 { 198 unsigned int 199 data_sign, 200 low_data; 201 202 float 203 low_quantity; 204 205 unsigned int 206 high_data; 207 208 float 209 high_quantity; 210 211 unsigned char 212 descriptor, 213 transfer_characteristic, 214 colorimetric, 215 bit_size; 216 217 unsigned short 218 packing, 219 encoding; 220 221 unsigned int 222 data_offset, 223 end_of_line_padding, 224 end_of_image_padding; 225 226 unsigned char 227 description[32]; 228 } DPXImageElement; 229 230 typedef struct _DPXImageInfo 231 { 232 unsigned short 233 orientation, 234 number_elements; 235 236 unsigned int 237 pixels_per_line, 238 lines_per_element; 239 240 DPXImageElement 241 image_element[MaxNumberImageElements]; 242 243 unsigned char 244 reserve[52]; 245 } DPXImageInfo; 246 247 typedef struct _DPXOrientationInfo 248 { 249 unsigned int 250 x_offset, 251 y_offset; 252 253 float 254 x_center, 255 y_center; 256 257 unsigned int 258 x_size, 259 y_size; 260 261 char 262 filename[100], 263 timestamp[24], 264 device[32], 265 serial[32]; 266 267 unsigned short 268 border[4]; 269 270 unsigned int 271 aspect_ratio[2]; 272 273 unsigned char 274 reserve[28]; 275 } DPXOrientationInfo; 276 277 typedef struct _DPXTelevisionInfo 278 { 279 unsigned int 280 time_code, 281 user_bits; 282 283 unsigned char 284 interlace, 285 field_number, 286 video_signal, 287 padding; 288 289 float 290 horizontal_sample_rate, 291 vertical_sample_rate, 292 frame_rate, 293 time_offset, 294 gamma, 295 black_level, 296 black_gain, 297 break_point, 298 white_level, 299 integration_times; 300 301 char 302 reserve[76]; 303 } DPXTelevisionInfo; 304 305 typedef struct _DPXUserInfo 306 { 307 char 308 id[32]; 309 } DPXUserInfo; 310 311 typedef struct DPXInfo 312 { 313 DPXFileInfo 314 file; 315 316 DPXImageInfo 317 image; 318 319 DPXOrientationInfo 320 orientation; 321 322 DPXFilmInfo 323 film; 324 325 DPXTelevisionInfo 326 television; 327 328 DPXUserInfo 329 user; 330 } DPXInfo; 331 332 /* 334 Forward declaractions. 335 */ 336 static MagickBooleanType 337 WriteDPXImage(const ImageInfo *,Image *,ExceptionInfo *); 338 339 /* 341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 342 % % 343 % % 344 % % 345 % I s D P X % 346 % % 347 % % 348 % % 349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 350 % 351 % IsDPX() returns MagickTrue if the image format type, identified by the 352 % magick string, is DPX. 353 % 354 % The format of the IsDPX method is: 355 % 356 % MagickBooleanType IsDPX(const unsigned char *magick,const size_t extent) 357 % 358 % A description of each parameter follows: 359 % 360 % o magick: compare image format pattern against these bytes. 361 % 362 % o extent: Specifies the extent of the magick string. 363 % 364 */ 365 static MagickBooleanType IsDPX(const unsigned char *magick,const size_t extent) 366 { 367 if (extent < 4) 368 return(MagickFalse); 369 if (memcmp(magick,"SDPX",4) == 0) 370 return(MagickTrue); 371 if (memcmp(magick,"XPDS",4) == 0) 372 return(MagickTrue); 373 return(MagickFalse); 374 } 375 376 /* 378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 379 % % 380 % % 381 % % 382 % R e a d D P X I m a g e % 383 % % 384 % % 385 % % 386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 387 % 388 % ReadDPXImage() reads an DPX X image file and returns it. It 389 % allocates the memory necessary for the new Image structure and returns a 390 % pointer to the new image. 391 % 392 % The format of the ReadDPXImage method is: 393 % 394 % Image *ReadDPXImage(const ImageInfo *image_info,ExceptionInfo *exception) 395 % 396 % A description of each parameter follows: 397 % 398 % o image_info: the image info. 399 % 400 % o exception: return any errors or warnings in this structure. 401 % 402 */ 403 404 static size_t GetBytesPerRow(const size_t columns, 405 const size_t samples_per_pixel,const size_t bits_per_pixel, 406 const MagickBooleanType pad) 407 { 408 size_t 409 bytes_per_row; 410 411 switch (bits_per_pixel) 412 { 413 case 1: 414 { 415 bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ 416 32); 417 break; 418 } 419 case 8: 420 default: 421 { 422 bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ 423 32); 424 break; 425 } 426 case 10: 427 { 428 if (pad == MagickFalse) 429 { 430 bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+ 431 31)/32); 432 break; 433 } 434 bytes_per_row=4*(((size_t) (32*((samples_per_pixel*columns+2)/3))+31)/32); 435 break; 436 } 437 case 12: 438 { 439 if (pad == MagickFalse) 440 { 441 bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+ 442 31)/32); 443 break; 444 } 445 bytes_per_row=2*(((size_t) (16*samples_per_pixel*columns)+15)/16); 446 break; 447 } 448 case 16: 449 { 450 if (pad == MagickFalse) 451 { 452 bytes_per_row=2*(((size_t) samples_per_pixel*columns*bits_per_pixel+ 453 15)/16); 454 break; 455 } 456 bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ 457 32); 458 break; 459 } 460 case 32: 461 { 462 bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ 463 32); 464 break; 465 } 466 case 64: 467 { 468 bytes_per_row=8*(((size_t) samples_per_pixel*columns*bits_per_pixel+63)/ 469 64); 470 break; 471 } 472 } 473 return(bytes_per_row); 474 } 475 476 static const char *GetImageTransferCharacteristic( 477 const DPXTransferCharacteristic characteristic) 478 { 479 const char 480 *transfer; 481 482 /* 483 Get the element transfer characteristic. 484 */ 485 switch(characteristic) 486 { 487 case TransferCharacteristicUserDefined: 488 { 489 transfer="UserDefined"; 490 break; 491 } 492 case TransferCharacteristicPrintingDensity: 493 { 494 transfer="PrintingDensity"; 495 break; 496 } 497 case TransferCharacteristicLinear: 498 { 499 transfer="Linear"; 500 break; 501 } 502 case TransferCharacteristicLogarithmic: 503 { 504 transfer="Logarithmic"; 505 break; 506 } 507 case TransferCharacteristicUnspecifiedVideo: 508 { 509 transfer="UnspecifiedVideo"; 510 break; 511 } 512 case TransferCharacteristicSMTPE274M: 513 { 514 transfer="SMTPE274M"; 515 break; 516 } 517 case TransferCharacteristicITU_R709: 518 { 519 transfer="ITU-R709"; 520 break; 521 } 522 case TransferCharacteristicITU_R601_625L: 523 { 524 transfer="ITU-R601-625L"; 525 break; 526 } 527 case TransferCharacteristicITU_R601_525L: 528 { 529 transfer="ITU-R601-525L"; 530 break; 531 } 532 case TransferCharacteristicNTSCCompositeVideo: 533 { 534 transfer="NTSCCompositeVideo"; 535 break; 536 } 537 case TransferCharacteristicPALCompositeVideo: 538 { 539 transfer="PALCompositeVideo"; 540 break; 541 } 542 case TransferCharacteristicZDepthLinear: 543 { 544 transfer="ZDepthLinear"; 545 break; 546 } 547 case TransferCharacteristicZDepthHomogeneous: 548 { 549 transfer="ZDepthHomogeneous"; 550 break; 551 } 552 default: 553 transfer="Reserved"; 554 } 555 return(transfer); 556 } 557 558 static inline MagickBooleanType IsFloatDefined(const float value) 559 { 560 union 561 { 562 unsigned int 563 unsigned_value; 564 565 float 566 float_value; 567 } quantum; 568 569 quantum.unsigned_value=0U; 570 quantum.float_value=(float) value; 571 if (quantum.unsigned_value == 0U) 572 return(MagickFalse); 573 return(MagickTrue); 574 } 575 576 static void SetPrimaryChromaticity(const DPXColorimetric colorimetric, 577 ChromaticityInfo *chromaticity_info) 578 { 579 switch(colorimetric) 580 { 581 case SMTPE_274MColorimetric: 582 case ITU_R709Colorimetric: 583 { 584 chromaticity_info->red_primary.x=0.640; 585 chromaticity_info->red_primary.y=0.330; 586 chromaticity_info->red_primary.z=0.030; 587 chromaticity_info->green_primary.x=0.300; 588 chromaticity_info->green_primary.y=0.600; 589 chromaticity_info->green_primary.z=0.100; 590 chromaticity_info->blue_primary.x=0.150; 591 chromaticity_info->blue_primary.y=0.060; 592 chromaticity_info->blue_primary.z=0.790; 593 chromaticity_info->white_point.x=0.3127; 594 chromaticity_info->white_point.y=0.3290; 595 chromaticity_info->white_point.z=0.3582; 596 break; 597 } 598 case NTSCCompositeVideoColorimetric: 599 { 600 chromaticity_info->red_primary.x=0.67; 601 chromaticity_info->red_primary.y=0.33; 602 chromaticity_info->red_primary.z=0.00; 603 chromaticity_info->green_primary.x=0.21; 604 chromaticity_info->green_primary.y=0.71; 605 chromaticity_info->green_primary.z=0.08; 606 chromaticity_info->blue_primary.x=0.14; 607 chromaticity_info->blue_primary.y=0.08; 608 chromaticity_info->blue_primary.z=0.78; 609 chromaticity_info->white_point.x=0.310; 610 chromaticity_info->white_point.y=0.316; 611 chromaticity_info->white_point.z=0.374; 612 break; 613 } 614 case PALCompositeVideoColorimetric: 615 { 616 chromaticity_info->red_primary.x=0.640; 617 chromaticity_info->red_primary.y=0.330; 618 chromaticity_info->red_primary.z=0.030; 619 chromaticity_info->green_primary.x=0.290; 620 chromaticity_info->green_primary.y=0.600; 621 chromaticity_info->green_primary.z=0.110; 622 chromaticity_info->blue_primary.x=0.150; 623 chromaticity_info->blue_primary.y=0.060; 624 chromaticity_info->blue_primary.z=0.790; 625 chromaticity_info->white_point.x=0.3127; 626 chromaticity_info->white_point.y=0.3290; 627 chromaticity_info->white_point.z=0.3582; 628 break; 629 } 630 default: 631 break; 632 } 633 } 634 635 static void TimeCodeToString(const size_t timestamp,char *code) 636 { 637 #define TimeFields 7 638 639 unsigned int 640 shift; 641 642 register ssize_t 643 i; 644 645 *code='\0'; 646 shift=4*TimeFields; 647 for (i=0; i <= TimeFields; i++) 648 { 649 (void) FormatLocaleString(code,MagickPathExtent-strlen(code),"%x", 650 (unsigned int) ((timestamp >> shift) & 0x0fU)); 651 code++; 652 if (((i % 2) != 0) && (i < TimeFields)) 653 *code++=':'; 654 shift-=4; 655 *code='\0'; 656 } 657 } 658 659 static Image *ReadDPXImage(const ImageInfo *image_info,ExceptionInfo *exception) 660 { 661 char 662 magick[4], 663 value[MagickPathExtent]; 664 665 DPXInfo 666 dpx; 667 668 Image 669 *image; 670 671 MagickBooleanType 672 status; 673 674 MagickOffsetType 675 offset; 676 677 QuantumInfo 678 *quantum_info; 679 680 QuantumType 681 quantum_type; 682 683 register ssize_t 684 i; 685 686 size_t 687 extent, 688 samples_per_pixel; 689 690 ssize_t 691 count, 692 n, 693 row, 694 y; 695 696 unsigned char 697 component_type; 698 699 /* 700 Open image file. 701 */ 702 assert(image_info != (const ImageInfo *) NULL); 703 assert(image_info->signature == MagickCoreSignature); 704 if (image_info->debug != MagickFalse) 705 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 706 image_info->filename); 707 assert(exception != (ExceptionInfo *) NULL); 708 assert(exception->signature == MagickCoreSignature); 709 image=AcquireImage(image_info,exception); 710 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 711 if (status == MagickFalse) 712 { 713 image=DestroyImageList(image); 714 return((Image *) NULL); 715 } 716 /* 717 Read DPX file header. 718 */ 719 offset=0; 720 count=ReadBlob(image,4,(unsigned char *) magick); 721 offset+=count; 722 if ((count != 4) || ((LocaleNCompare(magick,"SDPX",4) != 0) && 723 (LocaleNCompare((char *) magick,"XPDS",4) != 0))) 724 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 725 image->endian=LSBEndian; 726 if (LocaleNCompare(magick,"SDPX",4) == 0) 727 image->endian=MSBEndian; 728 (void) memset(&dpx,0,sizeof(dpx)); 729 dpx.file.image_offset=ReadBlobLong(image); 730 offset+=4; 731 offset+=ReadBlob(image,sizeof(dpx.file.version),(unsigned char *) 732 dpx.file.version); 733 (void) FormatImageProperty(image,"dpx:file.version","%.8s",dpx.file.version); 734 dpx.file.file_size=ReadBlobLong(image); 735 if (0 && dpx.file.file_size > GetBlobSize(image)) 736 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 737 offset+=4; 738 dpx.file.ditto_key=ReadBlobLong(image); 739 offset+=4; 740 if (dpx.file.ditto_key != ~0U) 741 (void) FormatImageProperty(image,"dpx:file.ditto.key","%u", 742 dpx.file.ditto_key); 743 dpx.file.generic_size=ReadBlobLong(image); 744 if (0 && dpx.file.generic_size > GetBlobSize(image)) 745 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 746 offset+=4; 747 dpx.file.industry_size=ReadBlobLong(image); 748 if (dpx.file.industry_size > GetBlobSize(image)) 749 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 750 offset+=4; 751 dpx.file.user_size=ReadBlobLong(image); 752 if (0 && dpx.file.user_size > GetBlobSize(image)) 753 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 754 offset+=4; 755 offset+=ReadBlob(image,sizeof(dpx.file.filename),(unsigned char *) 756 dpx.file.filename); 757 (void) FormatImageProperty(image,"dpx:file.filename","%.100s", 758 dpx.file.filename); 759 (void) FormatImageProperty(image,"document","%.100s",dpx.file.filename); 760 offset+=ReadBlob(image,sizeof(dpx.file.timestamp),(unsigned char *) 761 dpx.file.timestamp); 762 if (*dpx.file.timestamp != '\0') 763 (void) FormatImageProperty(image,"dpx:file.timestamp","%.24s", 764 dpx.file.timestamp); 765 offset+=ReadBlob(image,sizeof(dpx.file.creator),(unsigned char *) 766 dpx.file.creator); 767 if (*dpx.file.creator != '\0') 768 { 769 (void) FormatImageProperty(image,"dpx:file.creator","%.100s", 770 dpx.file.creator); 771 (void) FormatImageProperty(image,"software","%.100s",dpx.file.creator); 772 } 773 offset+=ReadBlob(image,sizeof(dpx.file.project),(unsigned char *) 774 dpx.file.project); 775 if (*dpx.file.project != '\0') 776 { 777 (void) FormatImageProperty(image,"dpx:file.project","%.200s", 778 dpx.file.project); 779 (void) FormatImageProperty(image,"comment","%.100s",dpx.file.project); 780 } 781 offset+=ReadBlob(image,sizeof(dpx.file.copyright),(unsigned char *) 782 dpx.file.copyright); 783 if (*dpx.file.copyright != '\0') 784 { 785 (void) FormatImageProperty(image,"dpx:file.copyright","%.200s", 786 dpx.file.copyright); 787 (void) FormatImageProperty(image,"copyright","%.100s", 788 dpx.file.copyright); 789 } 790 dpx.file.encrypt_key=ReadBlobLong(image); 791 offset+=4; 792 if (dpx.file.encrypt_key != ~0U) 793 (void) FormatImageProperty(image,"dpx:file.encrypt_key","%u", 794 dpx.file.encrypt_key); 795 offset+=ReadBlob(image,sizeof(dpx.file.reserve),(unsigned char *) 796 dpx.file.reserve); 797 /* 798 Read DPX image header. 799 */ 800 dpx.image.orientation=ReadBlobShort(image); 801 if (dpx.image.orientation > 7) 802 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 803 offset+=2; 804 if (dpx.image.orientation != (unsigned short) ~0) 805 (void) FormatImageProperty(image,"dpx:image.orientation","%d", 806 dpx.image.orientation); 807 switch (dpx.image.orientation) 808 { 809 default: 810 case 0: image->orientation=TopLeftOrientation; break; 811 case 1: image->orientation=TopRightOrientation; break; 812 case 2: image->orientation=BottomLeftOrientation; break; 813 case 3: image->orientation=BottomRightOrientation; break; 814 case 4: image->orientation=LeftTopOrientation; break; 815 case 5: image->orientation=RightTopOrientation; break; 816 case 6: image->orientation=LeftBottomOrientation; break; 817 case 7: image->orientation=RightBottomOrientation; break; 818 } 819 dpx.image.number_elements=ReadBlobShort(image); 820 if ((dpx.image.number_elements < 1) || 821 (dpx.image.number_elements > MaxNumberImageElements)) 822 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 823 offset+=2; 824 dpx.image.pixels_per_line=ReadBlobLong(image); 825 offset+=4; 826 image->columns=dpx.image.pixels_per_line; 827 dpx.image.lines_per_element=ReadBlobLong(image); 828 offset+=4; 829 image->rows=dpx.image.lines_per_element; 830 for (i=0; i < 8; i++) 831 { 832 char 833 property[MagickPathExtent]; 834 835 dpx.image.image_element[i].data_sign=ReadBlobLong(image); 836 offset+=4; 837 dpx.image.image_element[i].low_data=ReadBlobLong(image); 838 offset+=4; 839 dpx.image.image_element[i].low_quantity=ReadBlobFloat(image); 840 offset+=4; 841 dpx.image.image_element[i].high_data=ReadBlobLong(image); 842 offset+=4; 843 dpx.image.image_element[i].high_quantity=ReadBlobFloat(image); 844 offset+=4; 845 dpx.image.image_element[i].descriptor=(unsigned char) ReadBlobByte(image); 846 offset++; 847 dpx.image.image_element[i].transfer_characteristic=(unsigned char) 848 ReadBlobByte(image); 849 (void) FormatLocaleString(property,MagickPathExtent, 850 "dpx:image.element[%lu].transfer-characteristic",(long) i); 851 (void) FormatImageProperty(image,property,"%s", 852 GetImageTransferCharacteristic((DPXTransferCharacteristic) 853 dpx.image.image_element[i].transfer_characteristic)); 854 offset++; 855 dpx.image.image_element[i].colorimetric=(unsigned char) ReadBlobByte(image); 856 offset++; 857 dpx.image.image_element[i].bit_size=(unsigned char) ReadBlobByte(image); 858 offset++; 859 dpx.image.image_element[i].packing=ReadBlobShort(image); 860 if (dpx.image.image_element[i].packing > 2) 861 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 862 offset+=2; 863 dpx.image.image_element[i].encoding=ReadBlobShort(image); 864 offset+=2; 865 dpx.image.image_element[i].data_offset=ReadBlobLong(image); 866 offset+=4; 867 dpx.image.image_element[i].end_of_line_padding=ReadBlobLong(image); 868 offset+=4; 869 dpx.image.image_element[i].end_of_image_padding=ReadBlobLong(image); 870 offset+=4; 871 offset+=ReadBlob(image,sizeof(dpx.image.image_element[i].description), 872 (unsigned char *) dpx.image.image_element[i].description); 873 } 874 SetImageColorspace(image,RGBColorspace,exception); 875 offset+=ReadBlob(image,sizeof(dpx.image.reserve),(unsigned char *) 876 dpx.image.reserve); 877 if (dpx.file.image_offset >= 1664U) 878 { 879 /* 880 Read DPX orientation header. 881 */ 882 dpx.orientation.x_offset=ReadBlobLong(image); 883 offset+=4; 884 if (dpx.orientation.x_offset != ~0U) 885 (void) FormatImageProperty(image,"dpx:orientation.x_offset","%u", 886 dpx.orientation.x_offset); 887 dpx.orientation.y_offset=ReadBlobLong(image); 888 offset+=4; 889 if (dpx.orientation.y_offset != ~0U) 890 (void) FormatImageProperty(image,"dpx:orientation.y_offset","%u", 891 dpx.orientation.y_offset); 892 dpx.orientation.x_center=ReadBlobFloat(image); 893 offset+=4; 894 if (IsFloatDefined(dpx.orientation.x_center) != MagickFalse) 895 (void) FormatImageProperty(image,"dpx:orientation.x_center","%g", 896 dpx.orientation.x_center); 897 dpx.orientation.y_center=ReadBlobFloat(image); 898 offset+=4; 899 if (IsFloatDefined(dpx.orientation.y_center) != MagickFalse) 900 (void) FormatImageProperty(image,"dpx:orientation.y_center","%g", 901 dpx.orientation.y_center); 902 dpx.orientation.x_size=ReadBlobLong(image); 903 offset+=4; 904 if (dpx.orientation.x_size != ~0U) 905 (void) FormatImageProperty(image,"dpx:orientation.x_size","%u", 906 dpx.orientation.x_size); 907 dpx.orientation.y_size=ReadBlobLong(image); 908 offset+=4; 909 if (dpx.orientation.y_size != ~0U) 910 (void) FormatImageProperty(image,"dpx:orientation.y_size","%u", 911 dpx.orientation.y_size); 912 offset+=ReadBlob(image,sizeof(dpx.orientation.filename),(unsigned char *) 913 dpx.orientation.filename); 914 if (*dpx.orientation.filename != '\0') 915 (void) FormatImageProperty(image,"dpx:orientation.filename","%.100s", 916 dpx.orientation.filename); 917 offset+=ReadBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *) 918 dpx.orientation.timestamp); 919 if (*dpx.orientation.timestamp != '\0') 920 (void) FormatImageProperty(image,"dpx:orientation.timestamp","%.24s", 921 dpx.orientation.timestamp); 922 offset+=ReadBlob(image,sizeof(dpx.orientation.device),(unsigned char *) 923 dpx.orientation.device); 924 if (*dpx.orientation.device != '\0') 925 (void) FormatImageProperty(image,"dpx:orientation.device","%.32s", 926 dpx.orientation.device); 927 offset+=ReadBlob(image,sizeof(dpx.orientation.serial),(unsigned char *) 928 dpx.orientation.serial); 929 if (*dpx.orientation.serial != '\0') 930 (void) FormatImageProperty(image,"dpx:orientation.serial","%.32s", 931 dpx.orientation.serial); 932 for (i=0; i < 4; i++) 933 { 934 dpx.orientation.border[i]=ReadBlobShort(image); 935 offset+=2; 936 } 937 if ((dpx.orientation.border[0] != (unsigned short) (~0)) && 938 (dpx.orientation.border[1] != (unsigned short) (~0))) 939 (void) FormatImageProperty(image,"dpx:orientation.border","%dx%d%+d%+d", 940 dpx.orientation.border[0],dpx.orientation.border[1], 941 dpx.orientation.border[2],dpx.orientation.border[3]); 942 for (i=0; i < 2; i++) 943 { 944 dpx.orientation.aspect_ratio[i]=ReadBlobLong(image); 945 offset+=4; 946 } 947 if ((dpx.orientation.aspect_ratio[0] != ~0U) && 948 (dpx.orientation.aspect_ratio[1] != ~0U)) 949 (void) FormatImageProperty(image,"dpx:orientation.aspect_ratio", 950 "%ux%u",dpx.orientation.aspect_ratio[0], 951 dpx.orientation.aspect_ratio[1]); 952 offset+=ReadBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *) 953 dpx.orientation.reserve); 954 } 955 if (dpx.file.image_offset >= 1920U) 956 { 957 /* 958 Read DPX film header. 959 */ 960 offset+=ReadBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id); 961 if (*dpx.film.id != '\0') 962 (void) FormatImageProperty(image,"dpx:film.id","%.2s",dpx.film.id); 963 offset+=ReadBlob(image,sizeof(dpx.film.type),(unsigned char *) 964 dpx.film.type); 965 if (*dpx.film.type != '\0') 966 (void) FormatImageProperty(image,"dpx:film.type","%.2s",dpx.film.type); 967 offset+=ReadBlob(image,sizeof(dpx.film.offset),(unsigned char *) 968 dpx.film.offset); 969 if (*dpx.film.offset != '\0') 970 (void) FormatImageProperty(image,"dpx:film.offset","%.2s", 971 dpx.film.offset); 972 offset+=ReadBlob(image,sizeof(dpx.film.prefix),(unsigned char *) 973 dpx.film.prefix); 974 if (*dpx.film.prefix != '\0') 975 (void) FormatImageProperty(image,"dpx:film.prefix","%.6s", 976 dpx.film.prefix); 977 offset+=ReadBlob(image,sizeof(dpx.film.count),(unsigned char *) 978 dpx.film.count); 979 if (*dpx.film.count != '\0') 980 (void) FormatImageProperty(image,"dpx:film.count","%.4s", 981 dpx.film.count); 982 offset+=ReadBlob(image,sizeof(dpx.film.format),(unsigned char *) 983 dpx.film.format); 984 if (*dpx.film.format != '\0') 985 (void) FormatImageProperty(image,"dpx:film.format","%.4s", 986 dpx.film.format); 987 dpx.film.frame_position=ReadBlobLong(image); 988 offset+=4; 989 if (dpx.film.frame_position != ~0U) 990 (void) FormatImageProperty(image,"dpx:film.frame_position","%u", 991 dpx.film.frame_position); 992 dpx.film.sequence_extent=ReadBlobLong(image); 993 offset+=4; 994 if (dpx.film.sequence_extent != ~0U) 995 (void) FormatImageProperty(image,"dpx:film.sequence_extent","%u", 996 dpx.film.sequence_extent); 997 dpx.film.held_count=ReadBlobLong(image); 998 offset+=4; 999 if (dpx.film.held_count != ~0U) 1000 (void) FormatImageProperty(image,"dpx:film.held_count","%u", 1001 dpx.film.held_count); 1002 dpx.film.frame_rate=ReadBlobFloat(image); 1003 offset+=4; 1004 if (IsFloatDefined(dpx.film.frame_rate) != MagickFalse) 1005 (void) FormatImageProperty(image,"dpx:film.frame_rate","%g", 1006 dpx.film.frame_rate); 1007 dpx.film.shutter_angle=ReadBlobFloat(image); 1008 offset+=4; 1009 if (IsFloatDefined(dpx.film.shutter_angle) != MagickFalse) 1010 (void) FormatImageProperty(image,"dpx:film.shutter_angle","%g", 1011 dpx.film.shutter_angle); 1012 offset+=ReadBlob(image,sizeof(dpx.film.frame_id),(unsigned char *) 1013 dpx.film.frame_id); 1014 if (*dpx.film.frame_id != '\0') 1015 (void) FormatImageProperty(image,"dpx:film.frame_id","%.32s", 1016 dpx.film.frame_id); 1017 offset+=ReadBlob(image,sizeof(dpx.film.slate),(unsigned char *) 1018 dpx.film.slate); 1019 if (*dpx.film.slate != '\0') 1020 (void) FormatImageProperty(image,"dpx:film.slate","%.100s", 1021 dpx.film.slate); 1022 offset+=ReadBlob(image,sizeof(dpx.film.reserve),(unsigned char *) 1023 dpx.film.reserve); 1024 } 1025 if (dpx.file.image_offset >= 2048U) 1026 { 1027 /* 1028 Read DPX television header. 1029 */ 1030 dpx.television.time_code=(unsigned int) ReadBlobLong(image); 1031 offset+=4; 1032 TimeCodeToString(dpx.television.time_code,value); 1033 (void) SetImageProperty(image,"dpx:television.time.code",value,exception); 1034 dpx.television.user_bits=(unsigned int) ReadBlobLong(image); 1035 offset+=4; 1036 TimeCodeToString(dpx.television.user_bits,value); 1037 (void) SetImageProperty(image,"dpx:television.user.bits",value,exception); 1038 dpx.television.interlace=(unsigned char) ReadBlobByte(image); 1039 offset++; 1040 if (dpx.television.interlace != 0) 1041 (void) FormatImageProperty(image,"dpx:television.interlace","%.20g", 1042 (double) dpx.television.interlace); 1043 dpx.television.field_number=(unsigned char) ReadBlobByte(image); 1044 offset++; 1045 if (dpx.television.field_number != 0) 1046 (void) FormatImageProperty(image,"dpx:television.field_number","%.20g", 1047 (double) dpx.television.field_number); 1048 dpx.television.video_signal=(unsigned char) ReadBlobByte(image); 1049 offset++; 1050 if (dpx.television.video_signal != 0) 1051 (void) FormatImageProperty(image,"dpx:television.video_signal","%.20g", 1052 (double) dpx.television.video_signal); 1053 dpx.television.padding=(unsigned char) ReadBlobByte(image); 1054 offset++; 1055 if (dpx.television.padding != 0) 1056 (void) FormatImageProperty(image,"dpx:television.padding","%d", 1057 dpx.television.padding); 1058 dpx.television.horizontal_sample_rate=ReadBlobFloat(image); 1059 offset+=4; 1060 if (IsFloatDefined(dpx.television.horizontal_sample_rate) != MagickFalse) 1061 (void) FormatImageProperty(image, 1062 "dpx:television.horizontal_sample_rate","%g", 1063 dpx.television.horizontal_sample_rate); 1064 dpx.television.vertical_sample_rate=ReadBlobFloat(image); 1065 offset+=4; 1066 if (IsFloatDefined(dpx.television.vertical_sample_rate) != MagickFalse) 1067 (void) FormatImageProperty(image,"dpx:television.vertical_sample_rate", 1068 "%g",dpx.television.vertical_sample_rate); 1069 dpx.television.frame_rate=ReadBlobFloat(image); 1070 offset+=4; 1071 if (IsFloatDefined(dpx.television.frame_rate) != MagickFalse) 1072 (void) FormatImageProperty(image,"dpx:television.frame_rate","%g", 1073 dpx.television.frame_rate); 1074 dpx.television.time_offset=ReadBlobFloat(image); 1075 offset+=4; 1076 if (IsFloatDefined(dpx.television.time_offset) != MagickFalse) 1077 (void) FormatImageProperty(image,"dpx:television.time_offset","%g", 1078 dpx.television.time_offset); 1079 dpx.television.gamma=ReadBlobFloat(image); 1080 offset+=4; 1081 if (IsFloatDefined(dpx.television.gamma) != MagickFalse) 1082 (void) FormatImageProperty(image,"dpx:television.gamma","%g", 1083 dpx.television.gamma); 1084 dpx.television.black_level=ReadBlobFloat(image); 1085 offset+=4; 1086 if (IsFloatDefined(dpx.television.black_level) != MagickFalse) 1087 (void) FormatImageProperty(image,"dpx:television.black_level","%g", 1088 dpx.television.black_level); 1089 dpx.television.black_gain=ReadBlobFloat(image); 1090 offset+=4; 1091 if (IsFloatDefined(dpx.television.black_gain) != MagickFalse) 1092 (void) FormatImageProperty(image,"dpx:television.black_gain","%g", 1093 dpx.television.black_gain); 1094 dpx.television.break_point=ReadBlobFloat(image); 1095 offset+=4; 1096 if (IsFloatDefined(dpx.television.break_point) != MagickFalse) 1097 (void) FormatImageProperty(image,"dpx:television.break_point","%g", 1098 dpx.television.break_point); 1099 dpx.television.white_level=ReadBlobFloat(image); 1100 offset+=4; 1101 if (IsFloatDefined(dpx.television.white_level) != MagickFalse) 1102 (void) FormatImageProperty(image,"dpx:television.white_level","%g", 1103 dpx.television.white_level); 1104 dpx.television.integration_times=ReadBlobFloat(image); 1105 offset+=4; 1106 if (IsFloatDefined(dpx.television.integration_times) != MagickFalse) 1107 (void) FormatImageProperty(image,"dpx:television.integration_times", 1108 "%g",dpx.television.integration_times); 1109 offset+=ReadBlob(image,sizeof(dpx.television.reserve),(unsigned char *) 1110 dpx.television.reserve); 1111 } 1112 if (dpx.file.image_offset > 2080U) 1113 { 1114 /* 1115 Read DPX user header. 1116 */ 1117 offset+=ReadBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id); 1118 if (*dpx.user.id != '\0') 1119 (void) FormatImageProperty(image,"dpx:user.id","%.32s",dpx.user.id); 1120 if ((dpx.file.user_size != ~0U) && 1121 ((size_t) dpx.file.user_size > sizeof(dpx.user.id))) 1122 { 1123 StringInfo 1124 *profile; 1125 1126 if (dpx.file.user_size > GetBlobSize(image)) 1127 ThrowReaderException(CorruptImageError, 1128 "InsufficientImageDataInFile"); 1129 profile=BlobToStringInfo((const unsigned char *) NULL, 1130 dpx.file.user_size-sizeof(dpx.user.id)); 1131 if (profile == (StringInfo *) NULL) 1132 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1133 offset+=ReadBlob(image,GetStringInfoLength(profile), 1134 GetStringInfoDatum(profile)); 1135 if (EOFBlob(image) != MagickFalse) 1136 (void) SetImageProfile(image,"dpx:user-data",profile,exception); 1137 profile=DestroyStringInfo(profile); 1138 } 1139 } 1140 for ( ; offset < (MagickOffsetType) dpx.file.image_offset; offset++) 1141 if (ReadBlobByte(image) == EOF) 1142 break; 1143 if (EOFBlob(image) != MagickFalse) 1144 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 1145 image->filename); 1146 if (image_info->ping != MagickFalse) 1147 { 1148 (void) CloseBlob(image); 1149 return(GetFirstImageInList(image)); 1150 } 1151 status=SetImageExtent(image,image->columns,image->rows,exception); 1152 if (status == MagickFalse) 1153 return(DestroyImageList(image)); 1154 status=ResetImagePixels(image,exception); 1155 if (status == MagickFalse) 1156 return(DestroyImageList(image)); 1157 for (n=0; n < (ssize_t) dpx.image.number_elements; n++) 1158 { 1159 /* 1160 Convert DPX raster image to pixel packets. 1161 */ 1162 if ((dpx.image.image_element[n].data_offset != ~0U) && 1163 (dpx.image.image_element[n].data_offset != 0U)) 1164 { 1165 MagickOffsetType 1166 data_offset; 1167 1168 data_offset=(MagickOffsetType) dpx.image.image_element[n].data_offset; 1169 if (data_offset < offset) 1170 offset=SeekBlob(image,data_offset,SEEK_SET); 1171 else 1172 for ( ; offset < data_offset; offset++) 1173 if (ReadBlobByte(image) == EOF) 1174 break; 1175 if (offset != data_offset) 1176 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 1177 } 1178 SetPrimaryChromaticity((DPXColorimetric) 1179 dpx.image.image_element[n].colorimetric,&image->chromaticity); 1180 image->depth=dpx.image.image_element[n].bit_size; 1181 if ((image->depth == 0) || (image->depth > 32)) 1182 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1183 samples_per_pixel=1; 1184 quantum_type=GrayQuantum; 1185 component_type=dpx.image.image_element[n].descriptor; 1186 switch (component_type) 1187 { 1188 case CbYCrY422ComponentType: 1189 { 1190 samples_per_pixel=2; 1191 quantum_type=CbYCrYQuantum; 1192 break; 1193 } 1194 case CbYACrYA4224ComponentType: 1195 case CbYCr444ComponentType: 1196 { 1197 samples_per_pixel=3; 1198 quantum_type=CbYCrQuantum; 1199 break; 1200 } 1201 case RGBComponentType: 1202 { 1203 samples_per_pixel=3; 1204 quantum_type=RGBQuantum; 1205 break; 1206 } 1207 case ABGRComponentType: 1208 case RGBAComponentType: 1209 { 1210 image->alpha_trait=BlendPixelTrait; 1211 samples_per_pixel=4; 1212 quantum_type=RGBAQuantum; 1213 break; 1214 } 1215 default: 1216 break; 1217 } 1218 switch (component_type) 1219 { 1220 case CbYCrY422ComponentType: 1221 case CbYACrYA4224ComponentType: 1222 case CbYCr444ComponentType: 1223 { 1224 SetImageColorspace(image,Rec709YCbCrColorspace,exception); 1225 break; 1226 } 1227 case LumaComponentType: 1228 { 1229 SetImageColorspace(image,GRAYColorspace,exception); 1230 break; 1231 } 1232 default: 1233 { 1234 SetImageColorspace(image,sRGBColorspace,exception); 1235 if (dpx.image.image_element[n].transfer_characteristic == LogarithmicColorimetric) 1236 SetImageColorspace(image,LogColorspace,exception); 1237 if (dpx.image.image_element[n].transfer_characteristic == PrintingDensityColorimetric) 1238 SetImageColorspace(image,LogColorspace,exception); 1239 break; 1240 } 1241 } 1242 extent=GetBytesPerRow(image->columns,samples_per_pixel,image->depth, 1243 dpx.image.image_element[n].packing == 0 ? MagickFalse : MagickTrue); 1244 /* 1245 DPX any-bit pixel format. 1246 */ 1247 row=0; 1248 quantum_info=AcquireQuantumInfo(image_info,image); 1249 if (quantum_info == (QuantumInfo *) NULL) 1250 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1251 SetQuantumQuantum(quantum_info,32); 1252 SetQuantumPack(quantum_info,dpx.image.image_element[n].packing == 0 ? 1253 MagickTrue : MagickFalse); 1254 for (y=0; y < (ssize_t) image->rows; y++) 1255 { 1256 const unsigned char 1257 *pixels; 1258 1259 MagickBooleanType 1260 sync; 1261 1262 register Quantum 1263 *q; 1264 1265 size_t 1266 length; 1267 1268 ssize_t 1269 offset; 1270 1271 pixels=(const unsigned char *) ReadBlobStream(image,extent, 1272 GetQuantumPixels(quantum_info),&count); 1273 if (count != (ssize_t) extent) 1274 break; 1275 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 1276 (image->previous == (Image *) NULL)) 1277 { 1278 MagickBooleanType 1279 proceed; 1280 1281 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row, 1282 image->rows); 1283 if (proceed == MagickFalse) 1284 break; 1285 } 1286 offset=row++; 1287 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception); 1288 if (q == (Quantum *) NULL) 1289 break; 1290 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, 1291 quantum_type,pixels,exception); 1292 (void) length; 1293 sync=SyncAuthenticPixels(image,exception); 1294 if (sync == MagickFalse) 1295 break; 1296 } 1297 quantum_info=DestroyQuantumInfo(quantum_info); 1298 if (y < (ssize_t) image->rows) 1299 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 1300 SetQuantumImageType(image,quantum_type); 1301 if (EOFBlob(image) != MagickFalse) 1302 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 1303 image->filename); 1304 if ((i+1) < (ssize_t) dpx.image.number_elements) 1305 { 1306 /* 1307 Allocate next image structure. 1308 */ 1309 AcquireNextImage(image_info,image,exception); 1310 if (GetNextImageInList(image) == (Image *) NULL) 1311 { 1312 status=MagickFalse; 1313 break; 1314 } 1315 image=SyncNextImageInList(image); 1316 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 1317 GetBlobSize(image)); 1318 if (status == MagickFalse) 1319 break; 1320 } 1321 } 1322 (void) CloseBlob(image); 1323 if (status == MagickFalse) 1324 return(DestroyImageList(image)); 1325 return(GetFirstImageInList(image)); 1326 } 1327 1328 /* 1330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1331 % % 1332 % % 1333 % % 1334 % R e g i s t e r D P X I m a g e % 1335 % % 1336 % % 1337 % % 1338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1339 % 1340 % RegisterDPXImage() adds properties for the DPX image format to 1341 % the list of supported formats. The properties include the image format 1342 % tag, a method to read and/or write the format, whether the format 1343 % supports the saving of more than one frame to the same file or blob, 1344 % whether the format supports native in-memory I/O, and a brief 1345 % description of the format. 1346 % 1347 % The format of the RegisterDPXImage method is: 1348 % 1349 % size_t RegisterDPXImage(void) 1350 % 1351 */ 1352 ModuleExport size_t RegisterDPXImage(void) 1353 { 1354 MagickInfo 1355 *entry; 1356 1357 static const char 1358 *DPXNote = 1359 { 1360 "Digital Moving Picture Exchange Bitmap, Version 2.0.\n" 1361 "See SMPTE 268M-2003 specification at http://www.smtpe.org\n" 1362 }; 1363 1364 entry=AcquireMagickInfo("DPX","DPX","SMPTE 268M-2003 (DPX 2.0)"); 1365 entry->decoder=(DecodeImageHandler *) ReadDPXImage; 1366 entry->encoder=(EncodeImageHandler *) WriteDPXImage; 1367 entry->magick=(IsImageFormatHandler *) IsDPX; 1368 entry->flags^=CoderAdjoinFlag; 1369 entry->flags|=CoderDecoderSeekableStreamFlag; 1370 entry->note=ConstantString(DPXNote); 1371 (void) RegisterMagickInfo(entry); 1372 return(MagickImageCoderSignature); 1373 } 1374 1375 /* 1377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1378 % % 1379 % % 1380 % % 1381 % U n r e g i s t e r D P X I m a g e % 1382 % % 1383 % % 1384 % % 1385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1386 % 1387 % UnregisterDPXImage() removes format registrations made by the 1388 % DPX module from the list of supported formats. 1389 % 1390 % The format of the UnregisterDPXImage method is: 1391 % 1392 % UnregisterDPXImage(void) 1393 % 1394 */ 1395 ModuleExport void UnregisterDPXImage(void) 1396 { 1397 (void) UnregisterMagickInfo("DPX"); 1398 } 1399 1400 /* 1402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1403 % % 1404 % % 1405 % % 1406 % W r i t e D P X I m a g e % 1407 % % 1408 % % 1409 % % 1410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1411 % 1412 % WriteDPXImage() writes an image in DPX encoded image format. 1413 % 1414 % The format of the WriteDPXImage method is: 1415 % 1416 % MagickBooleanType WriteDPXImage(const ImageInfo *image_info, 1417 % Image *image,ExceptionInfo *exception) 1418 % 1419 % A description of each parameter follows. 1420 % 1421 % o image_info: the image info. 1422 % 1423 % o image: The image. 1424 % 1425 % o exception: return any errors or warnings in this structure. 1426 % 1427 */ 1428 1429 static unsigned int StringToTimeCode(const char *key) 1430 { 1431 char 1432 buffer[2]; 1433 1434 register ssize_t 1435 i; 1436 1437 unsigned int 1438 shift, 1439 value; 1440 1441 value=0; 1442 shift=28; 1443 buffer[1]='\0'; 1444 for (i=0; (*key != 0) && (i < 11); i++) 1445 { 1446 if (isxdigit((int) ((unsigned char) *key)) == 0) 1447 { 1448 key++; 1449 continue; 1450 } 1451 buffer[0]=(*key++); 1452 value|=(unsigned int) ((strtol(buffer,(char **) NULL,16)) << shift); 1453 shift-=4; 1454 } 1455 return(value); 1456 } 1457 1458 static inline const char *GetDPXProperty(const Image *image, 1459 const char *property,ExceptionInfo *exception) 1460 { 1461 const char 1462 *value; 1463 1464 value=GetImageArtifact(image,property); 1465 if (value != (const char *) NULL) 1466 return(value); 1467 return(GetImageProperty(image,property,exception)); 1468 } 1469 1470 static MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image, 1471 ExceptionInfo *exception) 1472 { 1473 char 1474 *url; 1475 1476 const char 1477 *value; 1478 1479 const StringInfo 1480 *profile; 1481 1482 DPXInfo 1483 dpx; 1484 1485 GeometryInfo 1486 geometry_info; 1487 1488 MagickBooleanType 1489 status; 1490 1491 MagickOffsetType 1492 offset; 1493 1494 MagickStatusType 1495 flags; 1496 1497 QuantumInfo 1498 *quantum_info; 1499 1500 QuantumType 1501 quantum_type; 1502 1503 register const Quantum 1504 *p; 1505 1506 register ssize_t 1507 i; 1508 1509 size_t 1510 channels, 1511 extent; 1512 1513 ssize_t 1514 count, 1515 horizontal_factor, 1516 vertical_factor, 1517 y; 1518 1519 time_t 1520 seconds; 1521 1522 unsigned char 1523 *pixels; 1524 1525 /* 1526 Open output image file. 1527 */ 1528 assert(image_info != (const ImageInfo *) NULL); 1529 assert(image_info->signature == MagickCoreSignature); 1530 assert(image != (Image *) NULL); 1531 assert(image->signature == MagickCoreSignature); 1532 if (image->debug != MagickFalse) 1533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1534 horizontal_factor=4; 1535 vertical_factor=4; 1536 if (image_info->sampling_factor != (char *) NULL) 1537 { 1538 flags=ParseGeometry(image_info->sampling_factor,&geometry_info); 1539 horizontal_factor=(ssize_t) geometry_info.rho; 1540 vertical_factor=(ssize_t) geometry_info.sigma; 1541 if ((flags & SigmaValue) == 0) 1542 vertical_factor=horizontal_factor; 1543 if ((horizontal_factor != 1) && (horizontal_factor != 2) && 1544 (horizontal_factor != 4) && (vertical_factor != 1) && 1545 (vertical_factor != 2) && (vertical_factor != 4)) 1546 ThrowWriterException(CorruptImageError,"UnexpectedSamplingFactor"); 1547 } 1548 if ((image->colorspace == YCbCrColorspace) && 1549 ((horizontal_factor == 2) || (vertical_factor == 2))) 1550 if ((image->columns % 2) != 0) 1551 image->columns++; 1552 assert(exception != (ExceptionInfo *) NULL); 1553 assert(exception->signature == MagickCoreSignature); 1554 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 1555 if (status == MagickFalse) 1556 return(status); 1557 /* 1558 Write file header. 1559 */ 1560 (void) memset(&dpx,0,sizeof(dpx)); 1561 offset=0; 1562 dpx.file.magic=0x53445058U; 1563 offset+=WriteBlobLong(image,dpx.file.magic); 1564 dpx.file.image_offset=0x2000U; 1565 profile=GetImageProfile(image,"dpx:user-data"); 1566 if (profile != (StringInfo *) NULL) 1567 { 1568 if (GetStringInfoLength(profile) > 1048576) 1569 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); 1570 dpx.file.image_offset+=(unsigned int) GetStringInfoLength(profile); 1571 dpx.file.image_offset=(((dpx.file.image_offset+0x2000-1)/0x2000)*0x2000); 1572 } 1573 offset+=WriteBlobLong(image,dpx.file.image_offset); 1574 (void) strncpy(dpx.file.version,"V2.0",sizeof(dpx.file.version)-1); 1575 offset+=WriteBlob(image,8,(unsigned char *) &dpx.file.version); 1576 channels=1; 1577 if (IsImageGray(image) == MagickFalse) 1578 channels=3; 1579 if (image->alpha_trait != UndefinedPixelTrait) 1580 channels++; 1581 dpx.file.file_size=(unsigned int) (channels*image->columns*image->rows+ 1582 dpx.file.image_offset); 1583 offset+=WriteBlobLong(image,dpx.file.file_size); 1584 dpx.file.ditto_key=1U; /* new frame */ 1585 offset+=WriteBlobLong(image,dpx.file.ditto_key); 1586 dpx.file.generic_size=0x00000680U; 1587 offset+=WriteBlobLong(image,dpx.file.generic_size); 1588 dpx.file.industry_size=0x00000180U; 1589 offset+=WriteBlobLong(image,dpx.file.industry_size); 1590 dpx.file.user_size=0; 1591 if (profile != (StringInfo *) NULL) 1592 { 1593 dpx.file.user_size+=(unsigned int) GetStringInfoLength(profile); 1594 dpx.file.user_size=(((dpx.file.user_size+0x2000-1)/0x2000)*0x2000); 1595 } 1596 offset+=WriteBlobLong(image,dpx.file.user_size); 1597 value=GetDPXProperty(image,"dpx:file.filename",exception); 1598 if (value != (const char *) NULL) 1599 (void) strncpy(dpx.file.filename,value,sizeof(dpx.file.filename)-1); 1600 offset+=WriteBlob(image,sizeof(dpx.file.filename),(unsigned char *) 1601 dpx.file.filename); 1602 seconds=time((time_t *) NULL); 1603 (void) FormatMagickTime(seconds,sizeof(dpx.file.timestamp), 1604 dpx.file.timestamp); 1605 offset+=WriteBlob(image,sizeof(dpx.file.timestamp),(unsigned char *) 1606 dpx.file.timestamp); 1607 url=GetMagickHomeURL(); 1608 (void) strncpy(dpx.file.creator,url,sizeof(dpx.file.creator)-1); 1609 url=DestroyString(url); 1610 value=GetDPXProperty(image,"dpx:file.creator",exception); 1611 if (value != (const char *) NULL) 1612 (void) strncpy(dpx.file.creator,value,sizeof(dpx.file.creator)-1); 1613 offset+=WriteBlob(image,sizeof(dpx.file.creator),(unsigned char *) 1614 dpx.file.creator); 1615 value=GetDPXProperty(image,"dpx:file.project",exception); 1616 if (value != (const char *) NULL) 1617 (void) strncpy(dpx.file.project,value,sizeof(dpx.file.project)-1); 1618 offset+=WriteBlob(image,sizeof(dpx.file.project),(unsigned char *) 1619 dpx.file.project); 1620 value=GetDPXProperty(image,"dpx:file.copyright",exception); 1621 if (value != (const char *) NULL) 1622 (void) strncpy(dpx.file.copyright,value,sizeof(dpx.file.copyright)-1); 1623 offset+=WriteBlob(image,sizeof(dpx.file.copyright),(unsigned char *) 1624 dpx.file.copyright); 1625 dpx.file.encrypt_key=(~0U); 1626 offset+=WriteBlobLong(image,dpx.file.encrypt_key); 1627 offset+=WriteBlob(image,sizeof(dpx.file.reserve),(unsigned char *) 1628 dpx.file.reserve); 1629 /* 1630 Write image header. 1631 */ 1632 switch (image->orientation) 1633 { 1634 default: 1635 case TopLeftOrientation: dpx.image.orientation=0; break; 1636 case TopRightOrientation: dpx.image.orientation=1; break; 1637 case BottomLeftOrientation: dpx.image.orientation=2; break; 1638 case BottomRightOrientation: dpx.image.orientation=3; break; 1639 case LeftTopOrientation: dpx.image.orientation=4; break; 1640 case RightTopOrientation: dpx.image.orientation=5; break; 1641 case LeftBottomOrientation: dpx.image.orientation=6; break; 1642 case RightBottomOrientation: dpx.image.orientation=7; break; 1643 } 1644 offset+=WriteBlobShort(image,dpx.image.orientation); 1645 dpx.image.number_elements=1; 1646 offset+=WriteBlobShort(image,dpx.image.number_elements); 1647 if ((image->columns != (unsigned int) image->columns) || 1648 (image->rows != (unsigned int) image->rows)) 1649 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); 1650 offset+=WriteBlobLong(image,(unsigned int) image->columns); 1651 offset+=WriteBlobLong(image,(unsigned int) image->rows); 1652 for (i=0; i < 8; i++) 1653 { 1654 dpx.image.image_element[i].data_sign=0U; 1655 offset+=WriteBlobLong(image,dpx.image.image_element[i].data_sign); 1656 dpx.image.image_element[i].low_data=0U; 1657 offset+=WriteBlobLong(image,dpx.image.image_element[i].low_data); 1658 dpx.image.image_element[i].low_quantity=0.0f; 1659 offset+=WriteBlobFloat(image,dpx.image.image_element[i].low_quantity); 1660 dpx.image.image_element[i].high_data=0U; 1661 offset+=WriteBlobLong(image,dpx.image.image_element[i].high_data); 1662 dpx.image.image_element[i].high_quantity=0.0f; 1663 offset+=WriteBlobFloat(image,dpx.image.image_element[i].high_quantity); 1664 dpx.image.image_element[i].descriptor=0; 1665 if (i == 0) 1666 switch (image->colorspace) 1667 { 1668 case Rec601YCbCrColorspace: 1669 case Rec709YCbCrColorspace: 1670 case YCbCrColorspace: 1671 { 1672 dpx.image.image_element[i].descriptor=CbYCr444ComponentType; 1673 if (image->alpha_trait != UndefinedPixelTrait) 1674 dpx.image.image_element[i].descriptor=CbYCrA4444ComponentType; 1675 break; 1676 } 1677 default: 1678 { 1679 dpx.image.image_element[i].descriptor=RGBComponentType; 1680 if (image->alpha_trait != UndefinedPixelTrait) 1681 dpx.image.image_element[i].descriptor=RGBAComponentType; 1682 if ((image_info->type != TrueColorType) && 1683 (image->alpha_trait == UndefinedPixelTrait) && 1684 (SetImageGray(image,exception) != MagickFalse)) 1685 dpx.image.image_element[i].descriptor=LumaComponentType; 1686 break; 1687 } 1688 } 1689 offset+=WriteBlobByte(image,dpx.image.image_element[i].descriptor); 1690 dpx.image.image_element[i].transfer_characteristic=0; 1691 if (image->colorspace == LogColorspace) 1692 dpx.image.image_element[0].transfer_characteristic= 1693 PrintingDensityColorimetric; 1694 offset+=WriteBlobByte(image, 1695 dpx.image.image_element[i].transfer_characteristic); 1696 dpx.image.image_element[i].colorimetric=0; 1697 offset+=WriteBlobByte(image,dpx.image.image_element[i].colorimetric); 1698 dpx.image.image_element[i].bit_size=0; 1699 if (i == 0) 1700 dpx.image.image_element[i].bit_size=(unsigned char) image->depth; 1701 offset+=WriteBlobByte(image,dpx.image.image_element[i].bit_size); 1702 dpx.image.image_element[i].packing=0; 1703 if ((image->depth == 10) || (image->depth == 12)) 1704 dpx.image.image_element[i].packing=1; 1705 offset+=WriteBlobShort(image,dpx.image.image_element[i].packing); 1706 dpx.image.image_element[i].encoding=0; 1707 offset+=WriteBlobShort(image,dpx.image.image_element[i].encoding); 1708 dpx.image.image_element[i].data_offset=0U; 1709 if (i == 0) 1710 dpx.image.image_element[i].data_offset=dpx.file.image_offset; 1711 offset+=WriteBlobLong(image,dpx.image.image_element[i].data_offset); 1712 dpx.image.image_element[i].end_of_line_padding=0U; 1713 offset+=WriteBlobLong(image,dpx.image.image_element[i].end_of_line_padding); 1714 offset+=WriteBlobLong(image, 1715 dpx.image.image_element[i].end_of_image_padding); 1716 offset+=WriteBlob(image,sizeof(dpx.image.image_element[i].description), 1717 (unsigned char *) dpx.image.image_element[i].description); 1718 } 1719 offset+=WriteBlob(image,sizeof(dpx.image.reserve),(unsigned char *) 1720 dpx.image.reserve); 1721 /* 1722 Write orientation header. 1723 */ 1724 if ((image->rows != image->magick_rows) || 1725 (image->columns != image->magick_columns)) 1726 { 1727 /* 1728 These properties are not valid if image size changed. 1729 */ 1730 (void) DeleteImageProperty(image,"dpx:orientation.x_offset"); 1731 (void) DeleteImageProperty(image,"dpx:orientation.y_offset"); 1732 (void) DeleteImageProperty(image,"dpx:orientation.x_center"); 1733 (void) DeleteImageProperty(image,"dpx:orientation.y_center"); 1734 (void) DeleteImageProperty(image,"dpx:orientation.x_size"); 1735 (void) DeleteImageProperty(image,"dpx:orientation.y_size"); 1736 } 1737 dpx.orientation.x_offset=0U; 1738 value=GetDPXProperty(image,"dpx:orientation.x_offset",exception); 1739 if (value != (const char *) NULL) 1740 dpx.orientation.x_offset=(unsigned int) StringToUnsignedLong(value); 1741 offset+=WriteBlobLong(image,dpx.orientation.x_offset); 1742 dpx.orientation.y_offset=0U; 1743 value=GetDPXProperty(image,"dpx:orientation.y_offset",exception); 1744 if (value != (const char *) NULL) 1745 dpx.orientation.y_offset=(unsigned int) StringToUnsignedLong(value); 1746 offset+=WriteBlobLong(image,dpx.orientation.y_offset); 1747 dpx.orientation.x_center=0.0f; 1748 value=GetDPXProperty(image,"dpx:orientation.x_center",exception); 1749 if (value != (const char *) NULL) 1750 dpx.orientation.x_center=StringToDouble(value,(char **) NULL); 1751 offset+=WriteBlobFloat(image,dpx.orientation.x_center); 1752 dpx.orientation.y_center=0.0f; 1753 value=GetDPXProperty(image,"dpx:orientation.y_center",exception); 1754 if (value != (const char *) NULL) 1755 dpx.orientation.y_center=StringToDouble(value,(char **) NULL); 1756 offset+=WriteBlobFloat(image,dpx.orientation.y_center); 1757 dpx.orientation.x_size=0U; 1758 value=GetDPXProperty(image,"dpx:orientation.x_size",exception); 1759 if (value != (const char *) NULL) 1760 dpx.orientation.x_size=(unsigned int) StringToUnsignedLong(value); 1761 offset+=WriteBlobLong(image,dpx.orientation.x_size); 1762 dpx.orientation.y_size=0U; 1763 value=GetDPXProperty(image,"dpx:orientation.y_size",exception); 1764 if (value != (const char *) NULL) 1765 dpx.orientation.y_size=(unsigned int) StringToUnsignedLong(value); 1766 offset+=WriteBlobLong(image,dpx.orientation.y_size); 1767 value=GetDPXProperty(image,"dpx:orientation.filename",exception); 1768 if (value != (const char *) NULL) 1769 (void) strncpy(dpx.orientation.filename,value, 1770 sizeof(dpx.orientation.filename)-1); 1771 offset+=WriteBlob(image,sizeof(dpx.orientation.filename),(unsigned char *) 1772 dpx.orientation.filename); 1773 offset+=WriteBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *) 1774 dpx.orientation.timestamp); 1775 value=GetDPXProperty(image,"dpx:orientation.device",exception); 1776 if (value != (const char *) NULL) 1777 (void) strncpy(dpx.orientation.device,value, 1778 sizeof(dpx.orientation.device)-1); 1779 offset+=WriteBlob(image,sizeof(dpx.orientation.device),(unsigned char *) 1780 dpx.orientation.device); 1781 value=GetDPXProperty(image,"dpx:orientation.serial",exception); 1782 if (value != (const char *) NULL) 1783 (void) strncpy(dpx.orientation.serial,value, 1784 sizeof(dpx.orientation.serial)-1); 1785 offset+=WriteBlob(image,sizeof(dpx.orientation.serial),(unsigned char *) 1786 dpx.orientation.serial); 1787 for (i=0; i < 4; i++) 1788 dpx.orientation.border[i]=0; 1789 value=GetDPXProperty(image,"dpx:orientation.border",exception); 1790 if (value != (const char *) NULL) 1791 { 1792 flags=ParseGeometry(value,&geometry_info); 1793 if ((flags & SigmaValue) == 0) 1794 geometry_info.sigma=geometry_info.rho; 1795 dpx.orientation.border[0]=(unsigned short) (geometry_info.rho+0.5); 1796 dpx.orientation.border[1]=(unsigned short) (geometry_info.sigma+0.5); 1797 dpx.orientation.border[2]=(unsigned short) (geometry_info.xi+0.5); 1798 dpx.orientation.border[3]=(unsigned short) (geometry_info.psi+0.5); 1799 } 1800 for (i=0; i < 4; i++) 1801 offset+=WriteBlobShort(image,dpx.orientation.border[i]); 1802 for (i=0; i < 2; i++) 1803 dpx.orientation.aspect_ratio[i]=0U; 1804 value=GetDPXProperty(image,"dpx:orientation.aspect_ratio",exception); 1805 if (value != (const char *) NULL) 1806 { 1807 flags=ParseGeometry(value,&geometry_info); 1808 if ((flags & SigmaValue) == 0) 1809 geometry_info.sigma=geometry_info.rho; 1810 dpx.orientation.aspect_ratio[0]=(unsigned int) (geometry_info.rho+0.5); 1811 dpx.orientation.aspect_ratio[1]=(unsigned int) (geometry_info.sigma+0.5); 1812 } 1813 for (i=0; i < 2; i++) 1814 offset+=WriteBlobLong(image,dpx.orientation.aspect_ratio[i]); 1815 offset+=WriteBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *) 1816 dpx.orientation.reserve); 1817 /* 1818 Write film header. 1819 */ 1820 (void) memset(dpx.film.id,0,sizeof(dpx.film.id)); 1821 value=GetDPXProperty(image,"dpx:film.id",exception); 1822 if (value != (const char *) NULL) 1823 (void) strncpy(dpx.film.id,value,sizeof(dpx.film.id)-1); 1824 offset+=WriteBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id); 1825 (void) memset(dpx.film.type,0,sizeof(dpx.film.type)); 1826 value=GetDPXProperty(image,"dpx:film.type",exception); 1827 if (value != (const char *) NULL) 1828 (void) strncpy(dpx.film.type,value,sizeof(dpx.film.type)-1); 1829 offset+=WriteBlob(image,sizeof(dpx.film.type),(unsigned char *) 1830 dpx.film.type); 1831 (void) memset(dpx.film.offset,0,sizeof(dpx.film.offset)); 1832 value=GetDPXProperty(image,"dpx:film.offset",exception); 1833 if (value != (const char *) NULL) 1834 (void) strncpy(dpx.film.offset,value,sizeof(dpx.film.offset)-1); 1835 offset+=WriteBlob(image,sizeof(dpx.film.offset),(unsigned char *) 1836 dpx.film.offset); 1837 (void) memset(dpx.film.prefix,0,sizeof(dpx.film.prefix)); 1838 value=GetDPXProperty(image,"dpx:film.prefix",exception); 1839 if (value != (const char *) NULL) 1840 (void) strncpy(dpx.film.prefix,value,sizeof(dpx.film.prefix)-1); 1841 offset+=WriteBlob(image,sizeof(dpx.film.prefix),(unsigned char *) 1842 dpx.film.prefix); 1843 (void) memset(dpx.film.count,0,sizeof(dpx.film.count)); 1844 value=GetDPXProperty(image,"dpx:film.count",exception); 1845 if (value != (const char *) NULL) 1846 (void) strncpy(dpx.film.count,value,sizeof(dpx.film.count)-1); 1847 offset+=WriteBlob(image,sizeof(dpx.film.count),(unsigned char *) 1848 dpx.film.count); 1849 (void) memset(dpx.film.format,0,sizeof(dpx.film.format)); 1850 value=GetDPXProperty(image,"dpx:film.format",exception); 1851 if (value != (const char *) NULL) 1852 (void) strncpy(dpx.film.format,value,sizeof(dpx.film.format)-1); 1853 offset+=WriteBlob(image,sizeof(dpx.film.format),(unsigned char *) 1854 dpx.film.format); 1855 dpx.film.frame_position=0U; 1856 value=GetDPXProperty(image,"dpx:film.frame_position",exception); 1857 if (value != (const char *) NULL) 1858 dpx.film.frame_position=(unsigned int) StringToUnsignedLong(value); 1859 offset+=WriteBlobLong(image,dpx.film.frame_position); 1860 dpx.film.sequence_extent=0U; 1861 value=GetDPXProperty(image,"dpx:film.sequence_extent",exception); 1862 if (value != (const char *) NULL) 1863 dpx.film.sequence_extent=(unsigned int) StringToUnsignedLong(value); 1864 offset+=WriteBlobLong(image,dpx.film.sequence_extent); 1865 dpx.film.held_count=0U; 1866 value=GetDPXProperty(image,"dpx:film.held_count",exception); 1867 if (value != (const char *) NULL) 1868 dpx.film.held_count=(unsigned int) StringToUnsignedLong(value); 1869 offset+=WriteBlobLong(image,dpx.film.held_count); 1870 dpx.film.frame_rate=0.0f; 1871 value=GetDPXProperty(image,"dpx:film.frame_rate",exception); 1872 if (value != (const char *) NULL) 1873 dpx.film.frame_rate=StringToDouble(value,(char **) NULL); 1874 offset+=WriteBlobFloat(image,dpx.film.frame_rate); 1875 dpx.film.shutter_angle=0.0f; 1876 value=GetDPXProperty(image,"dpx:film.shutter_angle",exception); 1877 if (value != (const char *) NULL) 1878 dpx.film.shutter_angle=StringToDouble(value,(char **) NULL); 1879 offset+=WriteBlobFloat(image,dpx.film.shutter_angle); 1880 (void) memset(dpx.film.frame_id,0,sizeof(dpx.film.frame_id)); 1881 value=GetDPXProperty(image,"dpx:film.frame_id",exception); 1882 if (value != (const char *) NULL) 1883 (void) strncpy(dpx.film.frame_id,value,sizeof(dpx.film.frame_id)-1); 1884 offset+=WriteBlob(image,sizeof(dpx.film.frame_id),(unsigned char *) 1885 dpx.film.frame_id); 1886 value=GetDPXProperty(image,"dpx:film.slate",exception); 1887 if (value != (const char *) NULL) 1888 (void) strncpy(dpx.film.slate,value,sizeof(dpx.film.slate)-1); 1889 offset+=WriteBlob(image,sizeof(dpx.film.slate),(unsigned char *) 1890 dpx.film.slate); 1891 offset+=WriteBlob(image,sizeof(dpx.film.reserve),(unsigned char *) 1892 dpx.film.reserve); 1893 /* 1894 Write television header. 1895 */ 1896 value=GetDPXProperty(image,"dpx:television.time.code",exception); 1897 if (value != (const char *) NULL) 1898 dpx.television.time_code=StringToTimeCode(value); 1899 offset+=WriteBlobLong(image,dpx.television.time_code); 1900 value=GetDPXProperty(image,"dpx:television.user.bits",exception); 1901 if (value != (const char *) NULL) 1902 dpx.television.user_bits=StringToTimeCode(value); 1903 offset+=WriteBlobLong(image,dpx.television.user_bits); 1904 value=GetDPXProperty(image,"dpx:television.interlace",exception); 1905 if (value != (const char *) NULL) 1906 dpx.television.interlace=(unsigned char) StringToLong(value); 1907 offset+=WriteBlobByte(image,dpx.television.interlace); 1908 value=GetDPXProperty(image,"dpx:television.field_number",exception); 1909 if (value != (const char *) NULL) 1910 dpx.television.field_number=(unsigned char) StringToLong(value); 1911 offset+=WriteBlobByte(image,dpx.television.field_number); 1912 dpx.television.video_signal=0; 1913 value=GetDPXProperty(image,"dpx:television.video_signal",exception); 1914 if (value != (const char *) NULL) 1915 dpx.television.video_signal=(unsigned char) StringToLong(value); 1916 offset+=WriteBlobByte(image,dpx.television.video_signal); 1917 dpx.television.padding=0; 1918 value=GetDPXProperty(image,"dpx:television.padding",exception); 1919 if (value != (const char *) NULL) 1920 dpx.television.padding=(unsigned char) StringToLong(value); 1921 offset+=WriteBlobByte(image,dpx.television.padding); 1922 dpx.television.horizontal_sample_rate=0.0f; 1923 value=GetDPXProperty(image,"dpx:television.horizontal_sample_rate", 1924 exception); 1925 if (value != (const char *) NULL) 1926 dpx.television.horizontal_sample_rate=StringToDouble(value,(char **) NULL); 1927 offset+=WriteBlobFloat(image,dpx.television.horizontal_sample_rate); 1928 dpx.television.vertical_sample_rate=0.0f; 1929 value=GetDPXProperty(image,"dpx:television.vertical_sample_rate",exception); 1930 if (value != (const char *) NULL) 1931 dpx.television.vertical_sample_rate=StringToDouble(value,(char **) NULL); 1932 offset+=WriteBlobFloat(image,dpx.television.vertical_sample_rate); 1933 dpx.television.frame_rate=0.0f; 1934 value=GetDPXProperty(image,"dpx:television.frame_rate",exception); 1935 if (value != (const char *) NULL) 1936 dpx.television.frame_rate=StringToDouble(value,(char **) NULL); 1937 offset+=WriteBlobFloat(image,dpx.television.frame_rate); 1938 dpx.television.time_offset=0.0f; 1939 value=GetDPXProperty(image,"dpx:television.time_offset",exception); 1940 if (value != (const char *) NULL) 1941 dpx.television.time_offset=StringToDouble(value,(char **) NULL); 1942 offset+=WriteBlobFloat(image,dpx.television.time_offset); 1943 dpx.television.gamma=0.0f; 1944 value=GetDPXProperty(image,"dpx:television.gamma",exception); 1945 if (value != (const char *) NULL) 1946 dpx.television.gamma=StringToDouble(value,(char **) NULL); 1947 offset+=WriteBlobFloat(image,dpx.television.gamma); 1948 dpx.television.black_level=0.0f; 1949 value=GetDPXProperty(image,"dpx:television.black_level",exception); 1950 if (value != (const char *) NULL) 1951 dpx.television.black_level=StringToDouble(value,(char **) NULL); 1952 offset+=WriteBlobFloat(image,dpx.television.black_level); 1953 dpx.television.black_gain=0.0f; 1954 value=GetDPXProperty(image,"dpx:television.black_gain",exception); 1955 if (value != (const char *) NULL) 1956 dpx.television.black_gain=StringToDouble(value,(char **) NULL); 1957 offset+=WriteBlobFloat(image,dpx.television.black_gain); 1958 dpx.television.break_point=0.0f; 1959 value=GetDPXProperty(image,"dpx:television.break_point",exception); 1960 if (value != (const char *) NULL) 1961 dpx.television.break_point=StringToDouble(value,(char **) NULL); 1962 offset+=WriteBlobFloat(image,dpx.television.break_point); 1963 dpx.television.white_level=0.0f; 1964 value=GetDPXProperty(image,"dpx:television.white_level",exception); 1965 if (value != (const char *) NULL) 1966 dpx.television.white_level=StringToDouble(value,(char **) NULL); 1967 offset+=WriteBlobFloat(image,dpx.television.white_level); 1968 dpx.television.integration_times=0.0f; 1969 value=GetDPXProperty(image,"dpx:television.integration_times",exception); 1970 if (value != (const char *) NULL) 1971 dpx.television.integration_times=StringToDouble(value,(char **) NULL); 1972 offset+=WriteBlobFloat(image,dpx.television.integration_times); 1973 offset+=WriteBlob(image,sizeof(dpx.television.reserve),(unsigned char *) 1974 dpx.television.reserve); 1975 /* 1976 Write user header. 1977 */ 1978 value=GetDPXProperty(image,"dpx:user.id",exception); 1979 if (value != (const char *) NULL) 1980 (void) strncpy(dpx.user.id,value,sizeof(dpx.user.id)-1); 1981 offset+=WriteBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id); 1982 if (profile != (StringInfo *) NULL) 1983 offset+=WriteBlob(image,GetStringInfoLength(profile), 1984 GetStringInfoDatum(profile)); 1985 while (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset) 1986 { 1987 count=WriteBlobByte(image,0x00); 1988 if (count != 1) 1989 { 1990 ThrowFileException(exception,FileOpenError,"UnableToWriteFile", 1991 image->filename); 1992 break; 1993 } 1994 offset+=count; 1995 } 1996 /* 1997 Convert pixel packets to DPX raster image. 1998 */ 1999 quantum_info=AcquireQuantumInfo(image_info,image); 2000 if (quantum_info == (QuantumInfo *) NULL) 2001 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 2002 SetQuantumQuantum(quantum_info,32); 2003 SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ? 2004 MagickTrue : MagickFalse); 2005 quantum_type=RGBQuantum; 2006 if (image->alpha_trait != UndefinedPixelTrait) 2007 quantum_type=RGBAQuantum; 2008 if (image->colorspace == YCbCrColorspace) 2009 { 2010 quantum_type=CbYCrQuantum; 2011 if (image->alpha_trait != UndefinedPixelTrait) 2012 quantum_type=CbYCrAQuantum; 2013 if ((horizontal_factor == 2) || (vertical_factor == 2)) 2014 quantum_type=CbYCrYQuantum; 2015 } 2016 extent=GetBytesPerRow(image->columns, 2017 image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL,image->depth, 2018 dpx.image.image_element[0].packing == 0 ? MagickFalse : MagickTrue); 2019 if ((image_info->type != TrueColorType) && 2020 (image->alpha_trait == UndefinedPixelTrait) && 2021 (SetImageGray(image,exception) != MagickFalse)) 2022 { 2023 quantum_type=GrayQuantum; 2024 extent=GetBytesPerRow(image->columns,1UL,image->depth, 2025 dpx.image.image_element[0].packing == 0 ? MagickFalse : MagickTrue); 2026 } 2027 pixels=(unsigned char *) GetQuantumPixels(quantum_info); 2028 for (y=0; y < (ssize_t) image->rows; y++) 2029 { 2030 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 2031 if (p == (const Quantum *) NULL) 2032 break; 2033 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, 2034 quantum_type,pixels,exception); 2035 count=WriteBlob(image,extent,pixels); 2036 if (count != (ssize_t) extent) 2037 break; 2038 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 2039 image->rows); 2040 if (status == MagickFalse) 2041 break; 2042 } 2043 quantum_info=DestroyQuantumInfo(quantum_info); 2044 (void) CloseBlob(image); 2045 return(status); 2046 } 2047