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