/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 | } |