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