Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                             CCCC  IIIII  N   N                              %
      7 %                            C        I    NN  N                              %
      8 %                            C        I    N N N                              %
      9 %                            C        I    N  NN                              %
     10 %                             CCCC  IIIII  N   N                              %
     11 %                                                                             %
     12 %                                                                             %
     13 %                    Read/Write Kodak Cineon Image Format                     %
     14 %                Cineon Image Format is a subset of SMTPE CIN                 %
     15 %                                                                             %
     16 %                                                                             %
     17 %                              Software Design                                %
     18 %                                   Cristy                                    %
     19 %                             Kelly Bergougnoux                               %
     20 %                               October 2003                                  %
     21 %                                                                             %
     22 %                                                                             %
     23 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     24 %  dedicated to making software imaging solutions freely available.           %
     25 %                                                                             %
     26 %  You may not use this file except in compliance with the License.  You may  %
     27 %  obtain a copy of the License at                                            %
     28 %                                                                             %
     29 %    http://www.imagemagick.org/script/license.php                            %
     30 %                                                                             %
     31 %  Unless required by applicable law or agreed to in writing, software        %
     32 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     33 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     34 %  See the License for the specific language governing permissions and        %
     35 %  limitations under the License.                                             %
     36 %                                                                             %
     37 %                                                                             %
     38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     39 %
     40 %  Cineon image file format draft is available at
     41 %  http://www.cineon.com/ff_draft.php.
     42 %
     43 %
     44 */
     45 
     46 /*
     48   Include declarations.
     49 */
     50 #include "MagickCore/studio.h"
     51 #include "MagickCore/artifact.h"
     52 #include "MagickCore/blob.h"
     53 #include "MagickCore/blob-private.h"
     54 #include "MagickCore/cache.h"
     55 #include "MagickCore/colorspace.h"
     56 #include "MagickCore/exception.h"
     57 #include "MagickCore/exception-private.h"
     58 #include "MagickCore/image.h"
     59 #include "MagickCore/image-private.h"
     60 #include "MagickCore/list.h"
     61 #include "MagickCore/magick.h"
     62 #include "MagickCore/memory_.h"
     63 #include "MagickCore/monitor.h"
     64 #include "MagickCore/monitor-private.h"
     65 #include "MagickCore/option.h"
     66 #include "MagickCore/profile.h"
     67 #include "MagickCore/property.h"
     68 #include "MagickCore/quantum-private.h"
     69 #include "MagickCore/quantum-private.h"
     70 #include "MagickCore/static.h"
     71 #include "MagickCore/string_.h"
     72 #include "MagickCore/string-private.h"
     73 #include "MagickCore/module.h"
     74 
     75 /*
     77   Typedef declaration.
     78 */
     79 typedef struct _CINDataFormatInfo
     80 {
     81   unsigned char
     82     interleave,
     83     packing,
     84     sign,
     85     sense;
     86 
     87   size_t
     88     line_pad,
     89     channel_pad;
     90 
     91   unsigned char
     92     reserve[20];
     93 } CINDataFormatInfo;
     94 
     95 typedef struct _CINFileInfo
     96 {
     97   size_t
     98     magic,
     99     image_offset,
    100     generic_length,
    101     industry_length,
    102     user_length,
    103     file_size;
    104 
    105   char
    106     version[8],
    107     filename[100],
    108     create_date[12],
    109     create_time[12],
    110     reserve[36];
    111 } CINFileInfo;
    112 
    113 typedef struct _CINFilmInfo
    114 {
    115   char
    116     id,
    117     type,
    118     offset,
    119     reserve1;
    120 
    121   size_t
    122     prefix,
    123     count;
    124 
    125   char
    126     format[32];
    127 
    128   size_t
    129     frame_position;
    130 
    131   float
    132     frame_rate;
    133 
    134   char
    135     frame_id[32],
    136     slate_info[200],
    137     reserve[740];
    138 } CINFilmInfo;
    139 
    140 typedef struct _CINImageChannel
    141 {
    142   unsigned char
    143     designator[2],
    144     bits_per_pixel,
    145     reserve;
    146 
    147   size_t
    148     pixels_per_line,
    149     lines_per_image;
    150 
    151   float
    152     min_data,
    153     min_quantity,
    154     max_data,
    155     max_quantity;
    156 } CINImageChannel;
    157 
    158 typedef struct _CINImageInfo
    159 {
    160   unsigned char
    161     orientation,
    162     number_channels,
    163     reserve1[2];
    164 
    165   CINImageChannel
    166     channel[8];
    167 
    168   float
    169     white_point[2],
    170     red_primary_chromaticity[2],
    171     green_primary_chromaticity[2],
    172     blue_primary_chromaticity[2];
    173 
    174   char
    175     label[200],
    176     reserve[28];
    177 } CINImageInfo;
    178 
    179 typedef struct _CINOriginationInfo
    180 {
    181   ssize_t
    182     x_offset,
    183     y_offset;
    184 
    185   char
    186     filename[100],
    187     create_date[12],
    188     create_time[12],
    189     device[64],
    190     model[32],
    191     serial[32];
    192 
    193   float
    194     x_pitch,
    195     y_pitch,
    196     gamma;
    197 
    198   char
    199     reserve[40];
    200 } CINOriginationInfo;
    201 
    202 typedef struct _CINUserInfo
    203 {
    204   char
    205     id[32];
    206 } CINUserInfo;
    207 
    208 typedef struct CINInfo
    209 {
    210   CINFileInfo
    211     file;
    212 
    213   CINImageInfo
    214     image;
    215 
    216   CINDataFormatInfo
    217     data_format;
    218 
    219   CINOriginationInfo
    220     origination;
    221 
    222   CINFilmInfo
    223     film;
    224 
    225   CINUserInfo
    226     user;
    227 } CINInfo;
    228 
    229 /*
    231   Forward declaractions.
    232 */
    233 static MagickBooleanType
    234   WriteCINImage(const ImageInfo *,Image *,ExceptionInfo *);
    235 
    236 /*
    238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    239 %                                                                             %
    240 %                                                                             %
    241 %                                                                             %
    242 %   I s C I N E O N                                                           %
    243 %                                                                             %
    244 %                                                                             %
    245 %                                                                             %
    246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    247 %
    248 %  IsCIN() returns MagickTrue if the image format type, identified by the magick
    249 %  string, is CIN.
    250 %
    251 %  The format of the IsCIN method is:
    252 %
    253 %      MagickBooleanType IsCIN(const unsigned char *magick,const size_t length)
    254 %
    255 %  A description of each parameter follows:
    256 %
    257 %    o magick: compare image format pattern against these bytes.
    258 %
    259 %    o length: Specifies the length of the magick string.
    260 %
    261 */
    262 static MagickBooleanType IsCIN(const unsigned char *magick,const size_t length)
    263 {
    264   if (length < 4)
    265     return(MagickFalse);
    266   if (memcmp(magick,"\200\052\137\327",4) == 0)
    267     return(MagickTrue);
    268   return(MagickFalse);
    269 }
    270 
    271 /*
    273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    274 %                                                                             %
    275 %                                                                             %
    276 %                                                                             %
    277 %   R e a d C I N E O N I m a g e                                             %
    278 %                                                                             %
    279 %                                                                             %
    280 %                                                                             %
    281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    282 %
    283 %  ReadCINImage() reads an CIN X image file and returns it.  It allocates
    284 %  the memory necessary for the new Image structure and returns a point to the
    285 %  new image.
    286 %
    287 %  The format of the ReadCINImage method is:
    288 %
    289 %      Image *ReadCINImage(const ImageInfo *image_info,
    290 %        ExceptionInfo *exception)
    291 %
    292 %  A description of each parameter follows:
    293 %
    294 %    o image_info: the image info.
    295 %
    296 %    o exception: return any errors or warnings in this structure.
    297 %
    298 */
    299 
    300 static size_t GetBytesPerRow(size_t columns,
    301   size_t samples_per_pixel,size_t bits_per_pixel,
    302   MagickBooleanType pad)
    303 {
    304   size_t
    305     bytes_per_row;
    306 
    307   switch (bits_per_pixel)
    308   {
    309     case 1:
    310     {
    311       bytes_per_row=4*(((size_t) samples_per_pixel*columns*
    312         bits_per_pixel+31)/32);
    313       break;
    314     }
    315     case 8:
    316     default:
    317     {
    318       bytes_per_row=4*(((size_t) samples_per_pixel*columns*
    319         bits_per_pixel+31)/32);
    320       break;
    321     }
    322     case 10:
    323     {
    324       if (pad == MagickFalse)
    325         {
    326           bytes_per_row=4*(((size_t) samples_per_pixel*columns*
    327             bits_per_pixel+31)/32);
    328           break;
    329         }
    330       bytes_per_row=4*(((size_t) (32*((samples_per_pixel*columns+2)/3))+31)/32);
    331       break;
    332     }
    333     case 12:
    334     {
    335       if (pad == MagickFalse)
    336         {
    337           bytes_per_row=4*(((size_t) samples_per_pixel*columns*
    338             bits_per_pixel+31)/32);
    339           break;
    340         }
    341       bytes_per_row=2*(((size_t) (16*samples_per_pixel*columns)+15)/16);
    342       break;
    343     }
    344     case 16:
    345     {
    346       bytes_per_row=2*(((size_t) samples_per_pixel*columns*
    347         bits_per_pixel+8)/16);
    348       break;
    349     }
    350     case 32:
    351     {
    352       bytes_per_row=4*(((size_t) samples_per_pixel*columns*
    353         bits_per_pixel+31)/32);
    354       break;
    355     }
    356     case 64:
    357     {
    358       bytes_per_row=8*(((size_t) samples_per_pixel*columns*
    359         bits_per_pixel+63)/64);
    360       break;
    361     }
    362   }
    363   return(bytes_per_row);
    364 }
    365 
    366 static inline MagickBooleanType IsFloatDefined(const float value)
    367 {
    368   union
    369   {
    370     unsigned int
    371       unsigned_value;
    372 
    373     double
    374       float_value;
    375   } quantum;
    376 
    377   quantum.unsigned_value=0U;
    378   quantum.float_value=value;
    379   if (quantum.unsigned_value == 0U)
    380     return(MagickFalse);
    381   return(MagickTrue);
    382 }
    383 
    384 static Image *ReadCINImage(const ImageInfo *image_info,ExceptionInfo *exception)
    385 {
    386 #define MonoColorType  1
    387 #define RGBColorType  3
    388 
    389   char
    390     property[MagickPathExtent];
    391 
    392   CINInfo
    393     cin;
    394 
    395   const unsigned char
    396     *pixels;
    397 
    398   Image
    399     *image;
    400 
    401   MagickBooleanType
    402     status;
    403 
    404   MagickOffsetType
    405     offset;
    406 
    407   QuantumInfo
    408     *quantum_info;
    409 
    410   QuantumType
    411     quantum_type;
    412 
    413   register ssize_t
    414     i;
    415 
    416   register Quantum
    417     *q;
    418 
    419   size_t
    420     length;
    421 
    422   ssize_t
    423     count,
    424     y;
    425 
    426   unsigned char
    427     magick[4];
    428 
    429   /*
    430     Open image file.
    431   */
    432   assert(image_info != (const ImageInfo *) NULL);
    433   assert(image_info->signature == MagickCoreSignature);
    434   if (image_info->debug != MagickFalse)
    435     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    436       image_info->filename);
    437   assert(exception != (ExceptionInfo *) NULL);
    438   assert(exception->signature == MagickCoreSignature);
    439   image=AcquireImage(image_info,exception);
    440   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    441   if (status == MagickFalse)
    442     {
    443       image=DestroyImageList(image);
    444       return((Image *) NULL);
    445     }
    446   /*
    447     File information.
    448   */
    449   offset=0;
    450   count=ReadBlob(image,4,magick);
    451   offset+=count;
    452   if ((count != 4) ||
    453       ((LocaleNCompare((char *) magick,"\200\052\137\327",4) != 0)))
    454     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    455   image->endian=(magick[0] == 0x80) && (magick[1] == 0x2a) &&
    456     (magick[2] == 0x5f) && (magick[3] == 0xd7) ? MSBEndian : LSBEndian;
    457   cin.file.image_offset=ReadBlobLong(image);
    458   offset+=4;
    459   cin.file.generic_length=ReadBlobLong(image);
    460   offset+=4;
    461   cin.file.industry_length=ReadBlobLong(image);
    462   offset+=4;
    463   cin.file.user_length=ReadBlobLong(image);
    464   offset+=4;
    465   cin.file.file_size=ReadBlobLong(image);
    466   offset+=4;
    467   offset+=ReadBlob(image,sizeof(cin.file.version),(unsigned char *)
    468     cin.file.version);
    469   (void) CopyMagickString(property,cin.file.version,sizeof(cin.file.version));
    470   (void) SetImageProperty(image,"dpx:file.version",property,exception);
    471   offset+=ReadBlob(image,sizeof(cin.file.filename),(unsigned char *)
    472     cin.file.filename);
    473   (void) CopyMagickString(property,cin.file.filename,sizeof(cin.file.filename));
    474   (void) SetImageProperty(image,"dpx:file.filename",property,exception);
    475   offset+=ReadBlob(image,sizeof(cin.file.create_date),(unsigned char *)
    476     cin.file.create_date);
    477   (void) CopyMagickString(property,cin.file.create_date,
    478     sizeof(cin.file.create_date));
    479   (void) SetImageProperty(image,"dpx:file.create_date",property,exception);
    480   offset+=ReadBlob(image,sizeof(cin.file.create_time),(unsigned char *)
    481     cin.file.create_time);
    482   (void) CopyMagickString(property,cin.file.create_time,
    483     sizeof(cin.file.create_time));
    484   (void) SetImageProperty(image,"dpx:file.create_time",property,exception);
    485   offset+=ReadBlob(image,sizeof(cin.file.reserve),(unsigned char *)
    486     cin.file.reserve);
    487   /*
    488     Image information.
    489   */
    490   cin.image.orientation=(unsigned char) ReadBlobByte(image);
    491   offset++;
    492   if (cin.image.orientation != (unsigned char) (~0))
    493     (void) FormatImageProperty(image,"dpx:image.orientation","%d",
    494       cin.image.orientation);
    495   switch (cin.image.orientation)
    496   {
    497     default:
    498     case 0: image->orientation=TopLeftOrientation; break;
    499     case 1: image->orientation=TopRightOrientation; break;
    500     case 2: image->orientation=BottomLeftOrientation; break;
    501     case 3: image->orientation=BottomRightOrientation; break;
    502     case 4: image->orientation=LeftTopOrientation; break;
    503     case 5: image->orientation=RightTopOrientation; break;
    504     case 6: image->orientation=LeftBottomOrientation; break;
    505     case 7: image->orientation=RightBottomOrientation; break;
    506   }
    507   cin.image.number_channels=(unsigned char) ReadBlobByte(image);
    508   offset++;
    509   offset+=ReadBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
    510     cin.image.reserve1);
    511   for (i=0; i < 8; i++)
    512   {
    513     cin.image.channel[i].designator[0]=(unsigned char) ReadBlobByte(image);
    514     offset++;
    515     cin.image.channel[i].designator[1]=(unsigned char) ReadBlobByte(image);
    516     offset++;
    517     cin.image.channel[i].bits_per_pixel=(unsigned char) ReadBlobByte(image);
    518     offset++;
    519     cin.image.channel[i].reserve=(unsigned char) ReadBlobByte(image);
    520     offset++;
    521     cin.image.channel[i].pixels_per_line=ReadBlobLong(image);
    522     offset+=4;
    523     cin.image.channel[i].lines_per_image=ReadBlobLong(image);
    524     offset+=4;
    525     cin.image.channel[i].min_data=ReadBlobFloat(image);
    526     offset+=4;
    527     cin.image.channel[i].min_quantity=ReadBlobFloat(image);
    528     offset+=4;
    529     cin.image.channel[i].max_data=ReadBlobFloat(image);
    530     offset+=4;
    531     cin.image.channel[i].max_quantity=ReadBlobFloat(image);
    532     offset+=4;
    533   }
    534   cin.image.white_point[0]=ReadBlobFloat(image);
    535   offset+=4;
    536   if (IsFloatDefined(cin.image.white_point[0]) != MagickFalse)
    537     image->chromaticity.white_point.x=cin.image.white_point[0];
    538   cin.image.white_point[1]=ReadBlobFloat(image);
    539   offset+=4;
    540   if (IsFloatDefined(cin.image.white_point[1]) != MagickFalse)
    541     image->chromaticity.white_point.y=cin.image.white_point[1];
    542   cin.image.red_primary_chromaticity[0]=ReadBlobFloat(image);
    543   offset+=4;
    544   if (IsFloatDefined(cin.image.red_primary_chromaticity[0]) != MagickFalse)
    545     image->chromaticity.red_primary.x=cin.image.red_primary_chromaticity[0];
    546   cin.image.red_primary_chromaticity[1]=ReadBlobFloat(image);
    547   offset+=4;
    548   if (IsFloatDefined(cin.image.red_primary_chromaticity[1]) != MagickFalse)
    549     image->chromaticity.red_primary.y=cin.image.red_primary_chromaticity[1];
    550   cin.image.green_primary_chromaticity[0]=ReadBlobFloat(image);
    551   offset+=4;
    552   if (IsFloatDefined(cin.image.green_primary_chromaticity[0]) != MagickFalse)
    553     image->chromaticity.red_primary.x=cin.image.green_primary_chromaticity[0];
    554   cin.image.green_primary_chromaticity[1]=ReadBlobFloat(image);
    555   offset+=4;
    556   if (IsFloatDefined(cin.image.green_primary_chromaticity[1]) != MagickFalse)
    557     image->chromaticity.green_primary.y=cin.image.green_primary_chromaticity[1];
    558   cin.image.blue_primary_chromaticity[0]=ReadBlobFloat(image);
    559   offset+=4;
    560   if (IsFloatDefined(cin.image.blue_primary_chromaticity[0]) != MagickFalse)
    561     image->chromaticity.blue_primary.x=cin.image.blue_primary_chromaticity[0];
    562   cin.image.blue_primary_chromaticity[1]=ReadBlobFloat(image);
    563   offset+=4;
    564   if (IsFloatDefined(cin.image.blue_primary_chromaticity[1]) != MagickFalse)
    565     image->chromaticity.blue_primary.y=cin.image.blue_primary_chromaticity[1];
    566   offset+=ReadBlob(image,sizeof(cin.image.label),(unsigned char *)
    567     cin.image.label);
    568   (void) CopyMagickString(property,cin.image.label,sizeof(cin.image.label));
    569   (void) SetImageProperty(image,"dpx:image.label",property,exception);
    570   offset+=ReadBlob(image,sizeof(cin.image.reserve),(unsigned char *)
    571     cin.image.reserve);
    572   /*
    573     Image data format information.
    574   */
    575   cin.data_format.interleave=(unsigned char) ReadBlobByte(image);
    576   offset++;
    577   cin.data_format.packing=(unsigned char) ReadBlobByte(image);
    578   offset++;
    579   cin.data_format.sign=(unsigned char) ReadBlobByte(image);
    580   offset++;
    581   cin.data_format.sense=(unsigned char) ReadBlobByte(image);
    582   offset++;
    583   cin.data_format.line_pad=ReadBlobLong(image);
    584   offset+=4;
    585   cin.data_format.channel_pad=ReadBlobLong(image);
    586   offset+=4;
    587   offset+=ReadBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
    588     cin.data_format.reserve);
    589   /*
    590     Image origination information.
    591   */
    592   cin.origination.x_offset=ReadBlobSignedLong(image);
    593   offset+=4;
    594   if ((size_t) cin.origination.x_offset != ~0UL)
    595     (void) FormatImageProperty(image,"dpx:origination.x_offset","%.20g",
    596       (double) cin.origination.x_offset);
    597   cin.origination.y_offset=(ssize_t) ReadBlobLong(image);
    598   offset+=4;
    599   if ((size_t) cin.origination.y_offset != ~0UL)
    600     (void) FormatImageProperty(image,"dpx:origination.y_offset","%.20g",
    601       (double) cin.origination.y_offset);
    602   offset+=ReadBlob(image,sizeof(cin.origination.filename),(unsigned char *)
    603     cin.origination.filename);
    604   (void) CopyMagickString(property,cin.origination.filename,
    605     sizeof(cin.origination.filename));
    606   (void) SetImageProperty(image,"dpx:origination.filename",property,exception);
    607   offset+=ReadBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
    608     cin.origination.create_date);
    609   (void) CopyMagickString(property,cin.origination.create_date,
    610     sizeof(cin.origination.create_date));
    611   (void) SetImageProperty(image,"dpx:origination.create_date",property,
    612     exception);
    613   offset+=ReadBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
    614     cin.origination.create_time);
    615   (void) CopyMagickString(property,cin.origination.create_time,
    616     sizeof(cin.origination.create_time));
    617   (void) SetImageProperty(image,"dpx:origination.create_time",property,
    618     exception);
    619   offset+=ReadBlob(image,sizeof(cin.origination.device),(unsigned char *)
    620     cin.origination.device);
    621   (void) CopyMagickString(property,cin.origination.device,
    622     sizeof(cin.origination.device));
    623   (void) SetImageProperty(image,"dpx:origination.device",property,exception);
    624   offset+=ReadBlob(image,sizeof(cin.origination.model),(unsigned char *)
    625     cin.origination.model);
    626   (void) CopyMagickString(property,cin.origination.model,
    627     sizeof(cin.origination.model));
    628   (void) SetImageProperty(image,"dpx:origination.model",property,exception);
    629   (void) ResetMagickMemory(cin.origination.serial,0,
    630     sizeof(cin.origination.serial));
    631   offset+=ReadBlob(image,sizeof(cin.origination.serial),(unsigned char *)
    632     cin.origination.serial);
    633   (void) CopyMagickString(property,cin.origination.serial,
    634     sizeof(cin.origination.serial));
    635   (void) SetImageProperty(image,"dpx:origination.serial",property,exception);
    636   cin.origination.x_pitch=ReadBlobFloat(image);
    637   offset+=4;
    638   cin.origination.y_pitch=ReadBlobFloat(image);
    639   offset+=4;
    640   cin.origination.gamma=ReadBlobFloat(image);
    641   offset+=4;
    642   if (IsFloatDefined(cin.origination.gamma) != MagickFalse)
    643     image->gamma=cin.origination.gamma;
    644   offset+=ReadBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
    645     cin.origination.reserve);
    646   if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
    647     {
    648       int
    649         c;
    650 
    651       /*
    652         Image film information.
    653       */
    654       cin.film.id=ReadBlobByte(image);
    655       offset++;
    656       c=cin.film.id;
    657       if (c != ~0)
    658         (void) FormatImageProperty(image,"dpx:film.id","%d",cin.film.id);
    659       cin.film.type=ReadBlobByte(image);
    660       offset++;
    661       c=cin.film.type;
    662       if (c != ~0)
    663         (void) FormatImageProperty(image,"dpx:film.type","%d",cin.film.type);
    664       cin.film.offset=ReadBlobByte(image);
    665       offset++;
    666       c=cin.film.offset;
    667       if (c != ~0)
    668         (void) FormatImageProperty(image,"dpx:film.offset","%d",
    669           cin.film.offset);
    670       cin.film.reserve1=ReadBlobByte(image);
    671       offset++;
    672       cin.film.prefix=ReadBlobLong(image);
    673       offset+=4;
    674       if (cin.film.prefix != ~0UL)
    675         (void) FormatImageProperty(image,"dpx:film.prefix","%.20g",(double)
    676           cin.film.prefix);
    677       cin.film.count=ReadBlobLong(image);
    678       offset+=4;
    679       offset+=ReadBlob(image,sizeof(cin.film.format),(unsigned char *)
    680         cin.film.format);
    681       (void) CopyMagickString(property,cin.film.format,sizeof(cin.film.format));
    682       (void) SetImageProperty(image,"dpx:film.format",property,exception);
    683       cin.film.frame_position=ReadBlobLong(image);
    684       offset+=4;
    685       if (cin.film.frame_position != ~0UL)
    686         (void) FormatImageProperty(image,"dpx:film.frame_position","%.20g",
    687           (double) cin.film.frame_position);
    688       cin.film.frame_rate=ReadBlobFloat(image);
    689       offset+=4;
    690       if (IsFloatDefined(cin.film.frame_rate) != MagickFalse)
    691         (void) FormatImageProperty(image,"dpx:film.frame_rate","%g",
    692           cin.film.frame_rate);
    693       offset+=ReadBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
    694         cin.film.frame_id);
    695       (void) CopyMagickString(property,cin.film.frame_id,
    696         sizeof(cin.film.frame_id));
    697       (void) SetImageProperty(image,"dpx:film.frame_id",property,exception);
    698       offset+=ReadBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
    699         cin.film.slate_info);
    700       (void) CopyMagickString(property,cin.film.slate_info,
    701         sizeof(cin.film.slate_info));
    702       (void) SetImageProperty(image,"dpx:film.slate_info",property,exception);
    703       offset+=ReadBlob(image,sizeof(cin.film.reserve),(unsigned char *)
    704         cin.film.reserve);
    705     }
    706   if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
    707     {
    708       StringInfo
    709         *profile;
    710 
    711       /*
    712         User defined data.
    713       */
    714       profile=BlobToStringInfo((const unsigned char *) NULL,cin.file.user_length);
    715       if (profile == (StringInfo *) NULL)
    716         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    717       offset+=ReadBlob(image,GetStringInfoLength(profile),
    718         GetStringInfoDatum(profile));
    719       (void) SetImageProfile(image,"dpx:user.data",profile,exception);
    720       profile=DestroyStringInfo(profile);
    721     }
    722   image->depth=cin.image.channel[0].bits_per_pixel;
    723   image->columns=cin.image.channel[0].pixels_per_line;
    724   image->rows=cin.image.channel[0].lines_per_image;
    725   if (image_info->ping != MagickFalse)
    726     {
    727       (void) CloseBlob(image);
    728       return(image);
    729     }
    730   for ( ; offset < (MagickOffsetType) cin.file.image_offset; offset++)
    731   {
    732     int
    733       c;
    734 
    735     c=ReadBlobByte(image);
    736     if (c == EOF)
    737       break;
    738   }
    739   if (offset < (MagickOffsetType) cin.file.image_offset)
    740     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    741   status=SetImageExtent(image,image->columns,image->rows,exception);
    742   if (status == MagickFalse)
    743     return(DestroyImageList(image));
    744   /*
    745     Convert CIN raster image to pixel packets.
    746   */
    747   quantum_info=AcquireQuantumInfo(image_info,image);
    748   if (quantum_info == (QuantumInfo *) NULL)
    749     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    750   quantum_info->quantum=32;
    751   quantum_info->pack=MagickFalse;
    752   quantum_type=RGBQuantum;
    753   length=GetQuantumExtent(image,quantum_info,quantum_type);
    754   length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
    755   if (cin.image.number_channels == 1)
    756     {
    757       quantum_type=GrayQuantum;
    758       length=GetBytesPerRow(image->columns,1,image->depth,MagickTrue);
    759     }
    760   for (y=0; y < (ssize_t) image->rows; y++)
    761   {
    762     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    763     if (q == (Quantum *) NULL)
    764       break;
    765     pixels=(const unsigned char *) ReadBlobStream(image,length,
    766       GetQuantumPixels(quantum_info),&count);
    767     if ((size_t) count != length)
    768       break;
    769     (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
    770       quantum_type,pixels,exception);
    771     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    772       break;
    773     if (image->previous == (Image *) NULL)
    774       {
    775         status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
    776           image->rows);
    777         if (status == MagickFalse)
    778           break;
    779       }
    780   }
    781   SetQuantumImageType(image,quantum_type);
    782   quantum_info=DestroyQuantumInfo(quantum_info);
    783   if (EOFBlob(image) != MagickFalse)
    784     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    785       image->filename);
    786   SetImageColorspace(image,LogColorspace,exception);
    787   (void) CloseBlob(image);
    788   return(GetFirstImageInList(image));
    789 }
    790 
    791 /*
    793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    794 %                                                                             %
    795 %                                                                             %
    796 %                                                                             %
    797 %   R e g i s t e r C I N E O N I m a g e                                     %
    798 %                                                                             %
    799 %                                                                             %
    800 %                                                                             %
    801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    802 %
    803 %  RegisterCINImage() adds attributes for the CIN image format to the list of
    804 %  of supported formats.  The attributes include the image format tag, a method
    805 %  to read and/or write the format, whether the format supports the saving of
    806 %  more than one frame to the same file or blob, whether the format supports
    807 %  native in-memory I/O, and a brief description of the format.
    808 %
    809 %  The format of the RegisterCINImage method is:
    810 %
    811 %      size_t RegisterCINImage(void)
    812 %
    813 */
    814 ModuleExport size_t RegisterCINImage(void)
    815 {
    816   MagickInfo
    817     *entry;
    818 
    819   entry=AcquireMagickInfo("CIN","CIN","Cineon Image File");
    820   entry->decoder=(DecodeImageHandler *) ReadCINImage;
    821   entry->encoder=(EncodeImageHandler *) WriteCINImage;
    822   entry->magick=(IsImageFormatHandler *) IsCIN;
    823   entry->flags^=CoderAdjoinFlag;
    824   (void) RegisterMagickInfo(entry);
    825   return(MagickImageCoderSignature);
    826 }
    827 
    828 /*
    830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    831 %                                                                             %
    832 %                                                                             %
    833 %                                                                             %
    834 %   U n r e g i s t e r C I N E O N I m a g e                                 %
    835 %                                                                             %
    836 %                                                                             %
    837 %                                                                             %
    838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    839 %
    840 %  UnregisterCINImage() removes format registrations made by the CIN module
    841 %  from the list of supported formats.
    842 %
    843 %  The format of the UnregisterCINImage method is:
    844 %
    845 %      UnregisterCINImage(void)
    846 %
    847 */
    848 ModuleExport void UnregisterCINImage(void)
    849 {
    850   (void) UnregisterMagickInfo("CINEON");
    851 }
    852 
    853 /*
    855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    856 %                                                                             %
    857 %                                                                             %
    858 %                                                                             %
    859 %   W r i t e C I N E O N I m a g e                                           %
    860 %                                                                             %
    861 %                                                                             %
    862 %                                                                             %
    863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    864 %
    865 %  WriteCINImage() writes an image in CIN encoded image format.
    866 %
    867 %  The format of the WriteCINImage method is:
    868 %
    869 %      MagickBooleanType WriteCINImage(const ImageInfo *image_info,
    870 %        Image *image,ExceptionInfo *exception)
    871 %
    872 %  A description of each parameter follows.
    873 %
    874 %    o image_info: the image info.
    875 %
    876 %    o image:  The image.
    877 %
    878 %    o exception: return any errors or warnings in this structure.
    879 %
    880 */
    881 
    882 static inline const char *GetCINProperty(const ImageInfo *image_info,
    883   const Image *image,const char *property,ExceptionInfo *exception)
    884 {
    885   const char
    886     *value;
    887 
    888   value=GetImageOption(image_info,property);
    889   if (value != (const char *) NULL)
    890     return(value);
    891   return(GetImageProperty(image,property,exception));
    892 }
    893 
    894 static MagickBooleanType WriteCINImage(const ImageInfo *image_info,Image *image,
    895   ExceptionInfo *exception)
    896 {
    897   char
    898     timestamp[MagickPathExtent];
    899 
    900   const char
    901     *value;
    902 
    903   CINInfo
    904     cin;
    905 
    906   const StringInfo
    907     *profile;
    908 
    909   MagickBooleanType
    910     status;
    911 
    912   MagickOffsetType
    913     offset;
    914 
    915   QuantumInfo
    916     *quantum_info;
    917 
    918   QuantumType
    919     quantum_type;
    920 
    921   register const Quantum
    922     *p;
    923 
    924   register ssize_t
    925     i;
    926 
    927   size_t
    928     length;
    929 
    930   ssize_t
    931     count,
    932     y;
    933 
    934   struct tm
    935     local_time;
    936 
    937   time_t
    938     seconds;
    939 
    940   unsigned char
    941     *pixels;
    942 
    943   /*
    944     Open output image file.
    945   */
    946   assert(image_info != (const ImageInfo *) NULL);
    947   assert(image_info->signature == MagickCoreSignature);
    948   assert(image != (Image *) NULL);
    949   assert(image->signature == MagickCoreSignature);
    950   if (image->debug != MagickFalse)
    951     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    952   assert(exception != (ExceptionInfo *) NULL);
    953   assert(exception->signature == MagickCoreSignature);
    954   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    955   if (status == MagickFalse)
    956     return(status);
    957   if (image->colorspace != LogColorspace)
    958     (void) TransformImageColorspace(image,LogColorspace,exception);
    959   /*
    960     Write image information.
    961   */
    962   (void) ResetMagickMemory(&cin,0,sizeof(cin));
    963   offset=0;
    964   cin.file.magic=0x802A5FD7UL;
    965   offset+=WriteBlobLong(image,(unsigned int) cin.file.magic);
    966   cin.file.image_offset=0x800;
    967   offset+=WriteBlobLong(image,(unsigned int) cin.file.image_offset);
    968   cin.file.generic_length=0x400;
    969   offset+=WriteBlobLong(image,(unsigned int) cin.file.generic_length);
    970   cin.file.industry_length=0x400;
    971   offset+=WriteBlobLong(image,(unsigned int) cin.file.industry_length);
    972   cin.file.user_length=0x00;
    973   profile=GetImageProfile(image,"dpx:user.data");
    974   if (profile != (StringInfo *) NULL)
    975     {
    976       cin.file.user_length+=(size_t) GetStringInfoLength(profile);
    977       cin.file.user_length=(((cin.file.user_length+0x2000-1)/0x2000)*0x2000);
    978     }
    979   offset+=WriteBlobLong(image,(unsigned int) cin.file.user_length);
    980   cin.file.file_size=4*image->columns*image->rows+0x2000;
    981   offset+=WriteBlobLong(image,(unsigned int) cin.file.file_size);
    982   (void) CopyMagickString(cin.file.version,"V4.5",sizeof(cin.file.version));
    983   offset+=WriteBlob(image,sizeof(cin.file.version),(unsigned char *)
    984     cin.file.version);
    985   value=GetCINProperty(image_info,image,"dpx:file.filename",exception);
    986   if (value != (const char *) NULL)
    987     (void) CopyMagickString(cin.file.filename,value,sizeof(cin.file.filename));
    988   else
    989     (void) CopyMagickString(cin.file.filename,image->filename,
    990       sizeof(cin.file.filename));
    991   offset+=WriteBlob(image,sizeof(cin.file.filename),(unsigned char *)
    992     cin.file.filename);
    993   seconds=time((time_t *) NULL);
    994 #if defined(MAGICKCORE_HAVE_LOCALTIME_R)
    995   (void) localtime_r(&seconds,&local_time);
    996 #else
    997   (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
    998 #endif
    999   (void) memset(timestamp,0,sizeof(timestamp));
   1000   (void) strftime(timestamp,MagickPathExtent,"%Y:%m:%d:%H:%M:%S%Z",&local_time);
   1001   (void) memset(cin.file.create_date,0,sizeof(cin.file.create_date));
   1002   (void) CopyMagickString(cin.file.create_date,timestamp,11);
   1003   offset+=WriteBlob(image,sizeof(cin.file.create_date),(unsigned char *)
   1004     cin.file.create_date);
   1005   (void) memset(cin.file.create_time,0,sizeof(cin.file.create_time));
   1006   (void) CopyMagickString(cin.file.create_time,timestamp+11,11);
   1007   offset+=WriteBlob(image,sizeof(cin.file.create_time),(unsigned char *)
   1008     cin.file.create_time);
   1009   offset+=WriteBlob(image,sizeof(cin.file.reserve),(unsigned char *)
   1010     cin.file.reserve);
   1011   cin.image.orientation=0x00;
   1012   offset+=WriteBlobByte(image,cin.image.orientation);
   1013   cin.image.number_channels=3;
   1014   offset+=WriteBlobByte(image,cin.image.number_channels);
   1015   offset+=WriteBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
   1016     cin.image.reserve1);
   1017   for (i=0; i < 8; i++)
   1018   {
   1019     cin.image.channel[i].designator[0]=0; /* universal metric */
   1020     offset+=WriteBlobByte(image,cin.image.channel[0].designator[0]);
   1021     cin.image.channel[i].designator[1]=(unsigned char) (i > 3 ? 0 : i+1); /* channel color */;
   1022     offset+=WriteBlobByte(image,cin.image.channel[1].designator[0]);
   1023     cin.image.channel[i].bits_per_pixel=(unsigned char) image->depth;
   1024     offset+=WriteBlobByte(image,cin.image.channel[0].bits_per_pixel);
   1025     offset+=WriteBlobByte(image,cin.image.channel[0].reserve);
   1026     cin.image.channel[i].pixels_per_line=image->columns;
   1027     offset+=WriteBlobLong(image,(unsigned int)
   1028       cin.image.channel[0].pixels_per_line);
   1029     cin.image.channel[i].lines_per_image=image->rows;
   1030     offset+=WriteBlobLong(image,(unsigned int)
   1031       cin.image.channel[0].lines_per_image);
   1032     cin.image.channel[i].min_data=0;
   1033     offset+=WriteBlobFloat(image,cin.image.channel[0].min_data);
   1034     cin.image.channel[i].min_quantity=0.0;
   1035     offset+=WriteBlobFloat(image,cin.image.channel[0].min_quantity);
   1036     cin.image.channel[i].max_data=(float) ((MagickOffsetType)
   1037       GetQuantumRange(image->depth));
   1038     offset+=WriteBlobFloat(image,cin.image.channel[0].max_data);
   1039     cin.image.channel[i].max_quantity=2.048f;
   1040     offset+=WriteBlobFloat(image,cin.image.channel[0].max_quantity);
   1041   }
   1042   offset+=WriteBlobFloat(image,image->chromaticity.white_point.x);
   1043   offset+=WriteBlobFloat(image,image->chromaticity.white_point.y);
   1044   offset+=WriteBlobFloat(image,image->chromaticity.red_primary.x);
   1045   offset+=WriteBlobFloat(image,image->chromaticity.red_primary.y);
   1046   offset+=WriteBlobFloat(image,image->chromaticity.green_primary.x);
   1047   offset+=WriteBlobFloat(image,image->chromaticity.green_primary.y);
   1048   offset+=WriteBlobFloat(image,image->chromaticity.blue_primary.x);
   1049   offset+=WriteBlobFloat(image,image->chromaticity.blue_primary.y);
   1050   value=GetCINProperty(image_info,image,"dpx:image.label",exception);
   1051   if (value != (const char *) NULL)
   1052     (void) CopyMagickString(cin.image.label,value,sizeof(cin.image.label));
   1053   offset+=WriteBlob(image,sizeof(cin.image.label),(unsigned char *)
   1054     cin.image.label);
   1055   offset+=WriteBlob(image,sizeof(cin.image.reserve),(unsigned char *)
   1056     cin.image.reserve);
   1057   /*
   1058     Write data format information.
   1059   */
   1060   cin.data_format.interleave=0; /* pixel interleave (rgbrgbr...) */
   1061   offset+=WriteBlobByte(image,cin.data_format.interleave);
   1062   cin.data_format.packing=5; /* packing ssize_tword (32bit) boundaries */
   1063   offset+=WriteBlobByte(image,cin.data_format.packing);
   1064   cin.data_format.sign=0; /* unsigned data */
   1065   offset+=WriteBlobByte(image,cin.data_format.sign);
   1066   cin.data_format.sense=0; /* image sense: positive image */
   1067   offset+=WriteBlobByte(image,cin.data_format.sense);
   1068   cin.data_format.line_pad=0;
   1069   offset+=WriteBlobLong(image,(unsigned int) cin.data_format.line_pad);
   1070   cin.data_format.channel_pad=0;
   1071   offset+=WriteBlobLong(image,(unsigned int) cin.data_format.channel_pad);
   1072   offset+=WriteBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
   1073     cin.data_format.reserve);
   1074   /*
   1075     Write origination information.
   1076   */
   1077   cin.origination.x_offset=0UL;
   1078   value=GetCINProperty(image_info,image,"dpx:origination.x_offset",exception);
   1079   if (value != (const char *) NULL)
   1080     cin.origination.x_offset=(ssize_t) StringToLong(value);
   1081   offset+=WriteBlobLong(image,(unsigned int) cin.origination.x_offset);
   1082   cin.origination.y_offset=0UL;
   1083   value=GetCINProperty(image_info,image,"dpx:origination.y_offset",exception);
   1084   if (value != (const char *) NULL)
   1085     cin.origination.y_offset=(ssize_t) StringToLong(value);
   1086   offset+=WriteBlobLong(image,(unsigned int) cin.origination.y_offset);
   1087   value=GetCINProperty(image_info,image,"dpx:origination.filename",exception);
   1088   if (value != (const char *) NULL)
   1089     (void) CopyMagickString(cin.origination.filename,value,
   1090       sizeof(cin.origination.filename));
   1091   else
   1092     (void) CopyMagickString(cin.origination.filename,image->filename,
   1093       sizeof(cin.origination.filename));
   1094   offset+=WriteBlob(image,sizeof(cin.origination.filename),(unsigned char *)
   1095     cin.origination.filename);
   1096   seconds=time((time_t *) NULL);
   1097   (void) memset(timestamp,0,sizeof(timestamp));
   1098   (void) strftime(timestamp,MagickPathExtent,"%Y:%m:%d:%H:%M:%S%Z",&local_time);
   1099   (void) memset(cin.origination.create_date,0,
   1100     sizeof(cin.origination.create_date));
   1101   (void) CopyMagickString(cin.origination.create_date,timestamp,11);
   1102   offset+=WriteBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
   1103     cin.origination.create_date);
   1104   (void) memset(cin.origination.create_time,0,
   1105      sizeof(cin.origination.create_time));
   1106   (void) CopyMagickString(cin.origination.create_time,timestamp+11,15);
   1107   offset+=WriteBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
   1108     cin.origination.create_time);
   1109   value=GetCINProperty(image_info,image,"dpx:origination.device",exception);
   1110   if (value != (const char *) NULL)
   1111     (void) CopyMagickString(cin.origination.device,value,
   1112       sizeof(cin.origination.device));
   1113   offset+=WriteBlob(image,sizeof(cin.origination.device),(unsigned char *)
   1114     cin.origination.device);
   1115   value=GetCINProperty(image_info,image,"dpx:origination.model",exception);
   1116   if (value != (const char *) NULL)
   1117     (void) CopyMagickString(cin.origination.model,value,
   1118       sizeof(cin.origination.model));
   1119   offset+=WriteBlob(image,sizeof(cin.origination.model),(unsigned char *)
   1120     cin.origination.model);
   1121   value=GetCINProperty(image_info,image,"dpx:origination.serial",exception);
   1122   if (value != (const char *) NULL)
   1123     (void) CopyMagickString(cin.origination.serial,value,
   1124       sizeof(cin.origination.serial));
   1125   offset+=WriteBlob(image,sizeof(cin.origination.serial),(unsigned char *)
   1126     cin.origination.serial);
   1127   cin.origination.x_pitch=0.0f;
   1128   value=GetCINProperty(image_info,image,"dpx:origination.x_pitch",exception);
   1129   if (value != (const char *) NULL)
   1130     cin.origination.x_pitch=StringToDouble(value,(char **) NULL);
   1131   offset+=WriteBlobFloat(image,cin.origination.x_pitch);
   1132   cin.origination.y_pitch=0.0f;
   1133   value=GetCINProperty(image_info,image,"dpx:origination.y_pitch",exception);
   1134   if (value != (const char *) NULL)
   1135     cin.origination.y_pitch=StringToDouble(value,(char **) NULL);
   1136   offset+=WriteBlobFloat(image,cin.origination.y_pitch);
   1137   cin.origination.gamma=image->gamma;
   1138   offset+=WriteBlobFloat(image,cin.origination.gamma);
   1139   offset+=WriteBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
   1140     cin.origination.reserve);
   1141   /*
   1142     Image film information.
   1143   */
   1144   cin.film.id=0;
   1145   value=GetCINProperty(image_info,image,"dpx:film.id",exception);
   1146   if (value != (const char *) NULL)
   1147     cin.film.id=(char) StringToLong(value);
   1148   offset+=WriteBlobByte(image,(unsigned char) cin.film.id);
   1149   cin.film.type=0;
   1150   value=GetCINProperty(image_info,image,"dpx:film.type",exception);
   1151   if (value != (const char *) NULL)
   1152     cin.film.type=(char) StringToLong(value);
   1153   offset+=WriteBlobByte(image,(unsigned char) cin.film.type);
   1154   cin.film.offset=0;
   1155   value=GetCINProperty(image_info,image,"dpx:film.offset",exception);
   1156   if (value != (const char *) NULL)
   1157     cin.film.offset=(char) StringToLong(value);
   1158   offset+=WriteBlobByte(image,(unsigned char) cin.film.offset);
   1159   offset+=WriteBlobByte(image,(unsigned char) cin.film.reserve1);
   1160   cin.film.prefix=0UL;
   1161   value=GetCINProperty(image_info,image,"dpx:film.prefix",exception);
   1162   if (value != (const char *) NULL)
   1163     cin.film.prefix=StringToUnsignedLong(value);
   1164   offset+=WriteBlobLong(image,(unsigned int) cin.film.prefix);
   1165   cin.film.count=0UL;
   1166   value=GetCINProperty(image_info,image,"dpx:film.count",exception);
   1167   if (value != (const char *) NULL)
   1168     cin.film.count=StringToUnsignedLong(value);
   1169   offset+=WriteBlobLong(image,(unsigned int) cin.film.count);
   1170   value=GetCINProperty(image_info,image,"dpx:film.format",exception);
   1171   if (value != (const char *) NULL)
   1172     (void) CopyMagickString(cin.film.format,value,sizeof(cin.film.format));
   1173   offset+=WriteBlob(image,sizeof(cin.film.format),(unsigned char *)
   1174     cin.film.format);
   1175   cin.film.frame_position=0UL;
   1176   value=GetCINProperty(image_info,image,"dpx:film.frame_position",exception);
   1177   if (value != (const char *) NULL)
   1178     cin.film.frame_position=StringToUnsignedLong(value);
   1179   offset+=WriteBlobLong(image,(unsigned int) cin.film.frame_position);
   1180   cin.film.frame_rate=0.0f;
   1181   value=GetCINProperty(image_info,image,"dpx:film.frame_rate",exception);
   1182   if (value != (const char *) NULL)
   1183     cin.film.frame_rate=StringToDouble(value,(char **) NULL);
   1184   offset+=WriteBlobFloat(image,cin.film.frame_rate);
   1185   value=GetCINProperty(image_info,image,"dpx:film.frame_id",exception);
   1186   if (value != (const char *) NULL)
   1187     (void) CopyMagickString(cin.film.frame_id,value,sizeof(cin.film.frame_id));
   1188   offset+=WriteBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
   1189     cin.film.frame_id);
   1190   value=GetCINProperty(image_info,image,"dpx:film.slate_info",exception);
   1191   if (value != (const char *) NULL)
   1192     (void) CopyMagickString(cin.film.slate_info,value,
   1193       sizeof(cin.film.slate_info));
   1194   offset+=WriteBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
   1195     cin.film.slate_info);
   1196   offset+=WriteBlob(image,sizeof(cin.film.reserve),(unsigned char *)
   1197     cin.film.reserve);
   1198   if (profile != (StringInfo *) NULL)
   1199     offset+=WriteBlob(image,GetStringInfoLength(profile),
   1200       GetStringInfoDatum(profile));
   1201   while (offset < (MagickOffsetType) cin.file.image_offset)
   1202     offset+=WriteBlobByte(image,0x00);
   1203   /*
   1204     Convert pixel packets to CIN raster image.
   1205   */
   1206   quantum_info=AcquireQuantumInfo(image_info,image);
   1207   if (quantum_info == (QuantumInfo *) NULL)
   1208     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   1209   quantum_info->quantum=32;
   1210   quantum_info->pack=MagickFalse;
   1211   quantum_type=RGBQuantum;
   1212   pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   1213   length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
   1214 DisableMSCWarning(4127)
   1215   if (0)
   1216 RestoreMSCWarning
   1217     {
   1218       quantum_type=GrayQuantum;
   1219       length=GetBytesPerRow(image->columns,1,image->depth,MagickTrue);
   1220     }
   1221   for (y=0; y < (ssize_t) image->rows; y++)
   1222   {
   1223     p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   1224     if (p == (const Quantum *) NULL)
   1225       break;
   1226     (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   1227       quantum_type,pixels,exception);
   1228     count=WriteBlob(image,length,pixels);
   1229     if (count != (ssize_t) length)
   1230       break;
   1231     status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
   1232       image->rows);
   1233     if (status == MagickFalse)
   1234       break;
   1235   }
   1236   quantum_info=DestroyQuantumInfo(quantum_info);
   1237   (void) CloseBlob(image);
   1238   return(status);
   1239 }
   1240