Coverage Report

Created: 2026-05-16 07:22

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