Coverage Report

Created: 2025-08-12 07:37

/src/imagemagick/coders/cin.c
Line
Count
Source (jump to first uncovered line)
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/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
/*
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.21k
{
300
2.21k
  size_t
301
2.21k
    bytes_per_row;
302
303
2.21k
  switch (bits_per_pixel)
304
2.21k
  {
305
349
    case 1:
306
349
    {
307
349
      bytes_per_row=4*(((size_t) samples_per_pixel*columns*
308
349
        bits_per_pixel+31)/32);
309
349
      break;
310
0
    }
311
187
    case 8:
312
690
    default:
313
690
    {
314
690
      bytes_per_row=4*(((size_t) samples_per_pixel*columns*
315
690
        bits_per_pixel+31)/32);
316
690
      break;
317
187
    }
318
299
    case 10:
319
299
    {
320
299
      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
299
      bytes_per_row=4*(((size_t) (32*((samples_per_pixel*columns+2)/3))+31)/32);
327
299
      break;
328
299
    }
329
312
    case 12:
330
312
    {
331
312
      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
312
      bytes_per_row=2*(((size_t) (16*samples_per_pixel*columns)+15)/16);
338
312
      break;
339
312
    }
340
318
    case 16:
341
318
    {
342
318
      bytes_per_row=2*(((size_t) samples_per_pixel*columns*
343
318
        bits_per_pixel+8)/16);
344
318
      break;
345
312
    }
346
167
    case 32:
347
167
    {
348
167
      bytes_per_row=4*(((size_t) samples_per_pixel*columns*
349
167
        bits_per_pixel+31)/32);
350
167
      break;
351
312
    }
352
78
    case 64:
353
78
    {
354
78
      bytes_per_row=8*(((size_t) samples_per_pixel*columns*
355
78
        bits_per_pixel+63)/64);
356
78
      break;
357
312
    }
358
2.21k
  }
359
2.21k
  return(bytes_per_row);
360
2.21k
}
361
362
static inline MagickBooleanType IsFloatDefined(const float value)
363
14.4k
{
364
14.4k
  union
365
14.4k
  {
366
14.4k
    unsigned int
367
14.4k
      unsigned_value;
368
369
14.4k
    double
370
14.4k
      float_value;
371
14.4k
  } quantum;
372
373
14.4k
  quantum.unsigned_value=0U;
374
14.4k
  quantum.float_value=value;
375
14.4k
  if (quantum.unsigned_value == 0U)
376
8.47k
    return(MagickFalse);
377
5.95k
  return(MagickTrue);
378
14.4k
}
379
380
static Image *ReadCINImage(const ImageInfo *image_info,ExceptionInfo *exception)
381
1.86k
{
382
1.86k
#define MonoColorType  1
383
1.86k
#define RGBColorType  3
384
385
1.86k
  char
386
1.86k
    property[MagickPathExtent];
387
388
1.86k
  CINInfo
389
1.86k
    cin;
390
391
1.86k
  Image
392
1.86k
    *image;
393
394
1.86k
  MagickBooleanType
395
1.86k
    status;
396
397
1.86k
  MagickOffsetType
398
1.86k
    offset;
399
400
1.86k
  QuantumInfo
401
1.86k
    *quantum_info;
402
403
1.86k
  QuantumType
404
1.86k
    quantum_type;
405
406
1.86k
  ssize_t
407
1.86k
    i;
408
409
1.86k
  Quantum
410
1.86k
    *q;
411
412
1.86k
  size_t
413
1.86k
    length;
414
415
1.86k
  ssize_t
416
1.86k
    count,
417
1.86k
    y;
418
419
1.86k
  unsigned char
420
1.86k
    magick[4],
421
1.86k
    *pixels;
422
423
424
  /*
425
    Open image file.
426
  */
427
1.86k
  assert(image_info != (const ImageInfo *) NULL);
428
1.86k
  assert(image_info->signature == MagickCoreSignature);
429
1.86k
  assert(exception != (ExceptionInfo *) NULL);
430
1.86k
  assert(exception->signature == MagickCoreSignature);
431
1.86k
  if (IsEventLogging() != MagickFalse)
432
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
433
0
      image_info->filename);
434
1.86k
  image=AcquireImage(image_info,exception);
435
1.86k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
436
1.86k
  if (status == MagickFalse)
437
0
    {
438
0
      image=DestroyImageList(image);
439
0
      return((Image *) NULL);
440
0
    }
441
  /*
442
    File information.
443
  */
444
1.86k
  offset=0;
445
1.86k
  count=ReadBlob(image,4,magick);
446
1.86k
  offset+=count;
447
1.86k
  if ((count != 4) ||
448
1.86k
      ((LocaleNCompare((char *) magick,"\200\052\137\327",4) != 0)))
449
1.58k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
450
1.58k
  memset(&cin,0,sizeof(cin));
451
1.58k
  image->endian=(magick[0] == 0x80) && (magick[1] == 0x2a) &&
452
1.58k
    (magick[2] == 0x5f) && (magick[3] == 0xd7) ? MSBEndian : LSBEndian;
453
1.58k
  cin.file.image_offset=ReadBlobLong(image);
454
1.58k
  if (cin.file.image_offset < 712)
455
1.57k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
456
1.57k
  offset+=4;
457
1.57k
  cin.file.generic_length=ReadBlobLong(image);
458
1.57k
  offset+=4;
459
1.57k
  cin.file.industry_length=ReadBlobLong(image);
460
1.57k
  offset+=4;
461
1.57k
  cin.file.user_length=ReadBlobLong(image);
462
1.57k
  offset+=4;
463
1.57k
  cin.file.file_size=ReadBlobLong(image);
464
1.57k
  offset+=4;
465
1.57k
  offset+=ReadBlob(image,sizeof(cin.file.version),(unsigned char *)
466
1.57k
    cin.file.version);
467
1.57k
  (void) CopyMagickString(property,cin.file.version,sizeof(cin.file.version));
468
1.57k
  (void) SetImageProperty(image,"dpx:file.version",property,exception);
469
1.57k
  offset+=ReadBlob(image,sizeof(cin.file.filename),(unsigned char *)
470
1.57k
    cin.file.filename);
471
1.57k
  (void) CopyMagickString(property,cin.file.filename,sizeof(cin.file.filename));
472
1.57k
  (void) SetImageProperty(image,"dpx:file.filename",property,exception);
473
1.57k
  offset+=ReadBlob(image,sizeof(cin.file.create_date),(unsigned char *)
474
1.57k
    cin.file.create_date);
475
1.57k
  (void) CopyMagickString(property,cin.file.create_date,
476
1.57k
    sizeof(cin.file.create_date));
477
1.57k
  (void) SetImageProperty(image,"dpx:file.create_date",property,exception);
478
1.57k
  offset+=ReadBlob(image,sizeof(cin.file.create_time),(unsigned char *)
479
1.57k
    cin.file.create_time);
480
1.57k
  (void) CopyMagickString(property,cin.file.create_time,
481
1.57k
    sizeof(cin.file.create_time));
482
1.57k
  (void) SetImageProperty(image,"dpx:file.create_time",property,exception);
483
1.57k
  offset+=ReadBlob(image,sizeof(cin.file.reserve),(unsigned char *)
484
1.57k
    cin.file.reserve);
485
  /*
486
    Image information.
487
  */
488
1.57k
  cin.image.orientation=(unsigned char) ReadBlobByte(image);
489
1.57k
  offset++;
490
1.57k
  if (cin.image.orientation != (unsigned char) (~0))
491
1.15k
    (void) FormatImageProperty(image,"dpx:image.orientation","%d",
492
1.15k
      cin.image.orientation);
493
1.57k
  switch (cin.image.orientation)
494
1.57k
  {
495
927
    default:
496
1.42k
    case 0: image->orientation=TopLeftOrientation; break;
497
87
    case 1: image->orientation=TopRightOrientation; break;
498
13
    case 2: image->orientation=BottomLeftOrientation; break;
499
21
    case 3: image->orientation=BottomRightOrientation; break;
500
8
    case 4: image->orientation=LeftTopOrientation; break;
501
3
    case 5: image->orientation=RightTopOrientation; break;
502
7
    case 6: image->orientation=LeftBottomOrientation; break;
503
5
    case 7: image->orientation=RightBottomOrientation; break;
504
1.57k
  }
505
1.57k
  cin.image.number_channels=(unsigned char) ReadBlobByte(image);
506
1.57k
  offset++;
507
1.57k
  offset+=ReadBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
508
1.57k
    cin.image.reserve1);
509
14.1k
  for (i=0; i < 8; i++)
510
12.5k
  {
511
12.5k
    cin.image.channel[i].designator[0]=(unsigned char) ReadBlobByte(image);
512
12.5k
    offset++;
513
12.5k
    cin.image.channel[i].designator[1]=(unsigned char) ReadBlobByte(image);
514
12.5k
    offset++;
515
12.5k
    cin.image.channel[i].bits_per_pixel=(unsigned char) ReadBlobByte(image);
516
12.5k
    offset++;
517
12.5k
    cin.image.channel[i].reserve=(unsigned char) ReadBlobByte(image);
518
12.5k
    offset++;
519
12.5k
    cin.image.channel[i].pixels_per_line=ReadBlobLong(image);
520
12.5k
    offset+=4;
521
12.5k
    cin.image.channel[i].lines_per_image=ReadBlobLong(image);
522
12.5k
    offset+=4;
523
12.5k
    cin.image.channel[i].min_data=ReadBlobFloat(image);
524
12.5k
    offset+=4;
525
12.5k
    cin.image.channel[i].min_quantity=ReadBlobFloat(image);
526
12.5k
    offset+=4;
527
12.5k
    cin.image.channel[i].max_data=ReadBlobFloat(image);
528
12.5k
    offset+=4;
529
12.5k
    cin.image.channel[i].max_quantity=ReadBlobFloat(image);
530
12.5k
    offset+=4;
531
12.5k
  }
532
1.57k
  cin.image.white_point[0]=ReadBlobFloat(image);
533
1.57k
  offset+=4;
534
1.57k
  if (IsFloatDefined(cin.image.white_point[0]) != MagickFalse)
535
664
    image->chromaticity.white_point.x=cin.image.white_point[0];
536
1.57k
  cin.image.white_point[1]=ReadBlobFloat(image);
537
1.57k
  offset+=4;
538
1.57k
  if (IsFloatDefined(cin.image.white_point[1]) != MagickFalse)
539
653
    image->chromaticity.white_point.y=cin.image.white_point[1];
540
1.57k
  cin.image.red_primary_chromaticity[0]=ReadBlobFloat(image);
541
1.57k
  offset+=4;
542
1.57k
  if (IsFloatDefined(cin.image.red_primary_chromaticity[0]) != MagickFalse)
543
681
    image->chromaticity.red_primary.x=cin.image.red_primary_chromaticity[0];
544
1.57k
  cin.image.red_primary_chromaticity[1]=ReadBlobFloat(image);
545
1.57k
  offset+=4;
546
1.57k
  if (IsFloatDefined(cin.image.red_primary_chromaticity[1]) != MagickFalse)
547
682
    image->chromaticity.red_primary.y=cin.image.red_primary_chromaticity[1];
548
1.57k
  cin.image.green_primary_chromaticity[0]=ReadBlobFloat(image);
549
1.57k
  offset+=4;
550
1.57k
  if (IsFloatDefined(cin.image.green_primary_chromaticity[0]) != MagickFalse)
551
684
    image->chromaticity.red_primary.x=cin.image.green_primary_chromaticity[0];
552
1.57k
  cin.image.green_primary_chromaticity[1]=ReadBlobFloat(image);
553
1.57k
  offset+=4;
554
1.57k
  if (IsFloatDefined(cin.image.green_primary_chromaticity[1]) != MagickFalse)
555
687
    image->chromaticity.green_primary.y=cin.image.green_primary_chromaticity[1];
556
1.57k
  cin.image.blue_primary_chromaticity[0]=ReadBlobFloat(image);
557
1.57k
  offset+=4;
558
1.57k
  if (IsFloatDefined(cin.image.blue_primary_chromaticity[0]) != MagickFalse)
559
664
    image->chromaticity.blue_primary.x=cin.image.blue_primary_chromaticity[0];
560
1.57k
  cin.image.blue_primary_chromaticity[1]=ReadBlobFloat(image);
561
1.57k
  offset+=4;
562
1.57k
  if (IsFloatDefined(cin.image.blue_primary_chromaticity[1]) != MagickFalse)
563
637
    image->chromaticity.blue_primary.y=cin.image.blue_primary_chromaticity[1];
564
1.57k
  offset+=ReadBlob(image,sizeof(cin.image.label),(unsigned char *)
565
1.57k
    cin.image.label);
566
1.57k
  (void) CopyMagickString(property,cin.image.label,sizeof(cin.image.label));
567
1.57k
  (void) SetImageProperty(image,"dpx:image.label",property,exception);
568
1.57k
  offset+=ReadBlob(image,sizeof(cin.image.reserve),(unsigned char *)
569
1.57k
    cin.image.reserve);
570
  /*
571
    Image data format information.
572
  */
573
1.57k
  cin.data_format.interleave=(unsigned char) ReadBlobByte(image);
574
1.57k
  offset++;
575
1.57k
  cin.data_format.packing=(unsigned char) ReadBlobByte(image);
576
1.57k
  offset++;
577
1.57k
  cin.data_format.sign=(unsigned char) ReadBlobByte(image);
578
1.57k
  offset++;
579
1.57k
  cin.data_format.sense=(unsigned char) ReadBlobByte(image);
580
1.57k
  offset++;
581
1.57k
  cin.data_format.line_pad=ReadBlobLong(image);
582
1.57k
  offset+=4;
583
1.57k
  cin.data_format.channel_pad=ReadBlobLong(image);
584
1.57k
  offset+=4;
585
1.57k
  offset+=ReadBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
586
1.57k
    cin.data_format.reserve);
587
  /*
588
    Image origination information.
589
  */
590
1.57k
  cin.origination.x_offset=ReadBlobSignedLong(image);
591
1.57k
  offset+=4;
592
1.57k
  if ((size_t) cin.origination.x_offset != ~0UL)
593
1.43k
    (void) FormatImageProperty(image,"dpx:origination.x_offset","%.20g",
594
1.43k
      (double) cin.origination.x_offset);
595
1.57k
  cin.origination.y_offset=(ssize_t) ReadBlobLong(image);
596
1.57k
  offset+=4;
597
1.57k
  if ((size_t) cin.origination.y_offset != ~0UL)
598
1.57k
    (void) FormatImageProperty(image,"dpx:origination.y_offset","%.20g",
599
1.57k
      (double) cin.origination.y_offset);
600
1.57k
  offset+=ReadBlob(image,sizeof(cin.origination.filename),(unsigned char *)
601
1.57k
    cin.origination.filename);
602
1.57k
  (void) CopyMagickString(property,cin.origination.filename,
603
1.57k
    sizeof(cin.origination.filename));
604
1.57k
  (void) SetImageProperty(image,"dpx:origination.filename",property,exception);
605
1.57k
  offset+=ReadBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
606
1.57k
    cin.origination.create_date);
607
1.57k
  (void) CopyMagickString(property,cin.origination.create_date,
608
1.57k
    sizeof(cin.origination.create_date));
609
1.57k
  (void) SetImageProperty(image,"dpx:origination.create_date",property,
610
1.57k
    exception);
611
1.57k
  offset+=ReadBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
612
1.57k
    cin.origination.create_time);
613
1.57k
  (void) CopyMagickString(property,cin.origination.create_time,
614
1.57k
    sizeof(cin.origination.create_time));
615
1.57k
  (void) SetImageProperty(image,"dpx:origination.create_time",property,
616
1.57k
    exception);
617
1.57k
  offset+=ReadBlob(image,sizeof(cin.origination.device),(unsigned char *)
618
1.57k
    cin.origination.device);
619
1.57k
  (void) CopyMagickString(property,cin.origination.device,
620
1.57k
    sizeof(cin.origination.device));
621
1.57k
  (void) SetImageProperty(image,"dpx:origination.device",property,exception);
622
1.57k
  offset+=ReadBlob(image,sizeof(cin.origination.model),(unsigned char *)
623
1.57k
    cin.origination.model);
624
1.57k
  (void) CopyMagickString(property,cin.origination.model,
625
1.57k
    sizeof(cin.origination.model));
626
1.57k
  (void) SetImageProperty(image,"dpx:origination.model",property,exception);
627
1.57k
  (void) memset(cin.origination.serial,0,
628
1.57k
    sizeof(cin.origination.serial));
629
1.57k
  offset+=ReadBlob(image,sizeof(cin.origination.serial),(unsigned char *)
630
1.57k
    cin.origination.serial);
631
1.57k
  (void) CopyMagickString(property,cin.origination.serial,
632
1.57k
    sizeof(cin.origination.serial));
633
1.57k
  (void) SetImageProperty(image,"dpx:origination.serial",property,exception);
634
1.57k
  cin.origination.x_pitch=ReadBlobFloat(image);
635
1.57k
  offset+=4;
636
1.57k
  cin.origination.y_pitch=ReadBlobFloat(image);
637
1.57k
  offset+=4;
638
1.57k
  cin.origination.gamma=ReadBlobFloat(image);
639
1.57k
  offset+=4;
640
1.57k
  if (IsFloatDefined(cin.origination.gamma) != MagickFalse)
641
566
    image->gamma=cin.origination.gamma;
642
1.57k
  offset+=ReadBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
643
1.57k
    cin.origination.reserve);
644
1.57k
  if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
645
279
    {
646
279
      int
647
279
        c;
648
649
      /*
650
        Image film information.
651
      */
652
279
      cin.film.id=(char) ReadBlobByte(image);
653
279
      offset++;
654
279
      c=cin.film.id;
655
279
      if (c != ~0)
656
93
        (void) FormatImageProperty(image,"dpx:film.id","%d",cin.film.id);
657
279
      cin.film.type=(char) ReadBlobByte(image);
658
279
      offset++;
659
279
      c=cin.film.type;
660
279
      if (c != ~0)
661
78
        (void) FormatImageProperty(image,"dpx:film.type","%d",cin.film.type);
662
279
      cin.film.offset=(char) ReadBlobByte(image);
663
279
      offset++;
664
279
      c=cin.film.offset;
665
279
      if (c != ~0)
666
77
        (void) FormatImageProperty(image,"dpx:film.offset","%d",
667
77
          cin.film.offset);
668
279
      cin.film.reserve1=(char) ReadBlobByte(image);
669
279
      offset++;
670
279
      cin.film.prefix=ReadBlobLong(image);
671
279
      offset+=4;
672
279
      if (cin.film.prefix != ~0UL)
673
279
        (void) FormatImageProperty(image,"dpx:film.prefix","%.20g",(double)
674
279
          cin.film.prefix);
675
279
      cin.film.count=ReadBlobLong(image);
676
279
      offset+=4;
677
279
      offset+=ReadBlob(image,sizeof(cin.film.format),(unsigned char *)
678
279
        cin.film.format);
679
279
      (void) CopyMagickString(property,cin.film.format,sizeof(cin.film.format));
680
279
      (void) SetImageProperty(image,"dpx:film.format",property,exception);
681
279
      cin.film.frame_position=ReadBlobLong(image);
682
279
      offset+=4;
683
279
      if (cin.film.frame_position != ~0UL)
684
279
        (void) FormatImageProperty(image,"dpx:film.frame_position","%.20g",
685
279
          (double) cin.film.frame_position);
686
279
      cin.film.frame_rate=ReadBlobFloat(image);
687
279
      offset+=4;
688
279
      if (IsFloatDefined(cin.film.frame_rate) != MagickFalse)
689
40
        (void) FormatImageProperty(image,"dpx:film.frame_rate","%g",
690
40
          (double) cin.film.frame_rate);
691
279
      offset+=ReadBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
692
279
        cin.film.frame_id);
693
279
      (void) CopyMagickString(property,cin.film.frame_id,
694
279
        sizeof(cin.film.frame_id));
695
279
      (void) SetImageProperty(image,"dpx:film.frame_id",property,exception);
696
279
      offset+=ReadBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
697
279
        cin.film.slate_info);
698
279
      (void) CopyMagickString(property,cin.film.slate_info,
699
279
        sizeof(cin.film.slate_info));
700
279
      (void) SetImageProperty(image,"dpx:film.slate_info",property,exception);
701
279
      offset+=ReadBlob(image,sizeof(cin.film.reserve),(unsigned char *)
702
279
        cin.film.reserve);
703
279
    }
704
1.57k
  if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
705
279
    {
706
279
      StringInfo
707
279
        *profile;
708
709
      /*
710
        User defined data.
711
      */
712
279
      if (cin.file.user_length > GetBlobSize(image))
713
145
        ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
714
134
      profile=AcquireProfileStringInfo("dpx:user.data",cin.file.user_length,
715
134
        exception);
716
134
      if (profile == (StringInfo *) NULL)
717
0
        offset=SeekBlob(image,(MagickOffsetType) cin.file.user_length,SEEK_CUR);
718
134
      else
719
134
        {
720
134
          offset+=ReadBlob(image,cin.file.user_length,
721
134
            GetStringInfoDatum(profile));
722
134
          (void) SetImageProfilePrivate(image,profile,exception);
723
134
        }
724
134
    }
725
1.42k
  image->depth=cin.image.channel[0].bits_per_pixel;
726
1.42k
  image->columns=cin.image.channel[0].pixels_per_line;
727
1.42k
  image->rows=cin.image.channel[0].lines_per_image;
728
1.42k
  if (image_info->ping != MagickFalse)
729
26
    {
730
26
      (void) CloseBlob(image);
731
26
      return(image);
732
26
    }
733
1.40k
  if (((MagickSizeType) image->columns*image->rows/8) > GetBlobSize(image))
734
1.22k
    ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
735
25.5k
  for ( ; offset < (MagickOffsetType) cin.file.image_offset; offset++)
736
24.5k
  {
737
24.5k
    int
738
24.5k
      c;
739
740
24.5k
    c=ReadBlobByte(image);
741
24.5k
    if (c == EOF)
742
154
      break;
743
24.5k
  }
744
1.22k
  if (offset < (MagickOffsetType) cin.file.image_offset)
745
1.06k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
746
1.06k
  status=SetImageExtent(image,image->columns,image->rows,exception);
747
1.06k
  if (status == MagickFalse)
748
66
    return(DestroyImageList(image));
749
1.00k
  (void) SetImageBackgroundColor(image,exception);
750
  /*
751
    Convert CIN raster image to pixel packets.
752
  */
753
1.00k
  quantum_info=AcquireQuantumInfo(image_info,image);
754
1.00k
  if (quantum_info == (QuantumInfo *) NULL)
755
1.00k
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
756
1.00k
  SetQuantumQuantum(quantum_info,32);
757
1.00k
  SetQuantumPack(quantum_info,MagickFalse);
758
1.00k
  quantum_type=RGBQuantum;
759
1.00k
  length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
760
1.00k
  if (cin.image.number_channels == 1)
761
620
    {
762
620
      quantum_type=GrayQuantum;
763
620
      length=GetBytesPerRow(image->columns,1,image->depth,MagickTrue);
764
620
    }
765
1.00k
  pixels=GetQuantumPixels(quantum_info);
766
32.8k
  for (y=0; y < (ssize_t) image->rows; y++)
767
32.2k
  {
768
32.2k
    const void
769
32.2k
      *stream;
770
771
32.2k
    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
772
32.2k
    if (q == (Quantum *) NULL)
773
0
      break;
774
32.2k
    stream=ReadBlobStream(image,length,pixels,&count);
775
32.2k
    if ((size_t) count != length)
776
402
      break;
777
31.8k
    (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
778
31.8k
      quantum_type,(unsigned char *) stream,exception);
779
31.8k
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
780
0
      break;
781
31.8k
    if (image->previous == (Image *) NULL)
782
31.8k
      {
783
31.8k
        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
784
31.8k
          image->rows);
785
31.8k
        if (status == MagickFalse)
786
0
          break;
787
31.8k
      }
788
31.8k
  }
789
1.00k
  SetQuantumImageType(image,quantum_type);
790
1.00k
  quantum_info=DestroyQuantumInfo(quantum_info);
791
1.00k
  if (EOFBlob(image) != MagickFalse)
792
402
    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
793
1.00k
      image->filename);
794
1.00k
  SetImageColorspace(image,LogColorspace,exception);
795
1.00k
  if (CloseBlob(image) == MagickFalse)
796
0
    status=MagickFalse;
797
1.00k
  if (status == MagickFalse)
798
0
    return(DestroyImageList(image));
799
1.00k
  return(GetFirstImageInList(image));
800
1.00k
}
801

802
/*
803
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804
%                                                                             %
805
%                                                                             %
806
%                                                                             %
807
%   R e g i s t e r C I N E O N I m a g e                                     %
808
%                                                                             %
809
%                                                                             %
810
%                                                                             %
811
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
812
%
813
%  RegisterCINImage() adds attributes for the CIN image format to the list of
814
%  of supported formats.  The attributes include the image format tag, a method
815
%  to read and/or write the format, whether the format supports the saving of
816
%  more than one frame to the same file or blob, whether the format supports
817
%  native in-memory I/O, and a brief description of the format.
818
%
819
%  The format of the RegisterCINImage method is:
820
%
821
%      size_t RegisterCINImage(void)
822
%
823
*/
824
ModuleExport size_t RegisterCINImage(void)
825
10
{
826
10
  MagickInfo
827
10
    *entry;
828
829
10
  entry=AcquireMagickInfo("CIN","CIN","Cineon Image File");
830
10
  entry->decoder=(DecodeImageHandler *) ReadCINImage;
831
10
  entry->encoder=(EncodeImageHandler *) WriteCINImage;
832
10
  entry->magick=(IsImageFormatHandler *) IsCIN;
833
10
  entry->flags|=CoderDecoderSeekableStreamFlag;
834
10
  entry->flags^=CoderAdjoinFlag;
835
10
  (void) RegisterMagickInfo(entry);
836
10
  return(MagickImageCoderSignature);
837
10
}
838

839
/*
840
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841
%                                                                             %
842
%                                                                             %
843
%                                                                             %
844
%   U n r e g i s t e r C I N E O N I m a g e                                 %
845
%                                                                             %
846
%                                                                             %
847
%                                                                             %
848
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
849
%
850
%  UnregisterCINImage() removes format registrations made by the CIN module
851
%  from the list of supported formats.
852
%
853
%  The format of the UnregisterCINImage method is:
854
%
855
%      UnregisterCINImage(void)
856
%
857
*/
858
ModuleExport void UnregisterCINImage(void)
859
0
{
860
0
  (void) UnregisterMagickInfo("CINEON");
861
0
}
862

863
/*
864
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865
%                                                                             %
866
%                                                                             %
867
%                                                                             %
868
%   W r i t e C I N E O N I m a g e                                           %
869
%                                                                             %
870
%                                                                             %
871
%                                                                             %
872
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873
%
874
%  WriteCINImage() writes an image in CIN encoded image format.
875
%
876
%  The format of the WriteCINImage method is:
877
%
878
%      MagickBooleanType WriteCINImage(const ImageInfo *image_info,
879
%        Image *image,ExceptionInfo *exception)
880
%
881
%  A description of each parameter follows.
882
%
883
%    o image_info: the image info.
884
%
885
%    o image:  The image.
886
%
887
%    o exception: return any errors or warnings in this structure.
888
%
889
*/
890
891
static inline const char *GetCINProperty(const ImageInfo *image_info,
892
  const Image *image,const char *property,ExceptionInfo *exception)
893
11.8k
{
894
11.8k
  const char
895
11.8k
    *value;
896
897
11.8k
  value=GetImageOption(image_info,property);
898
11.8k
  if (value != (const char *) NULL)
899
0
    return(value);
900
11.8k
  return(GetImageProperty(image,property,exception));
901
11.8k
}
902
903
static MagickBooleanType WriteCINImage(const ImageInfo *image_info,Image *image,
904
  ExceptionInfo *exception)
905
593
{
906
593
  char
907
593
    timestamp[MagickPathExtent];
908
909
593
  const char
910
593
    *value;
911
912
593
  CINInfo
913
593
    cin;
914
915
593
  const StringInfo
916
593
    *profile;
917
918
593
  MagickBooleanType
919
593
    status;
920
921
593
  MagickOffsetType
922
593
    offset;
923
924
593
  QuantumInfo
925
593
    *quantum_info;
926
927
593
  QuantumType
928
593
    quantum_type;
929
930
593
  const Quantum
931
593
    *p;
932
933
593
  ssize_t
934
593
    i;
935
936
593
  size_t
937
593
    length;
938
939
593
  ssize_t
940
593
    count,
941
593
    y;
942
943
593
  struct tm
944
593
    utc_time;
945
946
593
  time_t
947
593
    seconds;
948
949
593
  unsigned char
950
593
    *pixels;
951
952
  /*
953
    Open output image file.
954
  */
955
593
  assert(image_info != (const ImageInfo *) NULL);
956
593
  assert(image_info->signature == MagickCoreSignature);
957
593
  assert(image != (Image *) NULL);
958
593
  assert(image->signature == MagickCoreSignature);
959
593
  assert(exception != (ExceptionInfo *) NULL);
960
593
  assert(exception->signature == MagickCoreSignature);
961
593
  if (IsEventLogging() != MagickFalse)
962
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
963
593
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
964
593
  if (status == MagickFalse)
965
0
    return(status);
966
593
  if (image->colorspace != LogColorspace)
967
0
    (void) TransformImageColorspace(image,LogColorspace,exception);
968
  /*
969
    Write image information.
970
  */
971
593
  (void) memset(&cin,0,sizeof(cin));
972
593
  offset=0;
973
593
  cin.file.magic=0x802A5FD7UL;
974
593
  offset+=WriteBlobLong(image,(unsigned int) cin.file.magic);
975
593
  cin.file.image_offset=0x800;
976
593
  offset+=WriteBlobLong(image,(unsigned int) cin.file.image_offset);
977
593
  cin.file.generic_length=0x400;
978
593
  offset+=WriteBlobLong(image,(unsigned int) cin.file.generic_length);
979
593
  cin.file.industry_length=0x400;
980
593
  offset+=WriteBlobLong(image,(unsigned int) cin.file.industry_length);
981
593
  cin.file.user_length=0x00;
982
593
  profile=GetImageProfile(image,"dpx:user.data");
983
593
  if (profile != (StringInfo *) NULL)
984
40
    {
985
40
      cin.file.user_length+=(size_t) GetStringInfoLength(profile);
986
40
      cin.file.user_length=(((cin.file.user_length+0x2000-1)/0x2000)*0x2000);
987
40
    }
988
593
  offset+=WriteBlobLong(image,(unsigned int) cin.file.user_length);
989
593
  cin.file.file_size=4*image->columns*image->rows+0x2000;
990
593
  offset+=WriteBlobLong(image,(unsigned int) cin.file.file_size);
991
593
  (void) CopyMagickString(cin.file.version,"V4.5",sizeof(cin.file.version));
992
593
  offset+=WriteBlob(image,sizeof(cin.file.version),(unsigned char *)
993
593
    cin.file.version);
994
593
  value=GetCINProperty(image_info,image,"dpx:file.filename",exception);
995
593
  if (value != (const char *) NULL)
996
593
    (void) CopyMagickString(cin.file.filename,value,sizeof(cin.file.filename));
997
0
  else
998
0
    (void) CopyMagickString(cin.file.filename,image->filename,
999
0
      sizeof(cin.file.filename));
1000
593
  offset+=WriteBlob(image,sizeof(cin.file.filename),(unsigned char *)
1001
593
    cin.file.filename);
1002
593
  seconds=GetMagickTime();
1003
593
  GetMagickUTCTime(&seconds,&utc_time);
1004
593
  (void) memset(timestamp,0,sizeof(timestamp));
1005
593
  (void) strftime(timestamp,MagickPathExtent,"%Y:%m:%d:%H:%M:%SUTC",&utc_time);
1006
593
  (void) memset(cin.file.create_date,0,sizeof(cin.file.create_date));
1007
593
  (void) CopyMagickString(cin.file.create_date,timestamp,11);
1008
593
  offset+=WriteBlob(image,sizeof(cin.file.create_date),(unsigned char *)
1009
593
    cin.file.create_date);
1010
593
  (void) memset(cin.file.create_time,0,sizeof(cin.file.create_time));
1011
593
  (void) CopyMagickString(cin.file.create_time,timestamp+11,11);
1012
593
  offset+=WriteBlob(image,sizeof(cin.file.create_time),(unsigned char *)
1013
593
    cin.file.create_time);
1014
593
  offset+=WriteBlob(image,sizeof(cin.file.reserve),(unsigned char *)
1015
593
    cin.file.reserve);
1016
593
  cin.image.orientation=0x00;
1017
593
  offset+=WriteBlobByte(image,cin.image.orientation);
1018
593
  cin.image.number_channels=3;
1019
593
  offset+=WriteBlobByte(image,cin.image.number_channels);
1020
593
  offset+=WriteBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
1021
593
    cin.image.reserve1);
1022
5.33k
  for (i=0; i < 8; i++)
1023
4.74k
  {
1024
4.74k
    cin.image.channel[i].designator[0]=0; /* universal metric */
1025
4.74k
    offset+=WriteBlobByte(image,cin.image.channel[0].designator[0]);
1026
4.74k
    cin.image.channel[i].designator[1]=(unsigned char) (i > 3 ? 0 : i+1); /* channel color */;
1027
4.74k
    offset+=WriteBlobByte(image,cin.image.channel[1].designator[0]);
1028
4.74k
    cin.image.channel[i].bits_per_pixel=(unsigned char) image->depth;
1029
4.74k
    offset+=WriteBlobByte(image,cin.image.channel[0].bits_per_pixel);
1030
4.74k
    offset+=WriteBlobByte(image,cin.image.channel[0].reserve);
1031
4.74k
    cin.image.channel[i].pixels_per_line=image->columns;
1032
4.74k
    offset+=WriteBlobLong(image,(unsigned int)
1033
4.74k
      cin.image.channel[0].pixels_per_line);
1034
4.74k
    cin.image.channel[i].lines_per_image=image->rows;
1035
4.74k
    offset+=WriteBlobLong(image,(unsigned int)
1036
4.74k
      cin.image.channel[0].lines_per_image);
1037
4.74k
    cin.image.channel[i].min_data=0;
1038
4.74k
    offset+=WriteBlobFloat(image,cin.image.channel[0].min_data);
1039
4.74k
    cin.image.channel[i].min_quantity=0.0;
1040
4.74k
    offset+=WriteBlobFloat(image,cin.image.channel[0].min_quantity);
1041
4.74k
    cin.image.channel[i].max_data=(float) ((MagickOffsetType)
1042
4.74k
      GetQuantumRange(image->depth));
1043
4.74k
    offset+=WriteBlobFloat(image,cin.image.channel[0].max_data);
1044
4.74k
    cin.image.channel[i].max_quantity=2.048f;
1045
4.74k
    offset+=WriteBlobFloat(image,cin.image.channel[0].max_quantity);
1046
4.74k
  }
1047
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.white_point.x);
1048
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.white_point.y);
1049
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.red_primary.x);
1050
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.red_primary.y);
1051
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.green_primary.x);
1052
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.green_primary.y);
1053
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.blue_primary.x);
1054
593
  offset+=WriteBlobFloat(image,(float) image->chromaticity.blue_primary.y);
1055
593
  value=GetCINProperty(image_info,image,"dpx:image.label",exception);
1056
593
  if (value != (const char *) NULL)
1057
593
    (void) CopyMagickString(cin.image.label,value,sizeof(cin.image.label));
1058
593
  offset+=WriteBlob(image,sizeof(cin.image.label),(unsigned char *)
1059
593
    cin.image.label);
1060
593
  offset+=WriteBlob(image,sizeof(cin.image.reserve),(unsigned char *)
1061
593
    cin.image.reserve);
1062
  /*
1063
    Write data format information.
1064
  */
1065
593
  cin.data_format.interleave=0; /* pixel interleave (rgbrgbr...) */
1066
593
  offset+=WriteBlobByte(image,cin.data_format.interleave);
1067
593
  cin.data_format.packing=5; /* packing ssize_tword (32bit) boundaries */
1068
593
  offset+=WriteBlobByte(image,cin.data_format.packing);
1069
593
  cin.data_format.sign=0; /* unsigned data */
1070
593
  offset+=WriteBlobByte(image,cin.data_format.sign);
1071
593
  cin.data_format.sense=0; /* image sense: positive image */
1072
593
  offset+=WriteBlobByte(image,cin.data_format.sense);
1073
593
  cin.data_format.line_pad=0;
1074
593
  offset+=WriteBlobLong(image,(unsigned int) cin.data_format.line_pad);
1075
593
  cin.data_format.channel_pad=0;
1076
593
  offset+=WriteBlobLong(image,(unsigned int) cin.data_format.channel_pad);
1077
593
  offset+=WriteBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
1078
593
    cin.data_format.reserve);
1079
  /*
1080
    Write origination information.
1081
  */
1082
593
  cin.origination.x_offset=0UL;
1083
593
  value=GetCINProperty(image_info,image,"dpx:origination.x_offset",exception);
1084
593
  if (value != (const char *) NULL)
1085
519
    cin.origination.x_offset=(ssize_t) StringToLong(value);
1086
593
  offset+=WriteBlobLong(image,(unsigned int) cin.origination.x_offset);
1087
593
  cin.origination.y_offset=0UL;
1088
593
  value=GetCINProperty(image_info,image,"dpx:origination.y_offset",exception);
1089
593
  if (value != (const char *) NULL)
1090
593
    cin.origination.y_offset=(ssize_t) StringToLong(value);
1091
593
  offset+=WriteBlobLong(image,(unsigned int) cin.origination.y_offset);
1092
593
  value=GetCINProperty(image_info,image,"dpx:origination.filename",exception);
1093
593
  if (value != (const char *) NULL)
1094
593
    (void) CopyMagickString(cin.origination.filename,value,
1095
593
      sizeof(cin.origination.filename));
1096
0
  else
1097
0
    (void) CopyMagickString(cin.origination.filename,image->filename,
1098
0
      sizeof(cin.origination.filename));
1099
593
  offset+=WriteBlob(image,sizeof(cin.origination.filename),(unsigned char *)
1100
593
    cin.origination.filename);
1101
593
  (void) memset(timestamp,0,sizeof(timestamp));
1102
593
  (void) strftime(timestamp,MagickPathExtent,"%Y:%m:%d:%H:%M:%SUTC",&utc_time);
1103
593
  (void) memset(cin.origination.create_date,0,
1104
593
    sizeof(cin.origination.create_date));
1105
593
  (void) CopyMagickString(cin.origination.create_date,timestamp,11);
1106
593
  offset+=WriteBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
1107
593
    cin.origination.create_date);
1108
593
  (void) memset(cin.origination.create_time,0,
1109
593
     sizeof(cin.origination.create_time));
1110
593
  (void) CopyMagickString(cin.origination.create_time,timestamp+11,15);
1111
593
  offset+=WriteBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
1112
593
    cin.origination.create_time);
1113
593
  value=GetCINProperty(image_info,image,"dpx:origination.device",exception);
1114
593
  if (value != (const char *) NULL)
1115
593
    (void) CopyMagickString(cin.origination.device,value,
1116
593
      sizeof(cin.origination.device));
1117
593
  offset+=WriteBlob(image,sizeof(cin.origination.device),(unsigned char *)
1118
593
    cin.origination.device);
1119
593
  value=GetCINProperty(image_info,image,"dpx:origination.model",exception);
1120
593
  if (value != (const char *) NULL)
1121
593
    (void) CopyMagickString(cin.origination.model,value,
1122
593
      sizeof(cin.origination.model));
1123
593
  offset+=WriteBlob(image,sizeof(cin.origination.model),(unsigned char *)
1124
593
    cin.origination.model);
1125
593
  value=GetCINProperty(image_info,image,"dpx:origination.serial",exception);
1126
593
  if (value != (const char *) NULL)
1127
593
    (void) CopyMagickString(cin.origination.serial,value,
1128
593
      sizeof(cin.origination.serial));
1129
593
  offset+=WriteBlob(image,sizeof(cin.origination.serial),(unsigned char *)
1130
593
    cin.origination.serial);
1131
593
  cin.origination.x_pitch=0.0f;
1132
593
  value=GetCINProperty(image_info,image,"dpx:origination.x_pitch",exception);
1133
593
  if (value != (const char *) NULL)
1134
0
    cin.origination.x_pitch=StringToFloat(value,(char **) NULL);
1135
593
  offset+=WriteBlobFloat(image,cin.origination.x_pitch);
1136
593
  cin.origination.y_pitch=0.0f;
1137
593
  value=GetCINProperty(image_info,image,"dpx:origination.y_pitch",exception);
1138
593
  if (value != (const char *) NULL)
1139
0
    cin.origination.y_pitch=StringToFloat(value,(char **) NULL);
1140
593
  offset+=WriteBlobFloat(image,cin.origination.y_pitch);
1141
593
  cin.origination.gamma=(float) image->gamma;
1142
593
  offset+=WriteBlobFloat(image,cin.origination.gamma);
1143
593
  offset+=WriteBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
1144
593
    cin.origination.reserve);
1145
  /*
1146
    Image film information.
1147
  */
1148
593
  cin.film.id=0;
1149
593
  value=GetCINProperty(image_info,image,"dpx:film.id",exception);
1150
593
  if (value != (const char *) NULL)
1151
35
    cin.film.id=(char) StringToLong(value);
1152
593
  offset+=WriteBlobByte(image,(unsigned char) cin.film.id);
1153
593
  cin.film.type=0;
1154
593
  value=GetCINProperty(image_info,image,"dpx:film.type",exception);
1155
593
  if (value != (const char *) NULL)
1156
31
    cin.film.type=(char) StringToLong(value);
1157
593
  offset+=WriteBlobByte(image,(unsigned char) cin.film.type);
1158
593
  cin.film.offset=0;
1159
593
  value=GetCINProperty(image_info,image,"dpx:film.offset",exception);
1160
593
  if (value != (const char *) NULL)
1161
33
    cin.film.offset=(char) StringToLong(value);
1162
593
  offset+=WriteBlobByte(image,(unsigned char) cin.film.offset);
1163
593
  offset+=WriteBlobByte(image,(unsigned char) cin.film.reserve1);
1164
593
  cin.film.prefix=0UL;
1165
593
  value=GetCINProperty(image_info,image,"dpx:film.prefix",exception);
1166
593
  if (value != (const char *) NULL)
1167
40
    cin.film.prefix=StringToUnsignedLong(value);
1168
593
  offset+=WriteBlobLong(image,(unsigned int) cin.film.prefix);
1169
593
  cin.film.count=0UL;
1170
593
  value=GetCINProperty(image_info,image,"dpx:film.count",exception);
1171
593
  if (value != (const char *) NULL)
1172
0
    cin.film.count=StringToUnsignedLong(value);
1173
593
  offset+=WriteBlobLong(image,(unsigned int) cin.film.count);
1174
593
  value=GetCINProperty(image_info,image,"dpx:film.format",exception);
1175
593
  if (value != (const char *) NULL)
1176
40
    (void) CopyMagickString(cin.film.format,value,sizeof(cin.film.format));
1177
593
  offset+=WriteBlob(image,sizeof(cin.film.format),(unsigned char *)
1178
593
    cin.film.format);
1179
593
  cin.film.frame_position=0UL;
1180
593
  value=GetCINProperty(image_info,image,"dpx:film.frame_position",exception);
1181
593
  if (value != (const char *) NULL)
1182
40
    cin.film.frame_position=StringToUnsignedLong(value);
1183
593
  offset+=WriteBlobLong(image,(unsigned int) cin.film.frame_position);
1184
593
  cin.film.frame_rate=0.0f;
1185
593
  value=GetCINProperty(image_info,image,"dpx:film.frame_rate",exception);
1186
593
  if (value != (const char *) NULL)
1187
20
    cin.film.frame_rate=StringToFloat(value,(char **) NULL);
1188
593
  offset+=WriteBlobFloat(image,cin.film.frame_rate);
1189
593
  value=GetCINProperty(image_info,image,"dpx:film.frame_id",exception);
1190
593
  if (value != (const char *) NULL)
1191
40
    (void) CopyMagickString(cin.film.frame_id,value,sizeof(cin.film.frame_id));
1192
593
  offset+=WriteBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
1193
593
    cin.film.frame_id);
1194
593
  value=GetCINProperty(image_info,image,"dpx:film.slate_info",exception);
1195
593
  if (value != (const char *) NULL)
1196
40
    (void) CopyMagickString(cin.film.slate_info,value,
1197
40
      sizeof(cin.film.slate_info));
1198
593
  offset+=WriteBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
1199
593
    cin.film.slate_info);
1200
593
  offset+=WriteBlob(image,sizeof(cin.film.reserve),(unsigned char *)
1201
593
    cin.film.reserve);
1202
593
  if (profile != (StringInfo *) NULL)
1203
40
    offset+=WriteBlob(image,GetStringInfoLength(profile),
1204
40
      GetStringInfoDatum(profile));
1205
593
  while (offset < (MagickOffsetType) cin.file.image_offset)
1206
0
    offset+=WriteBlobByte(image,0x00);
1207
  /*
1208
    Convert pixel packets to CIN raster image.
1209
  */
1210
593
  quantum_info=AcquireQuantumInfo(image_info,image);
1211
593
  if (quantum_info == (QuantumInfo *) NULL)
1212
593
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1213
593
  SetQuantumQuantum(quantum_info,32);
1214
593
  SetQuantumPack(quantum_info,MagickFalse);
1215
593
  quantum_type=RGBQuantum;
1216
593
  pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1217
593
  length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
1218
26.1k
  for (y=0; y < (ssize_t) image->rows; y++)
1219
25.5k
  {
1220
25.5k
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1221
25.5k
    if (p == (const Quantum *) NULL)
1222
0
      break;
1223
25.5k
    (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1224
25.5k
      quantum_type,pixels,exception);
1225
25.5k
    count=WriteBlob(image,length,pixels);
1226
25.5k
    if (count != (ssize_t) length)
1227
0
      break;
1228
25.5k
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1229
25.5k
      image->rows);
1230
25.5k
    if (status == MagickFalse)
1231
0
      break;
1232
25.5k
  }
1233
593
  quantum_info=DestroyQuantumInfo(quantum_info);
1234
593
  if (CloseBlob(image) == MagickFalse)
1235
0
    status=MagickFalse;
1236
593
  return(status);
1237
593
}