Home | History | Annotate | Download | only in coders
      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