blob: 58f258d10ca58ad6f4c9761a6027b483e113af84 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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% John Cristy %
19% Kelly Bergougnoux %
20% October 2003 %
21% %
22% %
cristy1454be72011-12-19 01:52:48 +000023% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000024% dedicated to making software imaging solutions freely available. %
25% %
26% You may not use this file except in compliance with the License. You may %
27% obtain a copy of the License at %
28% %
29% http://www.imagemagick.org/script/license.php %
30% %
31% Unless required by applicable law or agreed to in writing, software %
32% distributed under the License is distributed on an "AS IS" BASIS, %
33% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
34% See the License for the specific language governing permissions and %
35% limitations under the License. %
36% %
37% %
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39%
40% Cineon image file format draft is available at
41% http://www.cineon.com/ff_draft.php.
42%
43%
44*/
45
46/*
47 Include declarations.
48*/
cristy4c08aed2011-07-01 19:47:50 +000049#include "MagickCore/studio.h"
50#include "MagickCore/blob.h"
51#include "MagickCore/blob-private.h"
52#include "MagickCore/cache.h"
53#include "MagickCore/colorspace.h"
54#include "MagickCore/exception.h"
55#include "MagickCore/exception-private.h"
56#include "MagickCore/image.h"
57#include "MagickCore/image-private.h"
58#include "MagickCore/list.h"
59#include "MagickCore/magick.h"
60#include "MagickCore/memory_.h"
61#include "MagickCore/monitor.h"
62#include "MagickCore/monitor-private.h"
63#include "MagickCore/option.h"
64#include "MagickCore/profile.h"
65#include "MagickCore/property.h"
66#include "MagickCore/quantum-private.h"
67#include "MagickCore/quantum-private.h"
68#include "MagickCore/static.h"
69#include "MagickCore/string_.h"
70#include "MagickCore/string-private.h"
71#include "MagickCore/module.h"
cristy3ed852e2009-09-05 21:47:34 +000072
73/*
74 Typedef declaration.
75*/
76typedef struct _CINDataFormatInfo
77{
78 unsigned char
79 interleave,
80 packing,
81 sign,
82 sense;
83
cristyf6fe0a12010-05-30 00:44:47 +000084 size_t
cristy3ed852e2009-09-05 21:47:34 +000085 line_pad,
86 channel_pad;
87
88 unsigned char
89 reserve[20];
90} CINDataFormatInfo;
91
92typedef struct _CINFileInfo
93{
cristyf6fe0a12010-05-30 00:44:47 +000094 size_t
cristy3ed852e2009-09-05 21:47:34 +000095 magic,
96 image_offset,
97 generic_length,
98 industry_length,
99 user_length,
100 file_size;
101
102 char
103 version[8],
104 filename[100],
105 create_date[12],
106 create_time[12],
107 reserve[36];
108} CINFileInfo;
109
110typedef struct _CINFilmInfo
111{
112 char
113 id,
114 type,
115 offset,
116 reserve1;
117
cristyf6fe0a12010-05-30 00:44:47 +0000118 size_t
cristy3ed852e2009-09-05 21:47:34 +0000119 prefix,
120 count;
121
122 char
123 format[32];
124
cristyf6fe0a12010-05-30 00:44:47 +0000125 size_t
cristy3ed852e2009-09-05 21:47:34 +0000126 frame_position;
127
128 float
129 frame_rate;
130
131 char
132 frame_id[32],
133 slate_info[200],
134 reserve[740];
135} CINFilmInfo;
136
137typedef struct _CINImageChannel
138{
139 unsigned char
140 designator[2],
141 bits_per_pixel,
142 reserve;
143
cristyf6fe0a12010-05-30 00:44:47 +0000144 size_t
cristy3ed852e2009-09-05 21:47:34 +0000145 pixels_per_line,
146 lines_per_image;
147
148 float
149 min_data,
150 min_quantity,
151 max_data,
152 max_quantity;
153} CINImageChannel;
154
155typedef struct _CINImageInfo
156{
157 unsigned char
158 orientation,
159 number_channels,
160 reserve1[2];
161
162 CINImageChannel
163 channel[8];
164
165 float
166 white_point[2],
167 red_primary_chromaticity[2],
168 green_primary_chromaticity[2],
169 blue_primary_chromaticity[2];
170
171 char
172 label[200],
173 reserve[28];
174} CINImageInfo;
175
176typedef struct _CINOriginationInfo
177{
cristyf6fe0a12010-05-30 00:44:47 +0000178 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000179 x_offset,
180 y_offset;
181
182 char
183 filename[100],
184 create_date[12],
185 create_time[12],
186 device[64],
187 model[32],
188 serial[32];
189
190 float
191 x_pitch,
192 y_pitch,
193 gamma;
194
195 char
196 reserve[40];
197} CINOriginationInfo;
198
199typedef struct _CINUserInfo
200{
201 char
202 id[32];
203} CINUserInfo;
204
205typedef struct CINInfo
206{
207 CINFileInfo
208 file;
209
210 CINImageInfo
211 image;
212
213 CINDataFormatInfo
214 data_format;
215
216 CINOriginationInfo
217 origination;
218
219 CINFilmInfo
220 film;
221
222 CINUserInfo
223 user;
224} CINInfo;
225
226/*
227 Forward declaractions.
228*/
229static MagickBooleanType
cristy1e178e72011-08-28 19:44:34 +0000230 WriteCINImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000231
232/*
233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234% %
235% %
236% %
237% I s C I N E O N %
238% %
239% %
240% %
241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242%
243% IsCIN() returns MagickTrue if the image format type, identified by the magick
244% string, is CIN.
245%
246% The format of the IsCIN method is:
247%
248% MagickBooleanType IsCIN(const unsigned char *magick,const size_t length)
249%
250% A description of each parameter follows:
251%
252% o magick: compare image format pattern against these bytes.
253%
254% o length: Specifies the length of the magick string.
255%
256*/
257static MagickBooleanType IsCIN(const unsigned char *magick,const size_t length)
258{
259 if (length < 4)
260 return(MagickFalse);
261 if (memcmp(magick,"\200\052\137\327",4) == 0)
262 return(MagickTrue);
263 return(MagickFalse);
264}
265
266/*
267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268% %
269% %
270% %
271% R e a d C I N E O N I m a g e %
272% %
273% %
274% %
275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276%
277% ReadCINImage() reads an CIN X image file and returns it. It allocates
278% the memory necessary for the new Image structure and returns a point to the
279% new image.
280%
281% The format of the ReadCINImage method is:
282%
283% Image *ReadCINImage(const ImageInfo *image_info,
284% ExceptionInfo *exception)
285%
286% A description of each parameter follows:
287%
288% o image_info: the image info.
289%
290% o exception: return any errors or warnings in this structure.
291%
292*/
293
cristybb503372010-05-27 20:51:26 +0000294static size_t GetBytesPerRow(size_t columns,
295 size_t samples_per_pixel,size_t bits_per_pixel,
cristy3ed852e2009-09-05 21:47:34 +0000296 MagickBooleanType pad)
297{
298 size_t
299 bytes_per_row;
300
301 switch (bits_per_pixel)
302 {
303 case 1:
304 {
305 bytes_per_row=4*(((size_t) samples_per_pixel*columns*
306 bits_per_pixel+31)/32);
307 break;
308 }
309 case 8:
310 default:
311 {
312 bytes_per_row=4*(((size_t) samples_per_pixel*columns*
313 bits_per_pixel+31)/32);
314 break;
315 }
316 case 10:
317 {
318 if (pad == MagickFalse)
319 {
320 bytes_per_row=4*(((size_t) samples_per_pixel*columns*
321 bits_per_pixel+31)/32);
322 break;
323 }
324 bytes_per_row=4*(((size_t) (32*((samples_per_pixel*columns+2)/3))+31)/32);
325 break;
326 }
327 case 12:
328 {
329 if (pad == MagickFalse)
330 {
331 bytes_per_row=4*(((size_t) samples_per_pixel*columns*
332 bits_per_pixel+31)/32);
333 break;
334 }
335 bytes_per_row=2*(((size_t) (16*samples_per_pixel*columns)+15)/16);
336 break;
337 }
338 case 16:
339 {
340 bytes_per_row=2*(((size_t) samples_per_pixel*columns*
341 bits_per_pixel+8)/16);
342 break;
343 }
344 case 32:
345 {
346 bytes_per_row=4*(((size_t) samples_per_pixel*columns*
347 bits_per_pixel+31)/32);
348 break;
349 }
350 case 64:
351 {
352 bytes_per_row=8*(((size_t) samples_per_pixel*columns*
353 bits_per_pixel+63)/64);
354 break;
355 }
356 }
357 return(bytes_per_row);
358}
359
360static inline MagickBooleanType IsFloatDefined(const float value)
361{
362 union
363 {
cristy97450ff2010-12-29 17:29:17 +0000364 unsigned int
cristy3ed852e2009-09-05 21:47:34 +0000365 unsigned_value;
366
367 double
368 float_value;
369 } quantum;
370
cristy97450ff2010-12-29 17:29:17 +0000371 quantum.unsigned_value=0U;
cristy3ed852e2009-09-05 21:47:34 +0000372 quantum.float_value=value;
cristy97450ff2010-12-29 17:29:17 +0000373 if (quantum.unsigned_value == 0U)
cristy3ed852e2009-09-05 21:47:34 +0000374 return(MagickFalse);
375 return(MagickTrue);
376}
377
cristy4e82e512011-04-24 01:33:42 +0000378static Image *ReadCINImage(const ImageInfo *image_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000379{
380#define MonoColorType 1
381#define RGBColorType 3
382
cristy3ed852e2009-09-05 21:47:34 +0000383 CINInfo
384 cin;
385
386 Image
387 *image;
388
cristy3ed852e2009-09-05 21:47:34 +0000389 MagickBooleanType
390 status;
391
392 MagickOffsetType
393 offset;
394
395 QuantumInfo
396 *quantum_info;
397
398 QuantumType
399 quantum_type;
400
cristybb503372010-05-27 20:51:26 +0000401 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000402 i;
403
cristy4c08aed2011-07-01 19:47:50 +0000404 register Quantum
cristy3ed852e2009-09-05 21:47:34 +0000405 *q;
406
407 size_t
cristy5a128302011-05-17 12:42:40 +0000408 length;
cristy3ed852e2009-09-05 21:47:34 +0000409
410 ssize_t
cristy4e82e512011-04-24 01:33:42 +0000411 count,
412 y;
cristy3ed852e2009-09-05 21:47:34 +0000413
414 unsigned char
cristya9c6cd62011-05-18 21:11:35 +0000415 magick[4],
cristy3ed852e2009-09-05 21:47:34 +0000416 *pixels;
417
cristy3ed852e2009-09-05 21:47:34 +0000418 /*
419 Open image file.
420 */
421 assert(image_info != (const ImageInfo *) NULL);
422 assert(image_info->signature == MagickSignature);
423 if (image_info->debug != MagickFalse)
424 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
425 image_info->filename);
426 assert(exception != (ExceptionInfo *) NULL);
427 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000428 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000429 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
430 if (status == MagickFalse)
431 {
432 image=DestroyImageList(image);
433 return((Image *) NULL);
434 }
435 /*
436 File information.
437 */
438 offset=0;
cristya9c6cd62011-05-18 21:11:35 +0000439 count=ReadBlob(image,4,magick);
cristy3ed852e2009-09-05 21:47:34 +0000440 offset+=count;
441 if ((count != 4) ||
442 ((LocaleNCompare((char *) magick,"\200\052\137\327",4) != 0)))
443 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristya9c6cd62011-05-18 21:11:35 +0000444 image->endian=(magick[0] == 0x80) && (magick[1] == 0x2a) &&
445 (magick[2] == 0x5f) && (magick[3] == 0xd7) ? MSBEndian : LSBEndian;
cristy3ed852e2009-09-05 21:47:34 +0000446 cin.file.image_offset=ReadBlobLong(image);
447 offset+=4;
448 cin.file.generic_length=ReadBlobLong(image);
449 offset+=4;
450 cin.file.industry_length=ReadBlobLong(image);
451 offset+=4;
452 cin.file.user_length=ReadBlobLong(image);
453 offset+=4;
454 cin.file.file_size=ReadBlobLong(image);
455 offset+=4;
456 offset+=ReadBlob(image,sizeof(cin.file.version),(unsigned char *)
457 cin.file.version);
cristyd15e6592011-10-15 00:13:06 +0000458 (void) SetImageProperty(image,"dpx:file.version",cin.file.version,exception);
cristy3ed852e2009-09-05 21:47:34 +0000459 offset+=ReadBlob(image,sizeof(cin.file.filename),(unsigned char *)
460 cin.file.filename);
cristyd15e6592011-10-15 00:13:06 +0000461 (void) SetImageProperty(image,"dpx:file.filename",cin.file.filename,
462 exception);
cristy3ed852e2009-09-05 21:47:34 +0000463 offset+=ReadBlob(image,sizeof(cin.file.create_date),(unsigned char *)
464 cin.file.create_date);
cristyd15e6592011-10-15 00:13:06 +0000465 (void) SetImageProperty(image,"dpx:file.create_date",cin.file.create_date,
466 exception);
cristy3ed852e2009-09-05 21:47:34 +0000467 offset+=ReadBlob(image,sizeof(cin.file.create_time),(unsigned char *)
468 cin.file.create_time);
cristyd15e6592011-10-15 00:13:06 +0000469 (void) SetImageProperty(image,"dpx:file.create_time",cin.file.create_time,
470 exception);
cristy3ed852e2009-09-05 21:47:34 +0000471 offset+=ReadBlob(image,sizeof(cin.file.reserve),(unsigned char *)
472 cin.file.reserve);
473 /*
474 Image information.
475 */
476 cin.image.orientation=(unsigned char) ReadBlobByte(image);
477 offset++;
478 if (cin.image.orientation != (unsigned char) (~0U))
cristy97450ff2010-12-29 17:29:17 +0000479 (void) FormatImageProperty(image,"dpx:image.orientation","%d",
cristy3ed852e2009-09-05 21:47:34 +0000480 cin.image.orientation);
481 switch (cin.image.orientation)
482 {
483 default:
cristy4e82e512011-04-24 01:33:42 +0000484 case 0: image->orientation=TopLeftOrientation; break;
485 case 1: image->orientation=TopRightOrientation; break;
486 case 2: image->orientation=BottomLeftOrientation; break;
487 case 3: image->orientation=BottomRightOrientation; break;
488 case 4: image->orientation=LeftTopOrientation; break;
489 case 5: image->orientation=RightTopOrientation; break;
490 case 6: image->orientation=LeftBottomOrientation; break;
491 case 7: image->orientation=RightBottomOrientation; break;
cristy3ed852e2009-09-05 21:47:34 +0000492 }
493 cin.image.number_channels=(unsigned char) ReadBlobByte(image);
494 offset++;
495 offset+=ReadBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
496 cin.image.reserve1);
497 for (i=0; i < 8; i++)
498 {
499 cin.image.channel[i].designator[0]=(unsigned char) ReadBlobByte(image);
500 offset++;
501 cin.image.channel[i].designator[1]=(unsigned char) ReadBlobByte(image);
502 offset++;
503 cin.image.channel[i].bits_per_pixel=(unsigned char) ReadBlobByte(image);
504 offset++;
505 cin.image.channel[i].reserve=(unsigned char) ReadBlobByte(image);
506 offset++;
507 cin.image.channel[i].pixels_per_line=ReadBlobLong(image);
508 offset+=4;
509 cin.image.channel[i].lines_per_image=ReadBlobLong(image);
510 offset+=4;
511 cin.image.channel[i].min_data=ReadBlobFloat(image);
512 offset+=4;
513 cin.image.channel[i].min_quantity=ReadBlobFloat(image);
514 offset+=4;
515 cin.image.channel[i].max_data=ReadBlobFloat(image);
516 offset+=4;
517 cin.image.channel[i].max_quantity=ReadBlobFloat(image);
518 offset+=4;
519 }
520 cin.image.white_point[0]=ReadBlobFloat(image);
521 offset+=4;
522 if (IsFloatDefined(cin.image.white_point[0]) != MagickFalse)
523 image->chromaticity.white_point.x=cin.image.white_point[0];
524 cin.image.white_point[1]=ReadBlobFloat(image);
525 offset+=4;
526 if (IsFloatDefined(cin.image.white_point[1]) != MagickFalse)
527 image->chromaticity.white_point.y=cin.image.white_point[1];
528 cin.image.red_primary_chromaticity[0]=ReadBlobFloat(image);
529 offset+=4;
530 if (IsFloatDefined(cin.image.red_primary_chromaticity[0]) != MagickFalse)
531 image->chromaticity.red_primary.x=cin.image.red_primary_chromaticity[0];
532 cin.image.red_primary_chromaticity[1]=ReadBlobFloat(image);
533 offset+=4;
534 if (IsFloatDefined(cin.image.red_primary_chromaticity[1]) != MagickFalse)
535 image->chromaticity.red_primary.y=cin.image.red_primary_chromaticity[1];
536 cin.image.green_primary_chromaticity[0]=ReadBlobFloat(image);
537 offset+=4;
538 if (IsFloatDefined(cin.image.green_primary_chromaticity[0]) != MagickFalse)
539 image->chromaticity.red_primary.x=cin.image.green_primary_chromaticity[0];
540 cin.image.green_primary_chromaticity[1]=ReadBlobFloat(image);
541 offset+=4;
542 if (IsFloatDefined(cin.image.green_primary_chromaticity[1]) != MagickFalse)
543 image->chromaticity.green_primary.y=cin.image.green_primary_chromaticity[1];
544 cin.image.blue_primary_chromaticity[0]=ReadBlobFloat(image);
545 offset+=4;
546 if (IsFloatDefined(cin.image.blue_primary_chromaticity[0]) != MagickFalse)
547 image->chromaticity.blue_primary.x=cin.image.blue_primary_chromaticity[0];
548 cin.image.blue_primary_chromaticity[1]=ReadBlobFloat(image);
549 offset+=4;
550 if (IsFloatDefined(cin.image.blue_primary_chromaticity[1]) != MagickFalse)
551 image->chromaticity.blue_primary.y=cin.image.blue_primary_chromaticity[1];
552 offset+=ReadBlob(image,sizeof(cin.image.label),(unsigned char *)
553 cin.image.label);
cristyd15e6592011-10-15 00:13:06 +0000554 (void) SetImageProperty(image,"dpx:image.label",cin.image.label,exception);
cristy3ed852e2009-09-05 21:47:34 +0000555 offset+=ReadBlob(image,sizeof(cin.image.reserve),(unsigned char *)
556 cin.image.reserve);
557 /*
558 Image data format information.
559 */
560 cin.data_format.interleave=(unsigned char) ReadBlobByte(image);
561 offset++;
562 cin.data_format.packing=(unsigned char) ReadBlobByte(image);
563 offset++;
564 cin.data_format.sign=(unsigned char) ReadBlobByte(image);
565 offset++;
566 cin.data_format.sense=(unsigned char) ReadBlobByte(image);
567 offset++;
568 cin.data_format.line_pad=ReadBlobLong(image);
569 offset+=4;
570 cin.data_format.channel_pad=ReadBlobLong(image);
571 offset+=4;
572 offset+=ReadBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
573 cin.data_format.reserve);
574 /*
575 Image origination information.
576 */
cristy6cff05d2010-09-02 11:22:46 +0000577 cin.origination.x_offset=(int) ReadBlobLong(image);
cristy3ed852e2009-09-05 21:47:34 +0000578 offset+=4;
cristybb503372010-05-27 20:51:26 +0000579 if ((size_t) cin.origination.x_offset != ~0UL)
cristy97450ff2010-12-29 17:29:17 +0000580 (void) FormatImageProperty(image,"dpx:origination.x_offset","%.20g",
cristye8c25f92010-06-03 00:53:06 +0000581 (double) cin.origination.x_offset);
cristy811f5172010-12-29 17:38:08 +0000582 cin.origination.y_offset=(ssize_t) ReadBlobLong(image);
cristy3ed852e2009-09-05 21:47:34 +0000583 offset+=4;
cristybb503372010-05-27 20:51:26 +0000584 if ((size_t) cin.origination.y_offset != ~0UL)
cristy97450ff2010-12-29 17:29:17 +0000585 (void) FormatImageProperty(image,"dpx:origination.y_offset","%.20g",
cristye8c25f92010-06-03 00:53:06 +0000586 (double) cin.origination.y_offset);
cristy3ed852e2009-09-05 21:47:34 +0000587 offset+=ReadBlob(image,sizeof(cin.origination.filename),(unsigned char *)
588 cin.origination.filename);
cristy97450ff2010-12-29 17:29:17 +0000589 (void) SetImageProperty(image,"dpx:origination.filename",
cristyd15e6592011-10-15 00:13:06 +0000590 cin.origination.filename,exception);
cristy3ed852e2009-09-05 21:47:34 +0000591 offset+=ReadBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
592 cin.origination.create_date);
cristy97450ff2010-12-29 17:29:17 +0000593 (void) SetImageProperty(image,"dpx:origination.create_date",
cristyd15e6592011-10-15 00:13:06 +0000594 cin.origination.create_date,exception);
cristy3ed852e2009-09-05 21:47:34 +0000595 offset+=ReadBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
596 cin.origination.create_time);
cristy97450ff2010-12-29 17:29:17 +0000597 (void) SetImageProperty(image,"dpx:origination.create_time",
cristyd15e6592011-10-15 00:13:06 +0000598 cin.origination.create_time,exception);
cristy3ed852e2009-09-05 21:47:34 +0000599 offset+=ReadBlob(image,sizeof(cin.origination.device),(unsigned char *)
600 cin.origination.device);
cristy97450ff2010-12-29 17:29:17 +0000601 (void) SetImageProperty(image,"dpx:origination.device",
cristyd15e6592011-10-15 00:13:06 +0000602 cin.origination.device,exception);
cristy3ed852e2009-09-05 21:47:34 +0000603 offset+=ReadBlob(image,sizeof(cin.origination.model),(unsigned char *)
604 cin.origination.model);
cristyd15e6592011-10-15 00:13:06 +0000605 (void) SetImageProperty(image,"dpx:origination.model",cin.origination.model,
606 exception);
cristy3ed852e2009-09-05 21:47:34 +0000607 offset+=ReadBlob(image,sizeof(cin.origination.serial),(unsigned char *)
608 cin.origination.serial);
cristy97450ff2010-12-29 17:29:17 +0000609 (void) SetImageProperty(image,"dpx:origination.serial",
cristyd15e6592011-10-15 00:13:06 +0000610 cin.origination.serial,exception);
cristy3ed852e2009-09-05 21:47:34 +0000611 cin.origination.x_pitch=ReadBlobFloat(image);
612 offset+=4;
613 cin.origination.y_pitch=ReadBlobFloat(image);
614 offset+=4;
615 cin.origination.gamma=ReadBlobFloat(image);
616 offset+=4;
617 if (IsFloatDefined(cin.origination.gamma) != MagickFalse)
618 image->gamma=cin.origination.gamma;
619 offset+=ReadBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
620 cin.origination.reserve);
621 if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
622 {
cristyf0605892011-09-06 14:56:46 +0000623 int
624 c;
625
cristy3ed852e2009-09-05 21:47:34 +0000626 /*
627 Image film information.
628 */
629 cin.film.id=ReadBlobByte(image);
630 offset++;
cristyf0605892011-09-06 14:56:46 +0000631 c=cin.film.id;
cristy94b11832011-09-08 19:46:03 +0000632 if (c != ~0)
cristy97450ff2010-12-29 17:29:17 +0000633 (void) FormatImageProperty(image,"dpx:film.id","%d",cin.film.id);
cristy3ed852e2009-09-05 21:47:34 +0000634 cin.film.type=ReadBlobByte(image);
635 offset++;
cristyf0605892011-09-06 14:56:46 +0000636 c=cin.film.type;
cristy94b11832011-09-08 19:46:03 +0000637 if (c != ~0)
cristy97450ff2010-12-29 17:29:17 +0000638 (void) FormatImageProperty(image,"dpx:film.type","%d",cin.film.type);
cristy3ed852e2009-09-05 21:47:34 +0000639 cin.film.offset=ReadBlobByte(image);
640 offset++;
cristyf0605892011-09-06 14:56:46 +0000641 c=cin.film.offset;
cristy94b11832011-09-08 19:46:03 +0000642 if (c != ~0)
cristy97450ff2010-12-29 17:29:17 +0000643 (void) FormatImageProperty(image,"dpx:film.offset","%d",
cristy3ed852e2009-09-05 21:47:34 +0000644 cin.film.offset);
645 cin.film.reserve1=ReadBlobByte(image);
646 offset++;
647 cin.film.prefix=ReadBlobLong(image);
648 offset+=4;
649 if (cin.film.prefix != ~0UL)
cristy97450ff2010-12-29 17:29:17 +0000650 (void) FormatImageProperty(image,"dpx:film.prefix","%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +0000651 cin.film.prefix);
652 cin.film.count=ReadBlobLong(image);
653 offset+=4;
654 offset+=ReadBlob(image,sizeof(cin.film.format),(unsigned char *)
655 cin.film.format);
cristyd15e6592011-10-15 00:13:06 +0000656 (void) SetImageProperty(image,"dpx:film.format",cin.film.format,
657 exception);
cristy3ed852e2009-09-05 21:47:34 +0000658 cin.film.frame_position=ReadBlobLong(image);
659 offset+=4;
660 if (cin.film.frame_position != ~0UL)
cristy97450ff2010-12-29 17:29:17 +0000661 (void) FormatImageProperty(image,"dpx:film.frame_position","%.20g",
cristye8c25f92010-06-03 00:53:06 +0000662 (double) cin.film.frame_position);
cristy3ed852e2009-09-05 21:47:34 +0000663 cin.film.frame_rate=ReadBlobFloat(image);
664 offset+=4;
665 if (IsFloatDefined(cin.film.frame_rate) != MagickFalse)
cristy97450ff2010-12-29 17:29:17 +0000666 (void) FormatImageProperty(image,"dpx:film.frame_rate","%g",
cristy3ed852e2009-09-05 21:47:34 +0000667 cin.film.frame_rate);
668 offset+=ReadBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
669 cin.film.frame_id);
cristyd15e6592011-10-15 00:13:06 +0000670 (void) SetImageProperty(image,"dpx:film.frame_id",cin.film.frame_id,
671 exception);
cristy3ed852e2009-09-05 21:47:34 +0000672 offset+=ReadBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
673 cin.film.slate_info);
cristyd15e6592011-10-15 00:13:06 +0000674 (void) SetImageProperty(image,"dpx:film.slate_info",cin.film.slate_info,
675 exception);
cristy3ed852e2009-09-05 21:47:34 +0000676 offset+=ReadBlob(image,sizeof(cin.film.reserve),(unsigned char *)
677 cin.film.reserve);
678 }
679 if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
680 {
681 StringInfo
682 *profile;
683
684 /*
685 User defined data.
686 */
cristy60395292011-09-01 13:25:56 +0000687 profile=BlobToStringInfo((const void *) NULL,cin.file.user_length);
688 if (profile == (StringInfo *) NULL)
689 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000690 offset+=ReadBlob(image,GetStringInfoLength(profile),
691 GetStringInfoDatum(profile));
cristyd15e6592011-10-15 00:13:06 +0000692 (void) SetImageProfile(image,"dpx:user.data",profile,exception);
cristy3ed852e2009-09-05 21:47:34 +0000693 profile=DestroyStringInfo(profile);
694 }
cristy811f5172010-12-29 17:38:08 +0000695 for ( ; offset < (MagickOffsetType) cin.file.image_offset; offset++)
cristy3ed852e2009-09-05 21:47:34 +0000696 (void) ReadBlobByte(image);
697 image->depth=cin.image.channel[0].bits_per_pixel;
698 image->columns=cin.image.channel[0].pixels_per_line;
699 image->rows=cin.image.channel[0].lines_per_image;
700 if (image_info->ping)
701 {
702 (void) CloseBlob(image);
703 return(image);
704 }
705 /*
706 Convert CIN raster image to pixel packets.
707 */
708 quantum_info=AcquireQuantumInfo(image_info,image);
709 if (quantum_info == (QuantumInfo *) NULL)
710 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
711 quantum_info->quantum=32;
712 quantum_info->pack=MagickFalse;
713 quantum_type=RGBQuantum;
714 pixels=GetQuantumPixels(quantum_info);
715 length=GetQuantumExtent(image,quantum_info,quantum_type);
716 length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
717 if (cin.image.number_channels == 1)
718 {
719 quantum_type=GrayQuantum;
720 length=GetBytesPerRow(image->columns,1,image->depth,MagickTrue);
721 }
cristybb503372010-05-27 20:51:26 +0000722 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000723 {
724 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000725 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000726 break;
727 count=ReadBlob(image,length,pixels);
728 if ((size_t) count != length)
729 break;
730 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
731 quantum_type,pixels,exception);
732 if (SyncAuthenticPixels(image,exception) == MagickFalse)
733 break;
734 if (image->previous == (Image *) NULL)
735 {
cristycee97112010-05-28 00:44:52 +0000736 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
cristy97450ff2010-12-29 17:29:17 +0000737 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000738 if (status == MagickFalse)
739 break;
740 }
741 }
742 SetQuantumImageType(image,quantum_type);
743 quantum_info=DestroyQuantumInfo(quantum_info);
744 if (EOFBlob(image) != MagickFalse)
745 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
746 image->filename);
cristye2c4f182012-05-12 14:11:53 +0000747 SetImageColorspace(image,LogColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000748 (void) CloseBlob(image);
749 return(GetFirstImageInList(image));
750}
751
752/*
753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754% %
755% %
756% %
757% R e g i s t e r C I N E O N I m a g e %
758% %
759% %
760% %
761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762%
763% RegisterCINImage() adds attributes for the CIN image format to the list of
764% of supported formats. The attributes include the image format tag, a method
765% to read and/or write the format, whether the format supports the saving of
766% more than one frame to the same file or blob, whether the format supports
767% native in-memory I/O, and a brief description of the format.
768%
769% The format of the RegisterCINImage method is:
770%
cristybb503372010-05-27 20:51:26 +0000771% size_t RegisterCINImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000772%
773*/
cristybb503372010-05-27 20:51:26 +0000774ModuleExport size_t RegisterCINImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000775{
776 MagickInfo
777 *entry;
778
779 entry=SetMagickInfo("CIN");
780 entry->decoder=(DecodeImageHandler *) ReadCINImage;
781 entry->encoder=(EncodeImageHandler *) WriteCINImage;
782 entry->magick=(IsImageFormatHandler *) IsCIN;
cristybc4eb112011-02-03 01:05:23 +0000783 entry->adjoin=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000784 entry->description=ConstantString("Cineon Image File");
785 entry->module=ConstantString("CIN");
786 (void) RegisterMagickInfo(entry);
787 return(MagickImageCoderSignature);
788}
789
790/*
791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792% %
793% %
794% %
795% U n r e g i s t e r C I N E O N I m a g e %
796% %
797% %
798% %
799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
800%
801% UnregisterCINImage() removes format registrations made by the CIN module
802% from the list of supported formats.
803%
804% The format of the UnregisterCINImage method is:
805%
806% UnregisterCINImage(void)
807%
808*/
809ModuleExport void UnregisterCINImage(void)
810{
811 (void) UnregisterMagickInfo("CINEON");
812}
813
814/*
815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
816% %
817% %
818% %
819% W r i t e C I N E O N I m a g e %
820% %
821% %
822% %
823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824%
825% WriteCINImage() writes an image in CIN encoded image format.
826%
827% The format of the WriteCINImage method is:
828%
cristy1e178e72011-08-28 19:44:34 +0000829% MagickBooleanType WriteCINImage(const ImageInfo *image_info,
830% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000831%
832% A description of each parameter follows.
833%
834% o image_info: the image info.
835%
836% o image: The image.
837%
cristy1e178e72011-08-28 19:44:34 +0000838% o exception: return any errors or warnings in this structure.
839%
cristy3ed852e2009-09-05 21:47:34 +0000840*/
841
842static inline const char *GetCINProperty(const ImageInfo *image_info,
cristyd15e6592011-10-15 00:13:06 +0000843 const Image *image,const char *property,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000844{
845 const char
846 *value;
847
848 value=GetImageOption(image_info,property);
849 if (value != (const char *) NULL)
850 return(value);
cristyd15e6592011-10-15 00:13:06 +0000851 return(GetImageProperty(image,property,exception));
cristy3ed852e2009-09-05 21:47:34 +0000852}
853
cristy1e178e72011-08-28 19:44:34 +0000854static MagickBooleanType WriteCINImage(const ImageInfo *image_info,Image *image,
855 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000856{
857 const char
858 *value;
859
860 CINInfo
861 cin;
862
863 const StringInfo
864 *profile;
865
cristy3ed852e2009-09-05 21:47:34 +0000866 MagickBooleanType
867 status;
868
869 MagickOffsetType
870 offset;
871
872 QuantumInfo
873 *quantum_info;
874
875 QuantumType
876 quantum_type;
877
cristy4c08aed2011-07-01 19:47:50 +0000878 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000879 *p;
880
cristybb503372010-05-27 20:51:26 +0000881 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000882 i;
883
884 size_t
885 length;
886
887 ssize_t
cristy4e82e512011-04-24 01:33:42 +0000888 count,
889 y;
cristy3ed852e2009-09-05 21:47:34 +0000890
891 struct tm
892 local_time;
893
894 time_t
895 seconds;
896
897 unsigned char
898 *pixels;
899
900 /*
901 Open output image file.
902 */
903 assert(image_info != (const ImageInfo *) NULL);
904 assert(image_info->signature == MagickSignature);
905 assert(image != (Image *) NULL);
906 assert(image->signature == MagickSignature);
907 if (image->debug != MagickFalse)
908 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy3a37efd2011-08-28 20:31:03 +0000909 assert(exception != (ExceptionInfo *) NULL);
910 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +0000911 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +0000912 if (status == MagickFalse)
913 return(status);
914 if (image->colorspace != LogColorspace)
cristye941a752011-10-15 01:52:48 +0000915 (void) TransformImageColorspace(image,LogColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000916 /*
917 Write image information.
918 */
919 (void) ResetMagickMemory(&cin,0,sizeof(cin));
920 offset=0;
921 cin.file.magic=0x802A5FD7UL;
cristyf6fe0a12010-05-30 00:44:47 +0000922 offset+=WriteBlobLong(image,(unsigned int) cin.file.magic);
cristy3ed852e2009-09-05 21:47:34 +0000923 cin.file.image_offset=0x800;
cristyf6fe0a12010-05-30 00:44:47 +0000924 offset+=WriteBlobLong(image,(unsigned int) cin.file.image_offset);
cristy3ed852e2009-09-05 21:47:34 +0000925 cin.file.generic_length=0x400;
cristyf6fe0a12010-05-30 00:44:47 +0000926 offset+=WriteBlobLong(image,(unsigned int) cin.file.generic_length);
cristy3ed852e2009-09-05 21:47:34 +0000927 cin.file.industry_length=0x400;
cristyf6fe0a12010-05-30 00:44:47 +0000928 offset+=WriteBlobLong(image,(unsigned int) cin.file.industry_length);
cristy3ed852e2009-09-05 21:47:34 +0000929 cin.file.user_length=0x00;
cristy97450ff2010-12-29 17:29:17 +0000930 profile=GetImageProfile(image,"dpx:user.data");
cristy3ed852e2009-09-05 21:47:34 +0000931 if (profile != (StringInfo *) NULL)
932 {
cristybb503372010-05-27 20:51:26 +0000933 cin.file.user_length+=(size_t) GetStringInfoLength(profile);
cristy3ed852e2009-09-05 21:47:34 +0000934 cin.file.user_length=(((cin.file.user_length+0x2000-1)/0x2000)*0x2000);
935 }
cristyf6fe0a12010-05-30 00:44:47 +0000936 offset+=WriteBlobLong(image,(unsigned int) cin.file.user_length);
cristy3ed852e2009-09-05 21:47:34 +0000937 cin.file.file_size=4*image->columns*image->rows+0x2000;
cristyf6fe0a12010-05-30 00:44:47 +0000938 offset+=WriteBlobLong(image,(unsigned int) cin.file.file_size);
cristy3ed852e2009-09-05 21:47:34 +0000939 (void) CopyMagickString(cin.file.version,"V4.5",sizeof(cin.file.version));
940 offset+=WriteBlob(image,sizeof(cin.file.version),(unsigned char *)
941 cin.file.version);
cristyd15e6592011-10-15 00:13:06 +0000942 value=GetCINProperty(image_info,image,"dpx:file.filename",exception);
cristy3ed852e2009-09-05 21:47:34 +0000943 if (value != (const char *) NULL)
944 (void) CopyMagickString(cin.file.filename,value,sizeof(cin.file.filename));
945 else
946 (void) CopyMagickString(cin.file.filename,image->filename,
947 sizeof(cin.file.filename));
948 offset+=WriteBlob(image,sizeof(cin.file.filename),(unsigned char *)
949 cin.file.filename);
950 seconds=time((time_t *) NULL);
951#if defined(MAGICKCORE_HAVE_LOCALTIME_R)
952 (void) localtime_r(&seconds,&local_time);
953#else
954 (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
955#endif
956 (void) strftime(cin.file.create_date,sizeof(cin.file.create_date),"%Y:%m:%d",
957 &local_time);
958 offset+=WriteBlob(image,sizeof(cin.file.create_date),(unsigned char *)
959 cin.file.create_date);
960 (void) strftime(cin.file.create_time,sizeof(cin.file.create_time),
961 "%H:%M:%S%Z",&local_time);
962 offset+=WriteBlob(image,sizeof(cin.file.create_time),(unsigned char *)
963 cin.file.create_time);
964 offset+=WriteBlob(image,sizeof(cin.file.reserve),(unsigned char *)
965 cin.file.reserve);
966 cin.image.orientation=0x00;
967 offset+=WriteBlobByte(image,cin.image.orientation);
968 cin.image.number_channels=3;
969 offset+=WriteBlobByte(image,cin.image.number_channels);
970 offset+=WriteBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
971 cin.image.reserve1);
972 for (i=0; i < 8; i++)
973 {
974 cin.image.channel[i].designator[0]=0; /* universal metric */
975 offset+=WriteBlobByte(image,cin.image.channel[0].designator[0]);
976 cin.image.channel[i].designator[1]=(unsigned char) (i > 3 ? 0 : i+1); /* channel color */;
977 offset+=WriteBlobByte(image,cin.image.channel[1].designator[0]);
978 cin.image.channel[i].bits_per_pixel=(unsigned char) image->depth;
979 offset+=WriteBlobByte(image,cin.image.channel[0].bits_per_pixel);
980 offset+=WriteBlobByte(image,cin.image.channel[0].reserve);
981 cin.image.channel[i].pixels_per_line=image->columns;
cristyf6fe0a12010-05-30 00:44:47 +0000982 offset+=WriteBlobLong(image,(unsigned int)
983 cin.image.channel[0].pixels_per_line);
cristy3ed852e2009-09-05 21:47:34 +0000984 cin.image.channel[i].lines_per_image=image->rows;
cristyf6fe0a12010-05-30 00:44:47 +0000985 offset+=WriteBlobLong(image,(unsigned int)
986 cin.image.channel[0].lines_per_image);
cristy3ed852e2009-09-05 21:47:34 +0000987 cin.image.channel[i].min_data=0;
988 offset+=WriteBlobFloat(image,cin.image.channel[0].min_data);
989 cin.image.channel[i].min_quantity=0.0;
990 offset+=WriteBlobFloat(image,cin.image.channel[0].min_quantity);
991 cin.image.channel[i].max_data=(float) ((MagickOffsetType)
992 GetQuantumRange(image->depth));
993 offset+=WriteBlobFloat(image,cin.image.channel[0].max_data);
994 cin.image.channel[i].max_quantity=2.048f;
995 offset+=WriteBlobFloat(image,cin.image.channel[0].max_quantity);
996 }
997 offset+=WriteBlobFloat(image,image->chromaticity.white_point.x);
998 offset+=WriteBlobFloat(image,image->chromaticity.white_point.y);
999 offset+=WriteBlobFloat(image,image->chromaticity.red_primary.x);
1000 offset+=WriteBlobFloat(image,image->chromaticity.red_primary.y);
1001 offset+=WriteBlobFloat(image,image->chromaticity.green_primary.x);
1002 offset+=WriteBlobFloat(image,image->chromaticity.green_primary.y);
1003 offset+=WriteBlobFloat(image,image->chromaticity.blue_primary.x);
1004 offset+=WriteBlobFloat(image,image->chromaticity.blue_primary.y);
cristyd15e6592011-10-15 00:13:06 +00001005 value=GetCINProperty(image_info,image,"dpx:image.label",exception);
cristy3ed852e2009-09-05 21:47:34 +00001006 if (value != (const char *) NULL)
1007 (void) CopyMagickString(cin.image.label,value,sizeof(cin.image.label));
1008 offset+=WriteBlob(image,sizeof(cin.image.label),(unsigned char *)
1009 cin.image.label);
1010 offset+=WriteBlob(image,sizeof(cin.image.reserve),(unsigned char *)
1011 cin.image.reserve);
1012 /*
1013 Write data format information.
1014 */
1015 cin.data_format.interleave=0; /* pixel interleave (rgbrgbr...) */
1016 offset+=WriteBlobByte(image,cin.data_format.interleave);
cristybb503372010-05-27 20:51:26 +00001017 cin.data_format.packing=5; /* packing ssize_tword (32bit) boundaries */
cristy3ed852e2009-09-05 21:47:34 +00001018 offset+=WriteBlobByte(image,cin.data_format.packing);
1019 cin.data_format.sign=0; /* unsigned data */
1020 offset+=WriteBlobByte(image,cin.data_format.sign);
1021 cin.data_format.sense=0; /* image sense: positive image */
1022 offset+=WriteBlobByte(image,cin.data_format.sense);
1023 cin.data_format.line_pad=0;
cristyf6fe0a12010-05-30 00:44:47 +00001024 offset+=WriteBlobLong(image,(unsigned int) cin.data_format.line_pad);
cristy3ed852e2009-09-05 21:47:34 +00001025 cin.data_format.channel_pad=0;
cristyf6fe0a12010-05-30 00:44:47 +00001026 offset+=WriteBlobLong(image,(unsigned int) cin.data_format.channel_pad);
cristy3ed852e2009-09-05 21:47:34 +00001027 offset+=WriteBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
1028 cin.data_format.reserve);
1029 /*
1030 Write origination information.
1031 */
1032 cin.origination.x_offset=0UL;
cristyd15e6592011-10-15 00:13:06 +00001033 value=GetCINProperty(image_info,image,"dpx:origination.x_offset",exception);
cristy3ed852e2009-09-05 21:47:34 +00001034 if (value != (const char *) NULL)
cristy811f5172010-12-29 17:38:08 +00001035 cin.origination.x_offset=(ssize_t) StringToLong(value);
cristyf9cca6a2010-06-04 23:49:28 +00001036 offset+=WriteBlobLong(image,(unsigned int) cin.origination.x_offset);
cristy3ed852e2009-09-05 21:47:34 +00001037 cin.origination.y_offset=0UL;
cristyd15e6592011-10-15 00:13:06 +00001038 value=GetCINProperty(image_info,image,"dpx:origination.y_offset",exception);
cristy3ed852e2009-09-05 21:47:34 +00001039 if (value != (const char *) NULL)
cristy811f5172010-12-29 17:38:08 +00001040 cin.origination.y_offset=(ssize_t) StringToLong(value);
cristyf9cca6a2010-06-04 23:49:28 +00001041 offset+=WriteBlobLong(image,(unsigned int) cin.origination.y_offset);
cristyd15e6592011-10-15 00:13:06 +00001042 value=GetCINProperty(image_info,image,"dpx:origination.filename",exception);
cristy3ed852e2009-09-05 21:47:34 +00001043 if (value != (const char *) NULL)
1044 (void) CopyMagickString(cin.origination.filename,value,
1045 sizeof(cin.origination.filename));
1046 else
1047 (void) CopyMagickString(cin.origination.filename,image->filename,
1048 sizeof(cin.origination.filename));
1049 offset+=WriteBlob(image,sizeof(cin.origination.filename),(unsigned char *)
1050 cin.origination.filename);
1051 seconds=time((time_t *) NULL);
1052 (void) strftime(cin.origination.create_date,
1053 sizeof(cin.origination.create_date),"%Y:%m:%d",&local_time);
1054 offset+=WriteBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
1055 cin.origination.create_date);
1056 (void) strftime(cin.origination.create_time,
1057 sizeof(cin.origination.create_time),"%H:%M:%S%Z",&local_time);
1058 offset+=WriteBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
1059 cin.origination.create_time);
cristyd15e6592011-10-15 00:13:06 +00001060 value=GetCINProperty(image_info,image,"dpx:origination.device",exception);
cristy3ed852e2009-09-05 21:47:34 +00001061 if (value != (const char *) NULL)
1062 (void) CopyMagickString(cin.origination.device,value,
1063 sizeof(cin.origination.device));
1064 offset+=WriteBlob(image,sizeof(cin.origination.device),(unsigned char *)
1065 cin.origination.device);
cristyd15e6592011-10-15 00:13:06 +00001066 value=GetCINProperty(image_info,image,"dpx:origination.model",exception);
cristy3ed852e2009-09-05 21:47:34 +00001067 if (value != (const char *) NULL)
1068 (void) CopyMagickString(cin.origination.model,value,
1069 sizeof(cin.origination.model));
1070 offset+=WriteBlob(image,sizeof(cin.origination.model),(unsigned char *)
1071 cin.origination.model);
cristyd15e6592011-10-15 00:13:06 +00001072 value=GetCINProperty(image_info,image,"dpx:origination.serial",exception);
cristy3ed852e2009-09-05 21:47:34 +00001073 if (value != (const char *) NULL)
1074 (void) CopyMagickString(cin.origination.serial,value,
1075 sizeof(cin.origination.serial));
1076 offset+=WriteBlob(image,sizeof(cin.origination.serial),(unsigned char *)
1077 cin.origination.serial);
1078 cin.origination.x_pitch=0.0f;
cristyd15e6592011-10-15 00:13:06 +00001079 value=GetCINProperty(image_info,image,"dpx:origination.x_pitch",exception);
cristy3ed852e2009-09-05 21:47:34 +00001080 if (value != (const char *) NULL)
cristydbdd0e32011-11-04 23:29:40 +00001081 cin.origination.x_pitch=StringToDouble(value,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001082 offset+=WriteBlobFloat(image,cin.origination.x_pitch);
1083 cin.origination.y_pitch=0.0f;
cristyd15e6592011-10-15 00:13:06 +00001084 value=GetCINProperty(image_info,image,"dpx:origination.y_pitch",exception);
cristy3ed852e2009-09-05 21:47:34 +00001085 if (value != (const char *) NULL)
cristydbdd0e32011-11-04 23:29:40 +00001086 cin.origination.y_pitch=StringToDouble(value,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001087 offset+=WriteBlobFloat(image,cin.origination.y_pitch);
1088 cin.origination.gamma=image->gamma;
1089 offset+=WriteBlobFloat(image,cin.origination.gamma);
1090 offset+=WriteBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
1091 cin.origination.reserve);
1092 /*
1093 Image film information.
1094 */
1095 cin.film.id=0;
cristyd15e6592011-10-15 00:13:06 +00001096 value=GetCINProperty(image_info,image,"dpx:film.id",exception);
cristy3ed852e2009-09-05 21:47:34 +00001097 if (value != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00001098 cin.film.id=(char) StringToLong(value);
cristy3ed852e2009-09-05 21:47:34 +00001099 offset+=WriteBlobByte(image,(unsigned char) cin.film.id);
1100 cin.film.type=0;
cristyd15e6592011-10-15 00:13:06 +00001101 value=GetCINProperty(image_info,image,"dpx:film.type",exception);
cristy3ed852e2009-09-05 21:47:34 +00001102 if (value != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00001103 cin.film.type=(char) StringToLong(value);
cristy3ed852e2009-09-05 21:47:34 +00001104 offset+=WriteBlobByte(image,(unsigned char) cin.film.type);
1105 cin.film.offset=0;
cristyd15e6592011-10-15 00:13:06 +00001106 value=GetCINProperty(image_info,image,"dpx:film.offset",exception);
cristy3ed852e2009-09-05 21:47:34 +00001107 if (value != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00001108 cin.film.offset=(char) StringToLong(value);
cristy3ed852e2009-09-05 21:47:34 +00001109 offset+=WriteBlobByte(image,(unsigned char) cin.film.offset);
1110 offset+=WriteBlobByte(image,(unsigned char) cin.film.reserve1);
1111 cin.film.prefix=0UL;
cristyd15e6592011-10-15 00:13:06 +00001112 value=GetCINProperty(image_info,image,"dpx:film.prefix",exception);
cristy3ed852e2009-09-05 21:47:34 +00001113 if (value != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00001114 cin.film.prefix=StringToUnsignedLong(value);
cristyf6fe0a12010-05-30 00:44:47 +00001115 offset+=WriteBlobLong(image,(unsigned int) cin.film.prefix);
cristy3ed852e2009-09-05 21:47:34 +00001116 cin.film.count=0UL;
cristyd15e6592011-10-15 00:13:06 +00001117 value=GetCINProperty(image_info,image,"dpx:film.count",exception);
cristy3ed852e2009-09-05 21:47:34 +00001118 if (value != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00001119 cin.film.count=StringToUnsignedLong(value);
cristyf6fe0a12010-05-30 00:44:47 +00001120 offset+=WriteBlobLong(image,(unsigned int) cin.film.count);
cristyd15e6592011-10-15 00:13:06 +00001121 value=GetCINProperty(image_info,image,"dpx:film.format",exception);
cristy3ed852e2009-09-05 21:47:34 +00001122 if (value != (const char *) NULL)
1123 (void) CopyMagickString(cin.film.format,value,sizeof(cin.film.format));
1124 offset+=WriteBlob(image,sizeof(cin.film.format),(unsigned char *)
1125 cin.film.format);
1126 cin.film.frame_position=0UL;
cristyd15e6592011-10-15 00:13:06 +00001127 value=GetCINProperty(image_info,image,"dpx:film.frame_position",exception);
cristy3ed852e2009-09-05 21:47:34 +00001128 if (value != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00001129 cin.film.frame_position=StringToUnsignedLong(value);
cristyf6fe0a12010-05-30 00:44:47 +00001130 offset+=WriteBlobLong(image,(unsigned int) cin.film.frame_position);
cristy3ed852e2009-09-05 21:47:34 +00001131 cin.film.frame_rate=0.0f;
cristyd15e6592011-10-15 00:13:06 +00001132 value=GetCINProperty(image_info,image,"dpx:film.frame_rate",exception);
cristy3ed852e2009-09-05 21:47:34 +00001133 if (value != (const char *) NULL)
cristydbdd0e32011-11-04 23:29:40 +00001134 cin.film.frame_rate=StringToDouble(value,(char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001135 offset+=WriteBlobFloat(image,cin.film.frame_rate);
cristyd15e6592011-10-15 00:13:06 +00001136 value=GetCINProperty(image_info,image,"dpx:film.frame_id",exception);
cristy3ed852e2009-09-05 21:47:34 +00001137 if (value != (const char *) NULL)
1138 (void) CopyMagickString(cin.film.frame_id,value,sizeof(cin.film.frame_id));
1139 offset+=WriteBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
1140 cin.film.frame_id);
cristyd15e6592011-10-15 00:13:06 +00001141 value=GetCINProperty(image_info,image,"dpx:film.slate_info",exception);
cristy3ed852e2009-09-05 21:47:34 +00001142 if (value != (const char *) NULL)
1143 (void) CopyMagickString(cin.film.slate_info,value,
1144 sizeof(cin.film.slate_info));
1145 offset+=WriteBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
1146 cin.film.slate_info);
1147 offset+=WriteBlob(image,sizeof(cin.film.reserve),(unsigned char *)
1148 cin.film.reserve);
1149 if (profile != (StringInfo *) NULL)
1150 offset+=WriteBlob(image,GetStringInfoLength(profile),
1151 GetStringInfoDatum(profile));
1152 while (offset < (MagickOffsetType) cin.file.image_offset)
1153 offset+=WriteBlobByte(image,0x00);
1154 /*
1155 Convert pixel packets to CIN raster image.
1156 */
1157 quantum_info=AcquireQuantumInfo(image_info,image);
1158 if (quantum_info == (QuantumInfo *) NULL)
1159 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1160 quantum_info->quantum=32;
1161 quantum_info->pack=MagickFalse;
1162 quantum_type=RGBQuantum;
1163 pixels=GetQuantumPixels(quantum_info);
1164 length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
1165 if (0)
1166 {
1167 quantum_type=GrayQuantum;
cristybccc4f42011-11-24 17:57:52 +00001168 length=GetBytesPerRow(image->columns,1,image->depth,MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +00001169 }
cristybb503372010-05-27 20:51:26 +00001170 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001171 {
cristy1e178e72011-08-28 19:44:34 +00001172 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00001173 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001174 break;
cristy4c08aed2011-07-01 19:47:50 +00001175 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001176 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001177 count=WriteBlob(image,length,pixels);
1178 if (count != (ssize_t) length)
1179 break;
cristycee97112010-05-28 00:44:52 +00001180 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
cristy97450ff2010-12-29 17:29:17 +00001181 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001182 if (status == MagickFalse)
1183 break;
1184 }
1185 quantum_info=DestroyQuantumInfo(quantum_info);
1186 (void) CloseBlob(image);
1187 return(status);
1188}