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-2016 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % http://www.imagemagick.org/script/license.php % 27 % % 28 % Unless required by applicable law or agreed to in writing, software % 29 % distributed under the License is distributed on an "AS IS" BASIS, % 30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31 % See the License for the specific language governing permissions and % 32 % limitations under the License. % 33 % % 34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 % 36 % 37 */ 38 39 /* 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) ResetMagickMemory(&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 offset+=4; 736 dpx.file.ditto_key=ReadBlobLong(image); 737 offset+=4; 738 if (dpx.file.ditto_key != ~0U) 739 (void) FormatImageProperty(image,"dpx:file.ditto.key","%u", 740 dpx.file.ditto_key); 741 dpx.file.generic_size=ReadBlobLong(image); 742 offset+=4; 743 dpx.file.industry_size=ReadBlobLong(image); 744 offset+=4; 745 dpx.file.user_size=ReadBlobLong(image); 746 offset+=4; 747 offset+=ReadBlob(image,sizeof(dpx.file.filename),(unsigned char *) 748 dpx.file.filename); 749 (void) FormatImageProperty(image,"dpx:file.filename","%.100s", 750 dpx.file.filename); 751 (void) FormatImageProperty(image,"document","%.100s",dpx.file.filename); 752 offset+=ReadBlob(image,sizeof(dpx.file.timestamp),(unsigned char *) 753 dpx.file.timestamp); 754 if (*dpx.file.timestamp != '\0') 755 (void) FormatImageProperty(image,"dpx:file.timestamp","%.24s", 756 dpx.file.timestamp); 757 offset+=ReadBlob(image,sizeof(dpx.file.creator),(unsigned char *) 758 dpx.file.creator); 759 if (*dpx.file.creator != '\0') 760 { 761 (void) FormatImageProperty(image,"dpx:file.creator","%.100s", 762 dpx.file.creator); 763 (void) FormatImageProperty(image,"software","%.100s",dpx.file.creator); 764 } 765 offset+=ReadBlob(image,sizeof(dpx.file.project),(unsigned char *) 766 dpx.file.project); 767 if (*dpx.file.project != '\0') 768 { 769 (void) FormatImageProperty(image,"dpx:file.project","%.200s", 770 dpx.file.project); 771 (void) FormatImageProperty(image,"comment","%.100s",dpx.file.project); 772 } 773 offset+=ReadBlob(image,sizeof(dpx.file.copyright),(unsigned char *) 774 dpx.file.copyright); 775 if (*dpx.file.copyright != '\0') 776 { 777 (void) FormatImageProperty(image,"dpx:file.copyright","%.200s", 778 dpx.file.copyright); 779 (void) FormatImageProperty(image,"copyright","%.100s", 780 dpx.file.copyright); 781 } 782 dpx.file.encrypt_key=ReadBlobLong(image); 783 offset+=4; 784 if (dpx.file.encrypt_key != ~0U) 785 (void) FormatImageProperty(image,"dpx:file.encrypt_key","%u", 786 dpx.file.encrypt_key); 787 offset+=ReadBlob(image,sizeof(dpx.file.reserve),(unsigned char *) 788 dpx.file.reserve); 789 /* 790 Read DPX image header. 791 */ 792 dpx.image.orientation=ReadBlobShort(image); 793 if (dpx.image.orientation > 7) 794 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 795 offset+=2; 796 if (dpx.image.orientation != (unsigned short) ~0) 797 (void) FormatImageProperty(image,"dpx:image.orientation","%d", 798 dpx.image.orientation); 799 switch (dpx.image.orientation) 800 { 801 default: 802 case 0: image->orientation=TopLeftOrientation; break; 803 case 1: image->orientation=TopRightOrientation; break; 804 case 2: image->orientation=BottomLeftOrientation; break; 805 case 3: image->orientation=BottomRightOrientation; break; 806 case 4: image->orientation=LeftTopOrientation; break; 807 case 5: image->orientation=RightTopOrientation; break; 808 case 6: image->orientation=LeftBottomOrientation; break; 809 case 7: image->orientation=RightBottomOrientation; break; 810 } 811 dpx.image.number_elements=ReadBlobShort(image); 812 if (dpx.image.number_elements > MaxNumberImageElements) 813 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 814 offset+=2; 815 dpx.image.pixels_per_line=ReadBlobLong(image); 816 offset+=4; 817 image->columns=dpx.image.pixels_per_line; 818 dpx.image.lines_per_element=ReadBlobLong(image); 819 offset+=4; 820 image->rows=dpx.image.lines_per_element; 821 for (i=0; i < 8; i++) 822 { 823 char 824 property[MagickPathExtent]; 825 826 dpx.image.image_element[i].data_sign=ReadBlobLong(image); 827 offset+=4; 828 dpx.image.image_element[i].low_data=ReadBlobLong(image); 829 offset+=4; 830 dpx.image.image_element[i].low_quantity=ReadBlobFloat(image); 831 offset+=4; 832 dpx.image.image_element[i].high_data=ReadBlobLong(image); 833 offset+=4; 834 dpx.image.image_element[i].high_quantity=ReadBlobFloat(image); 835 offset+=4; 836 dpx.image.image_element[i].descriptor=(unsigned char) ReadBlobByte(image); 837 offset++; 838 dpx.image.image_element[i].transfer_characteristic=(unsigned char) 839 ReadBlobByte(image); 840 (void) FormatLocaleString(property,MagickPathExtent, 841 "dpx:image.element[%lu].transfer-characteristic",(long) i); 842 (void) FormatImageProperty(image,property,"%s", 843 GetImageTransferCharacteristic((DPXTransferCharacteristic) 844 dpx.image.image_element[i].transfer_characteristic)); 845 offset++; 846 dpx.image.image_element[i].colorimetric=(unsigned char) ReadBlobByte(image); 847 offset++; 848 dpx.image.image_element[i].bit_size=(unsigned char) ReadBlobByte(image); 849 offset++; 850 dpx.image.image_element[i].packing=ReadBlobShort(image); 851 offset+=2; 852 dpx.image.image_element[i].encoding=ReadBlobShort(image); 853 offset+=2; 854 dpx.image.image_element[i].data_offset=ReadBlobLong(image); 855 offset+=4; 856 dpx.image.image_element[i].end_of_line_padding=ReadBlobLong(image); 857 offset+=4; 858 dpx.image.image_element[i].end_of_image_padding=ReadBlobLong(image); 859 offset+=4; 860 offset+=ReadBlob(image,sizeof(dpx.image.image_element[i].description), 861 (unsigned char *) dpx.image.image_element[i].description); 862 } 863 SetImageColorspace(image,RGBColorspace,exception); 864 offset+=ReadBlob(image,sizeof(dpx.image.reserve),(unsigned char *) 865 dpx.image.reserve); 866 if (dpx.file.image_offset >= 1664U) 867 { 868 /* 869 Read DPX orientation header. 870 */ 871 dpx.orientation.x_offset=ReadBlobLong(image); 872 offset+=4; 873 if (dpx.orientation.x_offset != ~0U) 874 (void) FormatImageProperty(image,"dpx:orientation.x_offset","%u", 875 dpx.orientation.x_offset); 876 dpx.orientation.y_offset=ReadBlobLong(image); 877 offset+=4; 878 if (dpx.orientation.y_offset != ~0U) 879 (void) FormatImageProperty(image,"dpx:orientation.y_offset","%u", 880 dpx.orientation.y_offset); 881 dpx.orientation.x_center=ReadBlobFloat(image); 882 offset+=4; 883 if (IsFloatDefined(dpx.orientation.x_center) != MagickFalse) 884 (void) FormatImageProperty(image,"dpx:orientation.x_center","%g", 885 dpx.orientation.x_center); 886 dpx.orientation.y_center=ReadBlobFloat(image); 887 offset+=4; 888 if (IsFloatDefined(dpx.orientation.y_center) != MagickFalse) 889 (void) FormatImageProperty(image,"dpx:orientation.y_center","%g", 890 dpx.orientation.y_center); 891 dpx.orientation.x_size=ReadBlobLong(image); 892 offset+=4; 893 if (dpx.orientation.x_size != ~0U) 894 (void) FormatImageProperty(image,"dpx:orientation.x_size","%u", 895 dpx.orientation.x_size); 896 dpx.orientation.y_size=ReadBlobLong(image); 897 offset+=4; 898 if (dpx.orientation.y_size != ~0U) 899 (void) FormatImageProperty(image,"dpx:orientation.y_size","%u", 900 dpx.orientation.y_size); 901 offset+=ReadBlob(image,sizeof(dpx.orientation.filename),(unsigned char *) 902 dpx.orientation.filename); 903 if (*dpx.orientation.filename != '\0') 904 (void) FormatImageProperty(image,"dpx:orientation.filename","%.100s", 905 dpx.orientation.filename); 906 offset+=ReadBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *) 907 dpx.orientation.timestamp); 908 if (*dpx.orientation.timestamp != '\0') 909 (void) FormatImageProperty(image,"dpx:orientation.timestamp","%.24s", 910 dpx.orientation.timestamp); 911 offset+=ReadBlob(image,sizeof(dpx.orientation.device),(unsigned char *) 912 dpx.orientation.device); 913 if (*dpx.orientation.device != '\0') 914 (void) FormatImageProperty(image,"dpx:orientation.device","%.32s", 915 dpx.orientation.device); 916 offset+=ReadBlob(image,sizeof(dpx.orientation.serial),(unsigned char *) 917 dpx.orientation.serial); 918 if (*dpx.orientation.serial != '\0') 919 (void) FormatImageProperty(image,"dpx:orientation.serial","%.32s", 920 dpx.orientation.serial); 921 for (i=0; i < 4; i++) 922 { 923 dpx.orientation.border[i]=ReadBlobShort(image); 924 offset+=2; 925 } 926 if ((dpx.orientation.border[0] != (unsigned short) (~0)) && 927 (dpx.orientation.border[1] != (unsigned short) (~0))) 928 (void) FormatImageProperty(image,"dpx:orientation.border","%dx%d%+d%+d", 929 dpx.orientation.border[0],dpx.orientation.border[1], 930 dpx.orientation.border[2],dpx.orientation.border[3]); 931 for (i=0; i < 2; i++) 932 { 933 dpx.orientation.aspect_ratio[i]=ReadBlobLong(image); 934 offset+=4; 935 } 936 if ((dpx.orientation.aspect_ratio[0] != ~0U) && 937 (dpx.orientation.aspect_ratio[1] != ~0U)) 938 (void) FormatImageProperty(image,"dpx:orientation.aspect_ratio", 939 "%ux%u",dpx.orientation.aspect_ratio[0], 940 dpx.orientation.aspect_ratio[1]); 941 offset+=ReadBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *) 942 dpx.orientation.reserve); 943 } 944 if (dpx.file.image_offset >= 1920U) 945 { 946 /* 947 Read DPX film header. 948 */ 949 offset+=ReadBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id); 950 if (*dpx.film.id != '\0') 951 (void) FormatImageProperty(image,"dpx:film.id","%.2s",dpx.film.id); 952 offset+=ReadBlob(image,sizeof(dpx.film.type),(unsigned char *) 953 dpx.film.type); 954 if (*dpx.film.type != '\0') 955 (void) FormatImageProperty(image,"dpx:film.type","%.2s",dpx.film.type); 956 offset+=ReadBlob(image,sizeof(dpx.film.offset),(unsigned char *) 957 dpx.film.offset); 958 if (*dpx.film.offset != '\0') 959 (void) FormatImageProperty(image,"dpx:film.offset","%.2s", 960 dpx.film.offset); 961 offset+=ReadBlob(image,sizeof(dpx.film.prefix),(unsigned char *) 962 dpx.film.prefix); 963 if (*dpx.film.prefix != '\0') 964 (void) FormatImageProperty(image,"dpx:film.prefix","%.6s", 965 dpx.film.prefix); 966 offset+=ReadBlob(image,sizeof(dpx.film.count),(unsigned char *) 967 dpx.film.count); 968 if (*dpx.film.count != '\0') 969 (void) FormatImageProperty(image,"dpx:film.count","%.4s", 970 dpx.film.count); 971 offset+=ReadBlob(image,sizeof(dpx.film.format),(unsigned char *) 972 dpx.film.format); 973 if (*dpx.film.format != '\0') 974 (void) FormatImageProperty(image,"dpx:film.format","%.4s", 975 dpx.film.format); 976 dpx.film.frame_position=ReadBlobLong(image); 977 offset+=4; 978 if (dpx.film.frame_position != ~0U) 979 (void) FormatImageProperty(image,"dpx:film.frame_position","%u", 980 dpx.film.frame_position); 981 dpx.film.sequence_extent=ReadBlobLong(image); 982 offset+=4; 983 if (dpx.film.sequence_extent != ~0U) 984 (void) FormatImageProperty(image,"dpx:film.sequence_extent","%u", 985 dpx.film.sequence_extent); 986 dpx.film.held_count=ReadBlobLong(image); 987 offset+=4; 988 if (dpx.film.held_count != ~0U) 989 (void) FormatImageProperty(image,"dpx:film.held_count","%u", 990 dpx.film.held_count); 991 dpx.film.frame_rate=ReadBlobFloat(image); 992 offset+=4; 993 if (IsFloatDefined(dpx.film.frame_rate) != MagickFalse) 994 (void) FormatImageProperty(image,"dpx:film.frame_rate","%g", 995 dpx.film.frame_rate); 996 dpx.film.shutter_angle=ReadBlobFloat(image); 997 offset+=4; 998 if (IsFloatDefined(dpx.film.shutter_angle) != MagickFalse) 999 (void) FormatImageProperty(image,"dpx:film.shutter_angle","%g", 1000 dpx.film.shutter_angle); 1001 offset+=ReadBlob(image,sizeof(dpx.film.frame_id),(unsigned char *) 1002 dpx.film.frame_id); 1003 if (*dpx.film.frame_id != '\0') 1004 (void) FormatImageProperty(image,"dpx:film.frame_id","%.32s", 1005 dpx.film.frame_id); 1006 offset+=ReadBlob(image,sizeof(dpx.film.slate),(unsigned char *) 1007 dpx.film.slate); 1008 if (*dpx.film.slate != '\0') 1009 (void) FormatImageProperty(image,"dpx:film.slate","%.100s", 1010 dpx.film.slate); 1011 offset+=ReadBlob(image,sizeof(dpx.film.reserve),(unsigned char *) 1012 dpx.film.reserve); 1013 } 1014 if (dpx.file.image_offset >= 2048U) 1015 { 1016 /* 1017 Read DPX television header. 1018 */ 1019 dpx.television.time_code=(unsigned int) ReadBlobLong(image); 1020 offset+=4; 1021 TimeCodeToString(dpx.television.time_code,value); 1022 (void) SetImageProperty(image,"dpx:television.time.code",value,exception); 1023 dpx.television.user_bits=(unsigned int) ReadBlobLong(image); 1024 offset+=4; 1025 TimeCodeToString(dpx.television.user_bits,value); 1026 (void) SetImageProperty(image,"dpx:television.user.bits",value,exception); 1027 dpx.television.interlace=(unsigned char) ReadBlobByte(image); 1028 offset++; 1029 if (dpx.television.interlace != 0) 1030 (void) FormatImageProperty(image,"dpx:television.interlace","%.20g", 1031 (double) dpx.television.interlace); 1032 dpx.television.field_number=(unsigned char) ReadBlobByte(image); 1033 offset++; 1034 if (dpx.television.field_number != 0) 1035 (void) FormatImageProperty(image,"dpx:television.field_number","%.20g", 1036 (double) dpx.television.field_number); 1037 dpx.television.video_signal=(unsigned char) ReadBlobByte(image); 1038 offset++; 1039 if (dpx.television.video_signal != 0) 1040 (void) FormatImageProperty(image,"dpx:television.video_signal","%.20g", 1041 (double) dpx.television.video_signal); 1042 dpx.television.padding=(unsigned char) ReadBlobByte(image); 1043 offset++; 1044 if (dpx.television.padding != 0) 1045 (void) FormatImageProperty(image,"dpx:television.padding","%d", 1046 dpx.television.padding); 1047 dpx.television.horizontal_sample_rate=ReadBlobFloat(image); 1048 offset+=4; 1049 if (IsFloatDefined(dpx.television.horizontal_sample_rate) != MagickFalse) 1050 (void) FormatImageProperty(image, 1051 "dpx:television.horizontal_sample_rate","%g", 1052 dpx.television.horizontal_sample_rate); 1053 dpx.television.vertical_sample_rate=ReadBlobFloat(image); 1054 offset+=4; 1055 if (IsFloatDefined(dpx.television.vertical_sample_rate) != MagickFalse) 1056 (void) FormatImageProperty(image,"dpx:television.vertical_sample_rate", 1057 "%g",dpx.television.vertical_sample_rate); 1058 dpx.television.frame_rate=ReadBlobFloat(image); 1059 offset+=4; 1060 if (IsFloatDefined(dpx.television.frame_rate) != MagickFalse) 1061 (void) FormatImageProperty(image,"dpx:television.frame_rate","%g", 1062 dpx.television.frame_rate); 1063 dpx.television.time_offset=ReadBlobFloat(image); 1064 offset+=4; 1065 if (IsFloatDefined(dpx.television.time_offset) != MagickFalse) 1066 (void) FormatImageProperty(image,"dpx:television.time_offset","%g", 1067 dpx.television.time_offset); 1068 dpx.television.gamma=ReadBlobFloat(image); 1069 offset+=4; 1070 if (IsFloatDefined(dpx.television.gamma) != MagickFalse) 1071 (void) FormatImageProperty(image,"dpx:television.gamma","%g", 1072 dpx.television.gamma); 1073 dpx.television.black_level=ReadBlobFloat(image); 1074 offset+=4; 1075 if (IsFloatDefined(dpx.television.black_level) != MagickFalse) 1076 (void) FormatImageProperty(image,"dpx:television.black_level","%g", 1077 dpx.television.black_level); 1078 dpx.television.black_gain=ReadBlobFloat(image); 1079 offset+=4; 1080 if (IsFloatDefined(dpx.television.black_gain) != MagickFalse) 1081 (void) FormatImageProperty(image,"dpx:television.black_gain","%g", 1082 dpx.television.black_gain); 1083 dpx.television.break_point=ReadBlobFloat(image); 1084 offset+=4; 1085 if (IsFloatDefined(dpx.television.break_point) != MagickFalse) 1086 (void) FormatImageProperty(image,"dpx:television.break_point","%g", 1087 dpx.television.break_point); 1088 dpx.television.white_level=ReadBlobFloat(image); 1089 offset+=4; 1090 if (IsFloatDefined(dpx.television.white_level) != MagickFalse) 1091 (void) FormatImageProperty(image,"dpx:television.white_level","%g", 1092 dpx.television.white_level); 1093 dpx.television.integration_times=ReadBlobFloat(image); 1094 offset+=4; 1095 if (IsFloatDefined(dpx.television.integration_times) != MagickFalse) 1096 (void) FormatImageProperty(image,"dpx:television.integration_times", 1097 "%g",dpx.television.integration_times); 1098 offset+=ReadBlob(image,sizeof(dpx.television.reserve),(unsigned char *) 1099 dpx.television.reserve); 1100 } 1101 if (dpx.file.image_offset > 2080U) 1102 { 1103 /* 1104 Read DPX user header. 1105 */ 1106 offset+=ReadBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id); 1107 if (*dpx.user.id != '\0') 1108 (void) FormatImageProperty(image,"dpx:user.id","%.32s",dpx.user.id); 1109 if ((dpx.file.user_size != ~0U) && 1110 ((size_t) dpx.file.user_size > sizeof(dpx.user.id))) 1111 { 1112 StringInfo 1113 *profile; 1114 1115 profile=BlobToStringInfo((const unsigned char *) NULL, 1116 dpx.file.user_size-sizeof(dpx.user.id)); 1117 if (profile == (StringInfo *) NULL) 1118 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1119 offset+=ReadBlob(image,GetStringInfoLength(profile), 1120 GetStringInfoDatum(profile)); 1121 (void) SetImageProfile(image,"dpx:user-data",profile,exception); 1122 profile=DestroyStringInfo(profile); 1123 } 1124 } 1125 for ( ; offset < (MagickOffsetType) dpx.file.image_offset; offset++) 1126 (void) ReadBlobByte(image); 1127 if (image_info->ping != MagickFalse) 1128 { 1129 (void) CloseBlob(image); 1130 return(GetFirstImageInList(image)); 1131 } 1132 status=SetImageExtent(image,image->columns,image->rows,exception); 1133 if (status == MagickFalse) 1134 return(DestroyImageList(image)); 1135 for (n=0; n < (ssize_t) dpx.image.number_elements; n++) 1136 { 1137 /* 1138 Convert DPX raster image to pixel packets. 1139 */ 1140 if ((dpx.image.image_element[n].data_offset != ~0U) && 1141 (dpx.image.image_element[n].data_offset != 0U)) 1142 { 1143 MagickOffsetType 1144 data_offset; 1145 1146 data_offset=(MagickOffsetType) dpx.image.image_element[n].data_offset; 1147 if (data_offset < offset) 1148 offset=SeekBlob(image,data_offset,SEEK_SET); 1149 else 1150 for ( ; offset < data_offset; offset++) 1151 (void) ReadBlobByte(image); 1152 if (offset != data_offset) 1153 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 1154 } 1155 SetPrimaryChromaticity((DPXColorimetric) 1156 dpx.image.image_element[n].colorimetric,&image->chromaticity); 1157 image->depth=dpx.image.image_element[n].bit_size; 1158 samples_per_pixel=1; 1159 quantum_type=GrayQuantum; 1160 component_type=dpx.image.image_element[n].descriptor; 1161 switch (component_type) 1162 { 1163 case CbYCrY422ComponentType: 1164 { 1165 samples_per_pixel=2; 1166 quantum_type=CbYCrYQuantum; 1167 break; 1168 } 1169 case CbYACrYA4224ComponentType: 1170 case CbYCr444ComponentType: 1171 { 1172 samples_per_pixel=3; 1173 quantum_type=CbYCrQuantum; 1174 break; 1175 } 1176 case RGBComponentType: 1177 { 1178 samples_per_pixel=3; 1179 quantum_type=RGBQuantum; 1180 break; 1181 } 1182 case ABGRComponentType: 1183 case RGBAComponentType: 1184 { 1185 image->alpha_trait=BlendPixelTrait; 1186 samples_per_pixel=4; 1187 quantum_type=RGBAQuantum; 1188 break; 1189 } 1190 default: 1191 break; 1192 } 1193 switch (component_type) 1194 { 1195 case CbYCrY422ComponentType: 1196 case CbYACrYA4224ComponentType: 1197 case CbYCr444ComponentType: 1198 { 1199 SetImageColorspace(image,Rec709YCbCrColorspace,exception); 1200 break; 1201 } 1202 case LumaComponentType: 1203 { 1204 SetImageColorspace(image,GRAYColorspace,exception); 1205 break; 1206 } 1207 default: 1208 { 1209 SetImageColorspace(image,sRGBColorspace,exception); 1210 if (dpx.image.image_element[n].transfer_characteristic == LogarithmicColorimetric) 1211 SetImageColorspace(image,LogColorspace,exception); 1212 if (dpx.image.image_element[n].transfer_characteristic == PrintingDensityColorimetric) 1213 SetImageColorspace(image,LogColorspace,exception); 1214 break; 1215 } 1216 } 1217 extent=GetBytesPerRow(image->columns,samples_per_pixel,image->depth, 1218 dpx.image.image_element[n].packing == 0 ? MagickFalse : MagickTrue); 1219 /* 1220 DPX any-bit pixel format. 1221 */ 1222 status=MagickTrue; 1223 row=0; 1224 quantum_info=AcquireQuantumInfo(image_info,image); 1225 if (quantum_info == (QuantumInfo *) NULL) 1226 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1227 SetQuantumQuantum(quantum_info,32); 1228 SetQuantumPack(quantum_info,dpx.image.image_element[n].packing == 0 ? 1229 MagickTrue : MagickFalse); 1230 for (y=0; y < (ssize_t) image->rows; y++) 1231 { 1232 const unsigned char 1233 *pixels; 1234 1235 MagickBooleanType 1236 sync; 1237 1238 register Quantum 1239 *q; 1240 1241 size_t 1242 length; 1243 1244 ssize_t 1245 count, 1246 offset; 1247 1248 if (status == MagickFalse) 1249 continue; 1250 pixels=(const unsigned char *) ReadBlobStream(image,extent, 1251 GetQuantumPixels(quantum_info),&count); 1252 if (count != (ssize_t) extent) 1253 status=MagickFalse; 1254 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 1255 (image->previous == (Image *) NULL)) 1256 { 1257 MagickBooleanType 1258 proceed; 1259 1260 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row, 1261 image->rows); 1262 if (proceed == MagickFalse) 1263 status=MagickFalse; 1264 } 1265 offset=row++; 1266 q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception); 1267 if (q == (Quantum *) NULL) 1268 { 1269 status=MagickFalse; 1270 continue; 1271 } 1272 length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, 1273 quantum_type,pixels,exception); 1274 (void) length; 1275 sync=SyncAuthenticPixels(image,exception); 1276 if (sync == MagickFalse) 1277 status=MagickFalse; 1278 } 1279 quantum_info=DestroyQuantumInfo(quantum_info); 1280 if (status == MagickFalse) 1281 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 1282 SetQuantumImageType(image,quantum_type); 1283 if (EOFBlob(image) != MagickFalse) 1284 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 1285 image->filename); 1286 if ((i+1) < (ssize_t) dpx.image.number_elements) 1287 { 1288 /* 1289 Allocate next image structure. 1290 */ 1291 AcquireNextImage(image_info,image,exception); 1292 if (GetNextImageInList(image) == (Image *) NULL) 1293 { 1294 image=DestroyImageList(image); 1295 return((Image *) NULL); 1296 } 1297 image=SyncNextImageInList(image); 1298 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 1299 GetBlobSize(image)); 1300 if (status == MagickFalse) 1301 break; 1302 } 1303 } 1304 (void) CloseBlob(image); 1305 return(GetFirstImageInList(image)); 1306 } 1307 1308 /* 1310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1311 % % 1312 % % 1313 % % 1314 % R e g i s t e r D P X I m a g e % 1315 % % 1316 % % 1317 % % 1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1319 % 1320 % RegisterDPXImage() adds properties for the DPX image format to 1321 % the list of supported formats. The properties include the image format 1322 % tag, a method to read and/or write the format, whether the format 1323 % supports the saving of more than one frame to the same file or blob, 1324 % whether the format supports native in-memory I/O, and a brief 1325 % description of the format. 1326 % 1327 % The format of the RegisterDPXImage method is: 1328 % 1329 % size_t RegisterDPXImage(void) 1330 % 1331 */ 1332 ModuleExport size_t RegisterDPXImage(void) 1333 { 1334 MagickInfo 1335 *entry; 1336 1337 static const char 1338 *DPXNote = 1339 { 1340 "Digital Moving Picture Exchange Bitmap, Version 2.0.\n" 1341 "See SMPTE 268M-2003 specification at http://www.smtpe.org\n" 1342 }; 1343 1344 entry=AcquireMagickInfo("DPX","DPX","SMPTE 268M-2003 (DPX 2.0)"); 1345 entry->decoder=(DecodeImageHandler *) ReadDPXImage; 1346 entry->encoder=(EncodeImageHandler *) WriteDPXImage; 1347 entry->magick=(IsImageFormatHandler *) IsDPX; 1348 entry->flags^=CoderAdjoinFlag; 1349 entry->flags|=CoderSeekableStreamFlag; 1350 entry->note=ConstantString(DPXNote); 1351 (void) RegisterMagickInfo(entry); 1352 return(MagickImageCoderSignature); 1353 } 1354 1355 /* 1357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1358 % % 1359 % % 1360 % % 1361 % U n r e g i s t e r D P X I m a g e % 1362 % % 1363 % % 1364 % % 1365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1366 % 1367 % UnregisterDPXImage() removes format registrations made by the 1368 % DPX module from the list of supported formats. 1369 % 1370 % The format of the UnregisterDPXImage method is: 1371 % 1372 % UnregisterDPXImage(void) 1373 % 1374 */ 1375 ModuleExport void UnregisterDPXImage(void) 1376 { 1377 (void) UnregisterMagickInfo("DPX"); 1378 } 1379 1380 /* 1382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1383 % % 1384 % % 1385 % % 1386 % W r i t e D P X I m a g e % 1387 % % 1388 % % 1389 % % 1390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1391 % 1392 % WriteDPXImage() writes an image in DPX encoded image format. 1393 % 1394 % The format of the WriteDPXImage method is: 1395 % 1396 % MagickBooleanType WriteDPXImage(const ImageInfo *image_info, 1397 % Image *image,ExceptionInfo *exception) 1398 % 1399 % A description of each parameter follows. 1400 % 1401 % o image_info: the image info. 1402 % 1403 % o image: The image. 1404 % 1405 % o exception: return any errors or warnings in this structure. 1406 % 1407 */ 1408 1409 static unsigned int StringToTimeCode(const char *key) 1410 { 1411 char 1412 buffer[2]; 1413 1414 register ssize_t 1415 i; 1416 1417 unsigned int 1418 shift, 1419 value; 1420 1421 value=0; 1422 shift=28; 1423 buffer[1]='\0'; 1424 for (i=0; (*key != 0) && (i < 11); i++) 1425 { 1426 if (isxdigit((int) ((unsigned char) *key)) == 0) 1427 { 1428 key++; 1429 continue; 1430 } 1431 buffer[0]=(*key++); 1432 value|=(unsigned int) ((strtol(buffer,(char **) NULL,16)) << shift); 1433 shift-=4; 1434 } 1435 return(value); 1436 } 1437 1438 static inline const char *GetDPXProperty(const Image *image, 1439 const char *property,ExceptionInfo *exception) 1440 { 1441 const char 1442 *value; 1443 1444 value=GetImageArtifact(image,property); 1445 if (value != (const char *) NULL) 1446 return(value); 1447 return(GetImageProperty(image,property,exception)); 1448 } 1449 1450 static MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image, 1451 ExceptionInfo *exception) 1452 { 1453 const char 1454 *value; 1455 1456 const StringInfo 1457 *profile; 1458 1459 DPXInfo 1460 dpx; 1461 1462 GeometryInfo 1463 geometry_info; 1464 1465 MagickBooleanType 1466 status; 1467 1468 MagickOffsetType 1469 offset; 1470 1471 MagickStatusType 1472 flags; 1473 1474 QuantumInfo 1475 *quantum_info; 1476 1477 QuantumType 1478 quantum_type; 1479 1480 register const Quantum 1481 *p; 1482 1483 register ssize_t 1484 i; 1485 1486 size_t 1487 extent; 1488 1489 ssize_t 1490 count, 1491 horizontal_factor, 1492 vertical_factor, 1493 y; 1494 1495 time_t 1496 seconds; 1497 1498 unsigned char 1499 *pixels; 1500 1501 /* 1502 Open output image file. 1503 */ 1504 assert(image_info != (const ImageInfo *) NULL); 1505 assert(image_info->signature == MagickCoreSignature); 1506 assert(image != (Image *) NULL); 1507 assert(image->signature == MagickCoreSignature); 1508 if (image->debug != MagickFalse) 1509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1510 horizontal_factor=4; 1511 vertical_factor=4; 1512 if (image_info->sampling_factor != (char *) NULL) 1513 { 1514 flags=ParseGeometry(image_info->sampling_factor,&geometry_info); 1515 horizontal_factor=(ssize_t) geometry_info.rho; 1516 vertical_factor=(ssize_t) geometry_info.sigma; 1517 if ((flags & SigmaValue) == 0) 1518 vertical_factor=horizontal_factor; 1519 if ((horizontal_factor != 1) && (horizontal_factor != 2) && 1520 (horizontal_factor != 4) && (vertical_factor != 1) && 1521 (vertical_factor != 2) && (vertical_factor != 4)) 1522 ThrowWriterException(CorruptImageError,"UnexpectedSamplingFactor"); 1523 } 1524 if ((image->colorspace == YCbCrColorspace) && 1525 ((horizontal_factor == 2) || (vertical_factor == 2))) 1526 if ((image->columns % 2) != 0) 1527 image->columns++; 1528 assert(exception != (ExceptionInfo *) NULL); 1529 assert(exception->signature == MagickCoreSignature); 1530 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 1531 if (status == MagickFalse) 1532 return(status); 1533 /* 1534 Write file header. 1535 */ 1536 (void) ResetMagickMemory(&dpx,0,sizeof(dpx)); 1537 offset=0; 1538 dpx.file.magic=0x53445058U; 1539 offset+=WriteBlobLong(image,dpx.file.magic); 1540 dpx.file.image_offset=0x2000U; 1541 profile=GetImageProfile(image,"dpx:user-data"); 1542 if (profile != (StringInfo *) NULL) 1543 { 1544 if (GetStringInfoLength(profile) > 1048576) 1545 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); 1546 dpx.file.image_offset+=(unsigned int) GetStringInfoLength(profile); 1547 dpx.file.image_offset=(((dpx.file.image_offset+0x2000-1)/0x2000)*0x2000); 1548 } 1549 offset+=WriteBlobLong(image,dpx.file.image_offset); 1550 (void) strncpy(dpx.file.version,"V2.0",sizeof(dpx.file.version)-1); 1551 offset+=WriteBlob(image,8,(unsigned char *) &dpx.file.version); 1552 dpx.file.file_size=(unsigned int) (4U*image->columns*image->rows+ 1553 dpx.file.image_offset); 1554 offset+=WriteBlobLong(image,dpx.file.file_size); 1555 dpx.file.ditto_key=1U; /* new frame */ 1556 offset+=WriteBlobLong(image,dpx.file.ditto_key); 1557 dpx.file.generic_size=0x00000680U; 1558 offset+=WriteBlobLong(image,dpx.file.generic_size); 1559 dpx.file.industry_size=0x00000180U; 1560 offset+=WriteBlobLong(image,dpx.file.industry_size); 1561 dpx.file.user_size=0; 1562 if (profile != (StringInfo *) NULL) 1563 { 1564 dpx.file.user_size+=(unsigned int) GetStringInfoLength(profile); 1565 dpx.file.user_size=(((dpx.file.user_size+0x2000-1)/0x2000)*0x2000); 1566 } 1567 offset+=WriteBlobLong(image,dpx.file.user_size); 1568 value=GetDPXProperty(image,"dpx:file.filename",exception); 1569 if (value != (const char *) NULL) 1570 (void) strncpy(dpx.file.filename,value,sizeof(dpx.file.filename)-1); 1571 offset+=WriteBlob(image,sizeof(dpx.file.filename),(unsigned char *) 1572 dpx.file.filename); 1573 seconds=time((time_t *) NULL); 1574 (void) FormatMagickTime(seconds,sizeof(dpx.file.timestamp), 1575 dpx.file.timestamp); 1576 offset+=WriteBlob(image,sizeof(dpx.file.timestamp),(unsigned char *) 1577 dpx.file.timestamp); 1578 (void) strncpy(dpx.file.creator,GetMagickVersion((size_t *) NULL), 1579 sizeof(dpx.file.creator)-1); 1580 value=GetDPXProperty(image,"dpx:file.creator",exception); 1581 if (value != (const char *) NULL) 1582 (void) strncpy(dpx.file.creator,value,sizeof(dpx.file.creator)-1); 1583 offset+=WriteBlob(image,sizeof(dpx.file.creator),(unsigned char *) 1584 dpx.file.creator); 1585 value=GetDPXProperty(image,"dpx:file.project",exception); 1586 if (value != (const char *) NULL) 1587 (void) strncpy(dpx.file.project,value,sizeof(dpx.file.project)-1); 1588 offset+=WriteBlob(image,sizeof(dpx.file.project),(unsigned char *) 1589 dpx.file.project); 1590 value=GetDPXProperty(image,"dpx:file.copyright",exception); 1591 if (value != (const char *) NULL) 1592 (void) strncpy(dpx.file.copyright,value,sizeof(dpx.file.copyright)-1); 1593 offset+=WriteBlob(image,sizeof(dpx.file.copyright),(unsigned char *) 1594 dpx.file.copyright); 1595 dpx.file.encrypt_key=(~0U); 1596 offset+=WriteBlobLong(image,dpx.file.encrypt_key); 1597 offset+=WriteBlob(image,sizeof(dpx.file.reserve),(unsigned char *) 1598 dpx.file.reserve); 1599 /* 1600 Write image header. 1601 */ 1602 switch (image->orientation) 1603 { 1604 default: 1605 case TopLeftOrientation: dpx.image.orientation=0; break; 1606 case TopRightOrientation: dpx.image.orientation=1; break; 1607 case BottomLeftOrientation: dpx.image.orientation=2; break; 1608 case BottomRightOrientation: dpx.image.orientation=3; break; 1609 case LeftTopOrientation: dpx.image.orientation=4; break; 1610 case RightTopOrientation: dpx.image.orientation=5; break; 1611 case LeftBottomOrientation: dpx.image.orientation=6; break; 1612 case RightBottomOrientation: dpx.image.orientation=7; break; 1613 } 1614 offset+=WriteBlobShort(image,dpx.image.orientation); 1615 dpx.image.number_elements=1; 1616 offset+=WriteBlobShort(image,dpx.image.number_elements); 1617 if ((image->columns != (unsigned int) image->columns) || 1618 (image->rows != (unsigned int) image->rows)) 1619 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); 1620 offset+=WriteBlobLong(image,(unsigned int) image->columns); 1621 offset+=WriteBlobLong(image,(unsigned int) image->rows); 1622 for (i=0; i < 8; i++) 1623 { 1624 dpx.image.image_element[i].data_sign=0U; 1625 offset+=WriteBlobLong(image,dpx.image.image_element[i].data_sign); 1626 dpx.image.image_element[i].low_data=0U; 1627 offset+=WriteBlobLong(image,dpx.image.image_element[i].low_data); 1628 dpx.image.image_element[i].low_quantity=0.0f; 1629 offset+=WriteBlobFloat(image,dpx.image.image_element[i].low_quantity); 1630 dpx.image.image_element[i].high_data=0U; 1631 offset+=WriteBlobLong(image,dpx.image.image_element[i].high_data); 1632 dpx.image.image_element[i].high_quantity=0.0f; 1633 offset+=WriteBlobFloat(image,dpx.image.image_element[i].high_quantity); 1634 dpx.image.image_element[i].descriptor=0; 1635 if (i == 0) 1636 switch (image->colorspace) 1637 { 1638 case Rec601YCbCrColorspace: 1639 case Rec709YCbCrColorspace: 1640 case YCbCrColorspace: 1641 { 1642 dpx.image.image_element[i].descriptor=CbYCr444ComponentType; 1643 if (image->alpha_trait != UndefinedPixelTrait) 1644 dpx.image.image_element[i].descriptor=CbYCrA4444ComponentType; 1645 break; 1646 } 1647 default: 1648 { 1649 dpx.image.image_element[i].descriptor=RGBComponentType; 1650 if (image->alpha_trait != UndefinedPixelTrait) 1651 dpx.image.image_element[i].descriptor=RGBAComponentType; 1652 if ((image_info->type != TrueColorType) && 1653 (image->alpha_trait == UndefinedPixelTrait) && 1654 (SetImageGray(image,exception) != MagickFalse)) 1655 dpx.image.image_element[i].descriptor=LumaComponentType; 1656 break; 1657 } 1658 } 1659 offset+=WriteBlobByte(image,dpx.image.image_element[i].descriptor); 1660 dpx.image.image_element[i].transfer_characteristic=0; 1661 if (image->colorspace == LogColorspace) 1662 dpx.image.image_element[0].transfer_characteristic= 1663 PrintingDensityColorimetric; 1664 offset+=WriteBlobByte(image, 1665 dpx.image.image_element[i].transfer_characteristic); 1666 dpx.image.image_element[i].colorimetric=0; 1667 offset+=WriteBlobByte(image,dpx.image.image_element[i].colorimetric); 1668 dpx.image.image_element[i].bit_size=0; 1669 if (i == 0) 1670 dpx.image.image_element[i].bit_size=(unsigned char) image->depth; 1671 offset+=WriteBlobByte(image,dpx.image.image_element[i].bit_size); 1672 dpx.image.image_element[i].packing=0; 1673 if ((image->depth == 10) || (image->depth == 12)) 1674 dpx.image.image_element[i].packing=1; 1675 offset+=WriteBlobShort(image,dpx.image.image_element[i].packing); 1676 dpx.image.image_element[i].encoding=0; 1677 offset+=WriteBlobShort(image,dpx.image.image_element[i].encoding); 1678 dpx.image.image_element[i].data_offset=0U; 1679 if (i == 0) 1680 dpx.image.image_element[i].data_offset=dpx.file.image_offset; 1681 offset+=WriteBlobLong(image,dpx.image.image_element[i].data_offset); 1682 dpx.image.image_element[i].end_of_line_padding=0U; 1683 offset+=WriteBlobLong(image,dpx.image.image_element[i].end_of_line_padding); 1684 offset+=WriteBlobLong(image, 1685 dpx.image.image_element[i].end_of_image_padding); 1686 offset+=WriteBlob(image,sizeof(dpx.image.image_element[i].description), 1687 (unsigned char *) dpx.image.image_element[i].description); 1688 } 1689 offset+=WriteBlob(image,sizeof(dpx.image.reserve),(unsigned char *) 1690 dpx.image.reserve); 1691 /* 1692 Write orientation header. 1693 */ 1694 if ((image->rows != image->magick_rows) || 1695 (image->columns != image->magick_columns)) 1696 { 1697 /* 1698 These properties are not valid if image size changed. 1699 */ 1700 (void) DeleteImageProperty(image,"dpx:orientation.x_offset"); 1701 (void) DeleteImageProperty(image,"dpx:orientation.y_offset"); 1702 (void) DeleteImageProperty(image,"dpx:orientation.x_center"); 1703 (void) DeleteImageProperty(image,"dpx:orientation.y_center"); 1704 (void) DeleteImageProperty(image,"dpx:orientation.x_size"); 1705 (void) DeleteImageProperty(image,"dpx:orientation.y_size"); 1706 } 1707 dpx.orientation.x_offset=0U; 1708 value=GetDPXProperty(image,"dpx:orientation.x_offset",exception); 1709 if (value != (const char *) NULL) 1710 dpx.orientation.x_offset=(unsigned int) StringToUnsignedLong(value); 1711 offset+=WriteBlobLong(image,dpx.orientation.x_offset); 1712 dpx.orientation.y_offset=0U; 1713 value=GetDPXProperty(image,"dpx:orientation.y_offset",exception); 1714 if (value != (const char *) NULL) 1715 dpx.orientation.y_offset=(unsigned int) StringToUnsignedLong(value); 1716 offset+=WriteBlobLong(image,dpx.orientation.y_offset); 1717 dpx.orientation.x_center=0.0f; 1718 value=GetDPXProperty(image,"dpx:orientation.x_center",exception); 1719 if (value != (const char *) NULL) 1720 dpx.orientation.x_center=StringToDouble(value,(char **) NULL); 1721 offset+=WriteBlobFloat(image,dpx.orientation.x_center); 1722 dpx.orientation.y_center=0.0f; 1723 value=GetDPXProperty(image,"dpx:orientation.y_center",exception); 1724 if (value != (const char *) NULL) 1725 dpx.orientation.y_center=StringToDouble(value,(char **) NULL); 1726 offset+=WriteBlobFloat(image,dpx.orientation.y_center); 1727 dpx.orientation.x_size=0U; 1728 value=GetDPXProperty(image,"dpx:orientation.x_size",exception); 1729 if (value != (const char *) NULL) 1730 dpx.orientation.x_size=(unsigned int) StringToUnsignedLong(value); 1731 offset+=WriteBlobLong(image,dpx.orientation.x_size); 1732 dpx.orientation.y_size=0U; 1733 value=GetDPXProperty(image,"dpx:orientation.y_size",exception); 1734 if (value != (const char *) NULL) 1735 dpx.orientation.y_size=(unsigned int) StringToUnsignedLong(value); 1736 offset+=WriteBlobLong(image,dpx.orientation.y_size); 1737 value=GetDPXProperty(image,"dpx:orientation.filename",exception); 1738 if (value != (const char *) NULL) 1739 (void) strncpy(dpx.orientation.filename,value, 1740 sizeof(dpx.orientation.filename)-1); 1741 offset+=WriteBlob(image,sizeof(dpx.orientation.filename),(unsigned char *) 1742 dpx.orientation.filename); 1743 offset+=WriteBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *) 1744 dpx.orientation.timestamp); 1745 value=GetDPXProperty(image,"dpx:orientation.device",exception); 1746 if (value != (const char *) NULL) 1747 (void) strncpy(dpx.orientation.device,value, 1748 sizeof(dpx.orientation.device)-1); 1749 offset+=WriteBlob(image,sizeof(dpx.orientation.device),(unsigned char *) 1750 dpx.orientation.device); 1751 value=GetDPXProperty(image,"dpx:orientation.serial",exception); 1752 if (value != (const char *) NULL) 1753 (void) strncpy(dpx.orientation.serial,value, 1754 sizeof(dpx.orientation.serial)-1); 1755 offset+=WriteBlob(image,sizeof(dpx.orientation.serial),(unsigned char *) 1756 dpx.orientation.serial); 1757 for (i=0; i < 4; i++) 1758 dpx.orientation.border[i]=0; 1759 value=GetDPXProperty(image,"dpx:orientation.border",exception); 1760 if (value != (const char *) NULL) 1761 { 1762 flags=ParseGeometry(value,&geometry_info); 1763 if ((flags & SigmaValue) == 0) 1764 geometry_info.sigma=geometry_info.rho; 1765 dpx.orientation.border[0]=(unsigned short) (geometry_info.rho+0.5); 1766 dpx.orientation.border[1]=(unsigned short) (geometry_info.sigma+0.5); 1767 dpx.orientation.border[2]=(unsigned short) (geometry_info.xi+0.5); 1768 dpx.orientation.border[3]=(unsigned short) (geometry_info.psi+0.5); 1769 } 1770 for (i=0; i < 4; i++) 1771 offset+=WriteBlobShort(image,dpx.orientation.border[i]); 1772 for (i=0; i < 2; i++) 1773 dpx.orientation.aspect_ratio[i]=0U; 1774 value=GetDPXProperty(image,"dpx:orientation.aspect_ratio",exception); 1775 if (value != (const char *) NULL) 1776 { 1777 flags=ParseGeometry(value,&geometry_info); 1778 if ((flags & SigmaValue) == 0) 1779 geometry_info.sigma=geometry_info.rho; 1780 dpx.orientation.aspect_ratio[0]=(unsigned int) (geometry_info.rho+0.5); 1781 dpx.orientation.aspect_ratio[1]=(unsigned int) (geometry_info.sigma+0.5); 1782 } 1783 for (i=0; i < 2; i++) 1784 offset+=WriteBlobLong(image,dpx.orientation.aspect_ratio[i]); 1785 offset+=WriteBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *) 1786 dpx.orientation.reserve); 1787 /* 1788 Write film header. 1789 */ 1790 (void) ResetMagickMemory(dpx.film.id,0,sizeof(dpx.film.id)); 1791 value=GetDPXProperty(image,"dpx:film.id",exception); 1792 if (value != (const char *) NULL) 1793 (void) strncpy(dpx.film.id,value,sizeof(dpx.film.id)-1); 1794 offset+=WriteBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id); 1795 (void) ResetMagickMemory(dpx.film.type,0,sizeof(dpx.film.type)); 1796 value=GetDPXProperty(image,"dpx:film.type",exception); 1797 if (value != (const char *) NULL) 1798 (void) strncpy(dpx.film.type,value,sizeof(dpx.film.type)-1); 1799 offset+=WriteBlob(image,sizeof(dpx.film.type),(unsigned char *) 1800 dpx.film.type); 1801 (void) ResetMagickMemory(dpx.film.offset,0,sizeof(dpx.film.offset)); 1802 value=GetDPXProperty(image,"dpx:film.offset",exception); 1803 if (value != (const char *) NULL) 1804 (void) strncpy(dpx.film.offset,value,sizeof(dpx.film.offset)-1); 1805 offset+=WriteBlob(image,sizeof(dpx.film.offset),(unsigned char *) 1806 dpx.film.offset); 1807 (void) ResetMagickMemory(dpx.film.prefix,0,sizeof(dpx.film.prefix)); 1808 value=GetDPXProperty(image,"dpx:film.prefix",exception); 1809 if (value != (const char *) NULL) 1810 (void) strncpy(dpx.film.prefix,value,sizeof(dpx.film.prefix)-1); 1811 offset+=WriteBlob(image,sizeof(dpx.film.prefix),(unsigned char *) 1812 dpx.film.prefix); 1813 (void) ResetMagickMemory(dpx.film.count,0,sizeof(dpx.film.count)); 1814 value=GetDPXProperty(image,"dpx:film.count",exception); 1815 if (value != (const char *) NULL) 1816 (void) strncpy(dpx.film.count,value,sizeof(dpx.film.count)-1); 1817 offset+=WriteBlob(image,sizeof(dpx.film.count),(unsigned char *) 1818 dpx.film.count); 1819 (void) ResetMagickMemory(dpx.film.format,0,sizeof(dpx.film.format)); 1820 value=GetDPXProperty(image,"dpx:film.format",exception); 1821 if (value != (const char *) NULL) 1822 (void) strncpy(dpx.film.format,value,sizeof(dpx.film.format)-1); 1823 offset+=WriteBlob(image,sizeof(dpx.film.format),(unsigned char *) 1824 dpx.film.format); 1825 dpx.film.frame_position=0U; 1826 value=GetDPXProperty(image,"dpx:film.frame_position",exception); 1827 if (value != (const char *) NULL) 1828 dpx.film.frame_position=(unsigned int) StringToUnsignedLong(value); 1829 offset+=WriteBlobLong(image,dpx.film.frame_position); 1830 dpx.film.sequence_extent=0U; 1831 value=GetDPXProperty(image,"dpx:film.sequence_extent",exception); 1832 if (value != (const char *) NULL) 1833 dpx.film.sequence_extent=(unsigned int) StringToUnsignedLong(value); 1834 offset+=WriteBlobLong(image,dpx.film.sequence_extent); 1835 dpx.film.held_count=0U; 1836 value=GetDPXProperty(image,"dpx:film.held_count",exception); 1837 if (value != (const char *) NULL) 1838 dpx.film.held_count=(unsigned int) StringToUnsignedLong(value); 1839 offset+=WriteBlobLong(image,dpx.film.held_count); 1840 dpx.film.frame_rate=0.0f; 1841 value=GetDPXProperty(image,"dpx:film.frame_rate",exception); 1842 if (value != (const char *) NULL) 1843 dpx.film.frame_rate=StringToDouble(value,(char **) NULL); 1844 offset+=WriteBlobFloat(image,dpx.film.frame_rate); 1845 dpx.film.shutter_angle=0.0f; 1846 value=GetDPXProperty(image,"dpx:film.shutter_angle",exception); 1847 if (value != (const char *) NULL) 1848 dpx.film.shutter_angle=StringToDouble(value,(char **) NULL); 1849 offset+=WriteBlobFloat(image,dpx.film.shutter_angle); 1850 (void) ResetMagickMemory(dpx.film.frame_id,0,sizeof(dpx.film.frame_id)); 1851 value=GetDPXProperty(image,"dpx:film.frame_id",exception); 1852 if (value != (const char *) NULL) 1853 (void) strncpy(dpx.film.frame_id,value,sizeof(dpx.film.frame_id)-1); 1854 offset+=WriteBlob(image,sizeof(dpx.film.frame_id),(unsigned char *) 1855 dpx.film.frame_id); 1856 value=GetDPXProperty(image,"dpx:film.slate",exception); 1857 if (value != (const char *) NULL) 1858 (void) strncpy(dpx.film.slate,value,sizeof(dpx.film.slate)-1); 1859 offset+=WriteBlob(image,sizeof(dpx.film.slate),(unsigned char *) 1860 dpx.film.slate); 1861 offset+=WriteBlob(image,sizeof(dpx.film.reserve),(unsigned char *) 1862 dpx.film.reserve); 1863 /* 1864 Write television header. 1865 */ 1866 value=GetDPXProperty(image,"dpx:television.time.code",exception); 1867 if (value != (const char *) NULL) 1868 dpx.television.time_code=StringToTimeCode(value); 1869 offset+=WriteBlobLong(image,dpx.television.time_code); 1870 value=GetDPXProperty(image,"dpx:television.user.bits",exception); 1871 if (value != (const char *) NULL) 1872 dpx.television.user_bits=StringToTimeCode(value); 1873 offset+=WriteBlobLong(image,dpx.television.user_bits); 1874 value=GetDPXProperty(image,"dpx:television.interlace",exception); 1875 if (value != (const char *) NULL) 1876 dpx.television.interlace=(unsigned char) StringToLong(value); 1877 offset+=WriteBlobByte(image,dpx.television.interlace); 1878 value=GetDPXProperty(image,"dpx:television.field_number",exception); 1879 if (value != (const char *) NULL) 1880 dpx.television.field_number=(unsigned char) StringToLong(value); 1881 offset+=WriteBlobByte(image,dpx.television.field_number); 1882 dpx.television.video_signal=0; 1883 value=GetDPXProperty(image,"dpx:television.video_signal",exception); 1884 if (value != (const char *) NULL) 1885 dpx.television.video_signal=(unsigned char) StringToLong(value); 1886 offset+=WriteBlobByte(image,dpx.television.video_signal); 1887 dpx.television.padding=0; 1888 value=GetDPXProperty(image,"dpx:television.padding",exception); 1889 if (value != (const char *) NULL) 1890 dpx.television.padding=(unsigned char) StringToLong(value); 1891 offset+=WriteBlobByte(image,dpx.television.padding); 1892 dpx.television.horizontal_sample_rate=0.0f; 1893 value=GetDPXProperty(image,"dpx:television.horizontal_sample_rate", 1894 exception); 1895 if (value != (const char *) NULL) 1896 dpx.television.horizontal_sample_rate=StringToDouble(value,(char **) NULL); 1897 offset+=WriteBlobFloat(image,dpx.television.horizontal_sample_rate); 1898 dpx.television.vertical_sample_rate=0.0f; 1899 value=GetDPXProperty(image,"dpx:television.vertical_sample_rate",exception); 1900 if (value != (const char *) NULL) 1901 dpx.television.vertical_sample_rate=StringToDouble(value,(char **) NULL); 1902 offset+=WriteBlobFloat(image,dpx.television.vertical_sample_rate); 1903 dpx.television.frame_rate=0.0f; 1904 value=GetDPXProperty(image,"dpx:television.frame_rate",exception); 1905 if (value != (const char *) NULL) 1906 dpx.television.frame_rate=StringToDouble(value,(char **) NULL); 1907 offset+=WriteBlobFloat(image,dpx.television.frame_rate); 1908 dpx.television.time_offset=0.0f; 1909 value=GetDPXProperty(image,"dpx:television.time_offset",exception); 1910 if (value != (const char *) NULL) 1911 dpx.television.time_offset=StringToDouble(value,(char **) NULL); 1912 offset+=WriteBlobFloat(image,dpx.television.time_offset); 1913 dpx.television.gamma=0.0f; 1914 value=GetDPXProperty(image,"dpx:television.gamma",exception); 1915 if (value != (const char *) NULL) 1916 dpx.television.gamma=StringToDouble(value,(char **) NULL); 1917 offset+=WriteBlobFloat(image,dpx.television.gamma); 1918 dpx.television.black_level=0.0f; 1919 value=GetDPXProperty(image,"dpx:television.black_level",exception); 1920 if (value != (const char *) NULL) 1921 dpx.television.black_level=StringToDouble(value,(char **) NULL); 1922 offset+=WriteBlobFloat(image,dpx.television.black_level); 1923 dpx.television.black_gain=0.0f; 1924 value=GetDPXProperty(image,"dpx:television.black_gain",exception); 1925 if (value != (const char *) NULL) 1926 dpx.television.black_gain=StringToDouble(value,(char **) NULL); 1927 offset+=WriteBlobFloat(image,dpx.television.black_gain); 1928 dpx.television.break_point=0.0f; 1929 value=GetDPXProperty(image,"dpx:television.break_point",exception); 1930 if (value != (const char *) NULL) 1931 dpx.television.break_point=StringToDouble(value,(char **) NULL); 1932 offset+=WriteBlobFloat(image,dpx.television.break_point); 1933 dpx.television.white_level=0.0f; 1934 value=GetDPXProperty(image,"dpx:television.white_level",exception); 1935 if (value != (const char *) NULL) 1936 dpx.television.white_level=StringToDouble(value,(char **) NULL); 1937 offset+=WriteBlobFloat(image,dpx.television.white_level); 1938 dpx.television.integration_times=0.0f; 1939 value=GetDPXProperty(image,"dpx:television.integration_times",exception); 1940 if (value != (const char *) NULL) 1941 dpx.television.integration_times=StringToDouble(value,(char **) NULL); 1942 offset+=WriteBlobFloat(image,dpx.television.integration_times); 1943 offset+=WriteBlob(image,sizeof(dpx.television.reserve),(unsigned char *) 1944 dpx.television.reserve); 1945 /* 1946 Write user header. 1947 */ 1948 value=GetDPXProperty(image,"dpx:user.id",exception); 1949 if (value != (const char *) NULL) 1950 (void) strncpy(dpx.user.id,value,sizeof(dpx.user.id)-1); 1951 offset+=WriteBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id); 1952 if (profile != (StringInfo *) NULL) 1953 offset+=WriteBlob(image,GetStringInfoLength(profile), 1954 GetStringInfoDatum(profile)); 1955 while (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset) 1956 { 1957 count=WriteBlobByte(image,0x00); 1958 if (count != 1) 1959 { 1960 ThrowFileException(exception,FileOpenError,"UnableToWriteFile", 1961 image->filename); 1962 break; 1963 } 1964 offset+=count; 1965 } 1966 /* 1967 Convert pixel packets to DPX raster image. 1968 */ 1969 quantum_info=AcquireQuantumInfo(image_info,image); 1970 SetQuantumQuantum(quantum_info,32); 1971 SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ? 1972 MagickTrue : MagickFalse); 1973 quantum_type=RGBQuantum; 1974 if (image->alpha_trait != UndefinedPixelTrait) 1975 quantum_type=RGBAQuantum; 1976 if (image->colorspace == YCbCrColorspace) 1977 { 1978 quantum_type=CbYCrQuantum; 1979 if (image->alpha_trait != UndefinedPixelTrait) 1980 quantum_type=CbYCrAQuantum; 1981 if ((horizontal_factor == 2) || (vertical_factor == 2)) 1982 quantum_type=CbYCrYQuantum; 1983 } 1984 extent=GetBytesPerRow(image->columns, 1985 image->alpha_trait != UndefinedPixelTrait ? 4UL : 3UL,image->depth, 1986 dpx.image.image_element[0].packing == 0 ? MagickFalse : MagickTrue); 1987 if ((image_info->type != TrueColorType) && 1988 (image->alpha_trait == UndefinedPixelTrait) && 1989 (SetImageGray(image,exception) != MagickFalse)) 1990 { 1991 quantum_type=GrayQuantum; 1992 extent=GetBytesPerRow(image->columns,1UL,image->depth, 1993 dpx.image.image_element[0].packing == 0 ? MagickFalse : MagickTrue); 1994 } 1995 pixels=(unsigned char *) GetQuantumPixels(quantum_info); 1996 for (y=0; y < (ssize_t) image->rows; y++) 1997 { 1998 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1999 if (p == (const Quantum *) NULL) 2000 break; 2001 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, 2002 quantum_type,pixels,exception); 2003 count=WriteBlob(image,extent,pixels); 2004 if (count != (ssize_t) extent) 2005 break; 2006 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 2007 image->rows); 2008 if (status == MagickFalse) 2009 break; 2010 } 2011 quantum_info=DestroyQuantumInfo(quantum_info); 2012 (void) CloseBlob(image); 2013 return(status); 2014 } 2015