/src/imagemagick/coders/dpx.c
Line | Count | Source |
1 | | /* |
2 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
3 | | % % |
4 | | % % |
5 | | % % |
6 | | % DDDD PPPP X X % |
7 | | % D D P P X X % |
8 | | % D D PPPP XXX % |
9 | | % D D P X X % |
10 | | % DDDD P X X % |
11 | | % % |
12 | | % % |
13 | | % Read/Write SMTPE DPX Image Format % |
14 | | % % |
15 | | % Software Design % |
16 | | % Cristy % |
17 | | % March 2001 % |
18 | | % % |
19 | | % % |
20 | | % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization % |
21 | | % dedicated to making software imaging solutions freely available. % |
22 | | % % |
23 | | % You may not use this file except in compliance with the License. You may % |
24 | | % obtain a copy of the License at % |
25 | | % % |
26 | | % https://imagemagick.org/license/ % |
27 | | % % |
28 | | % Unless required by applicable law or agreed to in writing, software % |
29 | | % distributed under the License is distributed on an "AS IS" BASIS, % |
30 | | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
31 | | % See the License for the specific language governing permissions and % |
32 | | % limitations under the License. % |
33 | | % % |
34 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
35 | | % |
36 | | % |
37 | | */ |
38 | | |
39 | | /* |
40 | | Include declarations. |
41 | | */ |
42 | | #include "MagickCore/studio.h" |
43 | | #include "MagickCore/attribute.h" |
44 | | #include "MagickCore/artifact.h" |
45 | | #include "MagickCore/blob.h" |
46 | | #include "MagickCore/blob-private.h" |
47 | | #include "MagickCore/cache.h" |
48 | | #include "MagickCore/colorspace.h" |
49 | | #include "MagickCore/colorspace-private.h" |
50 | | #include "MagickCore/exception.h" |
51 | | #include "MagickCore/exception-private.h" |
52 | | #include "MagickCore/geometry.h" |
53 | | #include "MagickCore/image.h" |
54 | | #include "MagickCore/image-private.h" |
55 | | #include "MagickCore/list.h" |
56 | | #include "MagickCore/magick.h" |
57 | | #include "MagickCore/memory_.h" |
58 | | #include "MagickCore/module.h" |
59 | | #include "MagickCore/monitor.h" |
60 | | #include "MagickCore/monitor-private.h" |
61 | | #include "MagickCore/option.h" |
62 | | #include "MagickCore/pixel-accessor.h" |
63 | | #include "MagickCore/profile-private.h" |
64 | | #include "MagickCore/property.h" |
65 | | #include "MagickCore/quantum-private.h" |
66 | | #include "MagickCore/static.h" |
67 | | #include "MagickCore/string_.h" |
68 | | #include "MagickCore/string-private.h" |
69 | | #include "MagickCore/timer-private.h" |
70 | | #include "coders/coders-private.h" |
71 | | |
72 | | /* |
73 | | Define declaration. |
74 | | */ |
75 | 2.71k | #define MaxNumberImageElements 8 |
76 | | |
77 | | /* |
78 | | Typedef declaration. |
79 | | */ |
80 | | typedef enum |
81 | | { |
82 | | UserDefinedColorimetric = 0, |
83 | | PrintingDensityColorimetric = 1, |
84 | | LinearColorimetric = 2, |
85 | | LogarithmicColorimetric = 3, |
86 | | UnspecifiedVideoColorimetric = 4, |
87 | | SMTPE_274MColorimetric = 5, |
88 | | ITU_R709Colorimetric = 6, |
89 | | ITU_R601_625LColorimetric = 7, |
90 | | ITU_R601_525LColorimetric = 8, |
91 | | NTSCCompositeVideoColorimetric = 9, |
92 | | PALCompositeVideoColorimetric = 10, |
93 | | ZDepthLinearColorimetric = 11, |
94 | | DepthHomogeneousColorimetric = 12 |
95 | | } DPXColorimetric; |
96 | | |
97 | | typedef enum |
98 | | { |
99 | | UndefinedComponentType = 0, |
100 | | RedComponentType = 1, |
101 | | GreenComponentType = 2, |
102 | | BlueComponentType = 3, |
103 | | AlphaComponentType = 4, |
104 | | LumaComponentType = 6, |
105 | | ColorDifferenceCbCrComponentType = 7, |
106 | | DepthComponentType = 8, |
107 | | CompositeVideoComponentType = 9, |
108 | | RGBComponentType = 50, |
109 | | RGBAComponentType = 51, |
110 | | ABGRComponentType = 52, |
111 | | CbYCrY422ComponentType = 100, |
112 | | CbYACrYA4224ComponentType = 101, |
113 | | CbYCr444ComponentType = 102, |
114 | | CbYCrA4444ComponentType = 103, |
115 | | UserDef2ElementComponentType = 150, |
116 | | UserDef3ElementComponentType = 151, |
117 | | UserDef4ElementComponentType = 152, |
118 | | UserDef5ElementComponentType = 153, |
119 | | UserDef6ElementComponentType = 154, |
120 | | UserDef7ElementComponentType = 155, |
121 | | UserDef8ElementComponentType = 156 |
122 | | } DPXComponentType; |
123 | | |
124 | | typedef enum |
125 | | { |
126 | | TransferCharacteristicUserDefined = 0, |
127 | | TransferCharacteristicPrintingDensity = 1, |
128 | | TransferCharacteristicLinear = 2, |
129 | | TransferCharacteristicLogarithmic = 3, |
130 | | TransferCharacteristicUnspecifiedVideo = 4, |
131 | | TransferCharacteristicSMTPE274M = 5, /* 1920x1080 TV */ |
132 | | TransferCharacteristicITU_R709 = 6, /* ITU R709 */ |
133 | | TransferCharacteristicITU_R601_625L = 7, /* 625 Line */ |
134 | | TransferCharacteristicITU_R601_525L = 8, /* 525 Line */ |
135 | | TransferCharacteristicNTSCCompositeVideo = 9, |
136 | | TransferCharacteristicPALCompositeVideo = 10, |
137 | | TransferCharacteristicZDepthLinear = 11, |
138 | | TransferCharacteristicZDepthHomogeneous = 12 |
139 | | } DPXTransferCharacteristic; |
140 | | |
141 | | typedef struct _DPXFileInfo |
142 | | { |
143 | | unsigned int |
144 | | magic, |
145 | | image_offset; |
146 | | |
147 | | char |
148 | | version[8]; |
149 | | |
150 | | unsigned int |
151 | | file_size, |
152 | | ditto_key, |
153 | | generic_size, |
154 | | industry_size, |
155 | | user_size; |
156 | | |
157 | | char |
158 | | filename[100], |
159 | | timestamp[24], |
160 | | creator[100], |
161 | | project[200], |
162 | | copyright[200]; |
163 | | |
164 | | unsigned int |
165 | | encrypt_key; |
166 | | |
167 | | char |
168 | | reserve[104]; |
169 | | } DPXFileInfo; |
170 | | |
171 | | typedef struct _DPXFilmInfo |
172 | | { |
173 | | char |
174 | | id[2], |
175 | | type[2], |
176 | | offset[2], |
177 | | prefix[6], |
178 | | count[4], |
179 | | format[32]; |
180 | | |
181 | | unsigned int |
182 | | frame_position, |
183 | | sequence_extent, |
184 | | held_count; |
185 | | |
186 | | float |
187 | | frame_rate, |
188 | | shutter_angle; |
189 | | |
190 | | char |
191 | | frame_id[32], |
192 | | slate[100], |
193 | | reserve[56]; |
194 | | } DPXFilmInfo; |
195 | | |
196 | | typedef struct _DPXImageElement |
197 | | { |
198 | | unsigned int |
199 | | data_sign, |
200 | | low_data; |
201 | | |
202 | | float |
203 | | low_quantity; |
204 | | |
205 | | unsigned int |
206 | | high_data; |
207 | | |
208 | | float |
209 | | high_quantity; |
210 | | |
211 | | unsigned char |
212 | | descriptor, |
213 | | transfer_characteristic, |
214 | | colorimetric, |
215 | | bit_size; |
216 | | |
217 | | unsigned short |
218 | | packing, |
219 | | encoding; |
220 | | |
221 | | unsigned int |
222 | | data_offset, |
223 | | end_of_line_padding, |
224 | | end_of_image_padding; |
225 | | |
226 | | unsigned char |
227 | | description[32]; |
228 | | } DPXImageElement; |
229 | | |
230 | | typedef struct _DPXImageInfo |
231 | | { |
232 | | unsigned short |
233 | | orientation, |
234 | | number_elements; |
235 | | |
236 | | unsigned int |
237 | | pixels_per_line, |
238 | | lines_per_element; |
239 | | |
240 | | DPXImageElement |
241 | | image_element[MaxNumberImageElements]; |
242 | | |
243 | | unsigned char |
244 | | reserve[52]; |
245 | | } DPXImageInfo; |
246 | | |
247 | | typedef struct _DPXOrientationInfo |
248 | | { |
249 | | unsigned int |
250 | | x_offset, |
251 | | y_offset; |
252 | | |
253 | | float |
254 | | x_center, |
255 | | y_center; |
256 | | |
257 | | unsigned int |
258 | | x_size, |
259 | | y_size; |
260 | | |
261 | | char |
262 | | filename[100], |
263 | | timestamp[24], |
264 | | device[32], |
265 | | serial[32]; |
266 | | |
267 | | unsigned short |
268 | | border[4]; |
269 | | |
270 | | unsigned int |
271 | | aspect_ratio[2]; |
272 | | |
273 | | unsigned char |
274 | | reserve[28]; |
275 | | } DPXOrientationInfo; |
276 | | |
277 | | typedef struct _DPXTelevisionInfo |
278 | | { |
279 | | unsigned int |
280 | | time_code, |
281 | | user_bits; |
282 | | |
283 | | unsigned char |
284 | | interlace, |
285 | | field_number, |
286 | | video_signal, |
287 | | padding; |
288 | | |
289 | | float |
290 | | horizontal_sample_rate, |
291 | | vertical_sample_rate, |
292 | | frame_rate, |
293 | | time_offset, |
294 | | gamma, |
295 | | black_level, |
296 | | black_gain, |
297 | | break_point, |
298 | | white_level, |
299 | | integration_times; |
300 | | |
301 | | char |
302 | | reserve[76]; |
303 | | } DPXTelevisionInfo; |
304 | | |
305 | | typedef struct _DPXUserInfo |
306 | | { |
307 | | char |
308 | | id[32]; |
309 | | } DPXUserInfo; |
310 | | |
311 | | typedef struct DPXInfo |
312 | | { |
313 | | DPXFileInfo |
314 | | file; |
315 | | |
316 | | DPXImageInfo |
317 | | image; |
318 | | |
319 | | DPXOrientationInfo |
320 | | orientation; |
321 | | |
322 | | DPXFilmInfo |
323 | | film; |
324 | | |
325 | | DPXTelevisionInfo |
326 | | television; |
327 | | |
328 | | DPXUserInfo |
329 | | user; |
330 | | } DPXInfo; |
331 | | |
332 | | /* |
333 | | Forward declarations. |
334 | | */ |
335 | | static MagickBooleanType |
336 | | WriteDPXImage(const ImageInfo *,Image *,ExceptionInfo *); |
337 | | |
338 | | /* |
339 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
340 | | % % |
341 | | % % |
342 | | % % |
343 | | % I s D P X % |
344 | | % % |
345 | | % % |
346 | | % % |
347 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
348 | | % |
349 | | % IsDPX() returns MagickTrue if the image format type, identified by the |
350 | | % magick string, is DPX. |
351 | | % |
352 | | % The format of the IsDPX method is: |
353 | | % |
354 | | % MagickBooleanType IsDPX(const unsigned char *magick,const size_t extent) |
355 | | % |
356 | | % A description of each parameter follows: |
357 | | % |
358 | | % o magick: compare image format pattern against these bytes. |
359 | | % |
360 | | % o extent: Specifies the extent of the magick string. |
361 | | % |
362 | | */ |
363 | | static MagickBooleanType IsDPX(const unsigned char *magick,const size_t extent) |
364 | 0 | { |
365 | 0 | if (extent < 4) |
366 | 0 | return(MagickFalse); |
367 | 0 | if (memcmp(magick,"SDPX",4) == 0) |
368 | 0 | return(MagickTrue); |
369 | 0 | if (memcmp(magick,"XPDS",4) == 0) |
370 | 0 | return(MagickTrue); |
371 | 0 | return(MagickFalse); |
372 | 0 | } |
373 | | |
374 | | /* |
375 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
376 | | % % |
377 | | % % |
378 | | % % |
379 | | % R e a d D P X I m a g e % |
380 | | % % |
381 | | % % |
382 | | % % |
383 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
384 | | % |
385 | | % ReadDPXImage() reads an DPX X image file and returns it. It |
386 | | % allocates the memory necessary for the new Image structure and returns a |
387 | | % pointer to the new image. |
388 | | % |
389 | | % The format of the ReadDPXImage method is: |
390 | | % |
391 | | % Image *ReadDPXImage(const ImageInfo *image_info,ExceptionInfo *exception) |
392 | | % |
393 | | % A description of each parameter follows: |
394 | | % |
395 | | % o image_info: the image info. |
396 | | % |
397 | | % o exception: return any errors or warnings in this structure. |
398 | | % |
399 | | */ |
400 | | |
401 | | static size_t GetBytesPerRow(const size_t columns, |
402 | | const size_t samples_per_pixel,const size_t bits_per_pixel, |
403 | | const MagickBooleanType pad) |
404 | 7.51k | { |
405 | 7.51k | size_t |
406 | 7.51k | bytes_per_row; |
407 | | |
408 | 7.51k | switch (bits_per_pixel) |
409 | 7.51k | { |
410 | 972 | case 1: |
411 | 972 | { |
412 | 972 | bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ |
413 | 972 | 32); |
414 | 972 | break; |
415 | 0 | } |
416 | 449 | case 8: |
417 | 2.78k | default: |
418 | 2.78k | { |
419 | 2.78k | bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ |
420 | 2.78k | 32); |
421 | 2.78k | break; |
422 | 449 | } |
423 | 1.26k | case 10: |
424 | 1.26k | { |
425 | 1.26k | if (pad == MagickFalse) |
426 | 393 | { |
427 | 393 | bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+ |
428 | 393 | 31)/32); |
429 | 393 | break; |
430 | 393 | } |
431 | 870 | bytes_per_row=4*(((size_t) (32*((samples_per_pixel*columns+2)/3))+31)/32); |
432 | 870 | break; |
433 | 1.26k | } |
434 | 1.23k | case 12: |
435 | 1.23k | { |
436 | 1.23k | if (pad == MagickFalse) |
437 | 452 | { |
438 | 452 | bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+ |
439 | 452 | 31)/32); |
440 | 452 | break; |
441 | 452 | } |
442 | 778 | bytes_per_row=2*(((size_t) (16*samples_per_pixel*columns)+15)/16); |
443 | 778 | break; |
444 | 1.23k | } |
445 | 708 | case 16: |
446 | 708 | { |
447 | 708 | if (pad == MagickFalse) |
448 | 221 | { |
449 | 221 | bytes_per_row=2*(((size_t) samples_per_pixel*columns*bits_per_pixel+ |
450 | 221 | 15)/16); |
451 | 221 | break; |
452 | 221 | } |
453 | 487 | bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ |
454 | 487 | 32); |
455 | 487 | break; |
456 | 708 | } |
457 | 556 | case 32: |
458 | 556 | { |
459 | 556 | bytes_per_row=4*(((size_t) samples_per_pixel*columns*bits_per_pixel+31)/ |
460 | 556 | 32); |
461 | 556 | break; |
462 | 708 | } |
463 | 0 | case 64: |
464 | 0 | { |
465 | 0 | bytes_per_row=8*(((size_t) samples_per_pixel*columns*bits_per_pixel+63)/ |
466 | 0 | 64); |
467 | 0 | break; |
468 | 708 | } |
469 | 7.51k | } |
470 | 7.51k | return(bytes_per_row); |
471 | 7.51k | } |
472 | | |
473 | | static const char *GetImageTransferCharacteristic( |
474 | | const DPXTransferCharacteristic characteristic) |
475 | 21.6k | { |
476 | 21.6k | const char |
477 | 21.6k | *transfer; |
478 | | |
479 | | /* |
480 | | Get the element transfer characteristic. |
481 | | */ |
482 | 21.6k | switch(characteristic) |
483 | 21.6k | { |
484 | 5.61k | case TransferCharacteristicUserDefined: |
485 | 5.61k | { |
486 | 5.61k | transfer="UserDefined"; |
487 | 5.61k | break; |
488 | 0 | } |
489 | 1.06k | case TransferCharacteristicPrintingDensity: |
490 | 1.06k | { |
491 | 1.06k | transfer="PrintingDensity"; |
492 | 1.06k | break; |
493 | 0 | } |
494 | 140 | case TransferCharacteristicLinear: |
495 | 140 | { |
496 | 140 | transfer="Linear"; |
497 | 140 | break; |
498 | 0 | } |
499 | 294 | case TransferCharacteristicLogarithmic: |
500 | 294 | { |
501 | 294 | transfer="Logarithmic"; |
502 | 294 | break; |
503 | 0 | } |
504 | 232 | case TransferCharacteristicUnspecifiedVideo: |
505 | 232 | { |
506 | 232 | transfer="UnspecifiedVideo"; |
507 | 232 | break; |
508 | 0 | } |
509 | 247 | case TransferCharacteristicSMTPE274M: |
510 | 247 | { |
511 | 247 | transfer="SMTPE274M"; |
512 | 247 | break; |
513 | 0 | } |
514 | 90 | case TransferCharacteristicITU_R709: |
515 | 90 | { |
516 | 90 | transfer="ITU-R709"; |
517 | 90 | break; |
518 | 0 | } |
519 | 56 | case TransferCharacteristicITU_R601_625L: |
520 | 56 | { |
521 | 56 | transfer="ITU-R601-625L"; |
522 | 56 | break; |
523 | 0 | } |
524 | 142 | case TransferCharacteristicITU_R601_525L: |
525 | 142 | { |
526 | 142 | transfer="ITU-R601-525L"; |
527 | 142 | break; |
528 | 0 | } |
529 | 69 | case TransferCharacteristicNTSCCompositeVideo: |
530 | 69 | { |
531 | 69 | transfer="NTSCCompositeVideo"; |
532 | 69 | break; |
533 | 0 | } |
534 | 158 | case TransferCharacteristicPALCompositeVideo: |
535 | 158 | { |
536 | 158 | transfer="PALCompositeVideo"; |
537 | 158 | break; |
538 | 0 | } |
539 | 16 | case TransferCharacteristicZDepthLinear: |
540 | 16 | { |
541 | 16 | transfer="ZDepthLinear"; |
542 | 16 | break; |
543 | 0 | } |
544 | 70 | case TransferCharacteristicZDepthHomogeneous: |
545 | 70 | { |
546 | 70 | transfer="ZDepthHomogeneous"; |
547 | 70 | break; |
548 | 0 | } |
549 | 13.4k | default: |
550 | 13.4k | transfer="Reserved"; |
551 | 21.6k | } |
552 | 21.6k | return(transfer); |
553 | 21.6k | } |
554 | | |
555 | | static inline MagickBooleanType IsFloatDefined(const float value) |
556 | 19.1k | { |
557 | 19.1k | union |
558 | 19.1k | { |
559 | 19.1k | unsigned int |
560 | 19.1k | unsigned_value; |
561 | | |
562 | 19.1k | float |
563 | 19.1k | float_value; |
564 | 19.1k | } quantum; |
565 | | |
566 | 19.1k | quantum.unsigned_value=(~0U); |
567 | 19.1k | quantum.float_value=(float) value; |
568 | 19.1k | if (quantum.unsigned_value == ~0U) |
569 | 730 | return(MagickFalse); |
570 | 18.3k | return(MagickTrue); |
571 | 19.1k | } |
572 | | |
573 | | static void SetPrimaryChromaticity(const DPXColorimetric colorimetric, |
574 | | ChromaticityInfo *chromaticity_info) |
575 | 6.49k | { |
576 | 6.49k | switch(colorimetric) |
577 | 6.49k | { |
578 | 27 | case SMTPE_274MColorimetric: |
579 | 71 | case ITU_R709Colorimetric: |
580 | 71 | { |
581 | 71 | chromaticity_info->red_primary.x=0.640; |
582 | 71 | chromaticity_info->red_primary.y=0.330; |
583 | 71 | chromaticity_info->red_primary.z=0.030; |
584 | 71 | chromaticity_info->green_primary.x=0.300; |
585 | 71 | chromaticity_info->green_primary.y=0.600; |
586 | 71 | chromaticity_info->green_primary.z=0.100; |
587 | 71 | chromaticity_info->blue_primary.x=0.150; |
588 | 71 | chromaticity_info->blue_primary.y=0.060; |
589 | 71 | chromaticity_info->blue_primary.z=0.790; |
590 | 71 | chromaticity_info->white_point.x=0.3127; |
591 | 71 | chromaticity_info->white_point.y=0.3290; |
592 | 71 | chromaticity_info->white_point.z=0.3582; |
593 | 71 | break; |
594 | 27 | } |
595 | 6 | case NTSCCompositeVideoColorimetric: |
596 | 6 | { |
597 | 6 | chromaticity_info->red_primary.x=0.67; |
598 | 6 | chromaticity_info->red_primary.y=0.33; |
599 | 6 | chromaticity_info->red_primary.z=0.00; |
600 | 6 | chromaticity_info->green_primary.x=0.21; |
601 | 6 | chromaticity_info->green_primary.y=0.71; |
602 | 6 | chromaticity_info->green_primary.z=0.08; |
603 | 6 | chromaticity_info->blue_primary.x=0.14; |
604 | 6 | chromaticity_info->blue_primary.y=0.08; |
605 | 6 | chromaticity_info->blue_primary.z=0.78; |
606 | 6 | chromaticity_info->white_point.x=0.310; |
607 | 6 | chromaticity_info->white_point.y=0.316; |
608 | 6 | chromaticity_info->white_point.z=0.374; |
609 | 6 | break; |
610 | 27 | } |
611 | 40 | case PALCompositeVideoColorimetric: |
612 | 40 | { |
613 | 40 | chromaticity_info->red_primary.x=0.640; |
614 | 40 | chromaticity_info->red_primary.y=0.330; |
615 | 40 | chromaticity_info->red_primary.z=0.030; |
616 | 40 | chromaticity_info->green_primary.x=0.290; |
617 | 40 | chromaticity_info->green_primary.y=0.600; |
618 | 40 | chromaticity_info->green_primary.z=0.110; |
619 | 40 | chromaticity_info->blue_primary.x=0.150; |
620 | 40 | chromaticity_info->blue_primary.y=0.060; |
621 | 40 | chromaticity_info->blue_primary.z=0.790; |
622 | 40 | chromaticity_info->white_point.x=0.3127; |
623 | 40 | chromaticity_info->white_point.y=0.3290; |
624 | 40 | chromaticity_info->white_point.z=0.3582; |
625 | 40 | break; |
626 | 27 | } |
627 | 6.37k | default: |
628 | 6.37k | break; |
629 | 6.49k | } |
630 | 6.49k | } |
631 | | |
632 | | static void TimeCodeToString(const size_t timestamp,char *code) |
633 | 2.69k | { |
634 | 37.6k | #define TimeFields 7 |
635 | | |
636 | 2.69k | unsigned int |
637 | 2.69k | shift; |
638 | | |
639 | 2.69k | ssize_t |
640 | 2.69k | i; |
641 | | |
642 | 2.69k | *code='\0'; |
643 | 2.69k | shift=4*TimeFields; |
644 | 24.2k | for (i=0; i <= TimeFields; i++) |
645 | 21.5k | { |
646 | 21.5k | (void) FormatLocaleString(code,MagickPathExtent-strlen(code),"%x", |
647 | 21.5k | (unsigned int) ((timestamp >> shift) & 0x0fU)); |
648 | 21.5k | code++; |
649 | 21.5k | if (((i % 2) != 0) && (i < TimeFields)) |
650 | 8.07k | *code++=':'; |
651 | 21.5k | shift-=4; |
652 | 21.5k | *code='\0'; |
653 | 21.5k | } |
654 | 2.69k | } |
655 | | |
656 | | static Image *ReadDPXImage(const ImageInfo *image_info,ExceptionInfo *exception) |
657 | 2.98k | { |
658 | 2.98k | char |
659 | 2.98k | magick[4], |
660 | 2.98k | value[MagickPathExtent]; |
661 | | |
662 | 2.98k | DPXInfo |
663 | 2.98k | dpx; |
664 | | |
665 | 2.98k | Image |
666 | 2.98k | *image; |
667 | | |
668 | 2.98k | MagickBooleanType |
669 | 2.98k | status; |
670 | | |
671 | 2.98k | MagickOffsetType |
672 | 2.98k | offset; |
673 | | |
674 | 2.98k | QuantumInfo |
675 | 2.98k | *quantum_info; |
676 | | |
677 | 2.98k | QuantumType |
678 | 2.98k | quantum_type; |
679 | | |
680 | 2.98k | ssize_t |
681 | 2.98k | i; |
682 | | |
683 | 2.98k | size_t |
684 | 2.98k | extent, |
685 | 2.98k | samples_per_pixel; |
686 | | |
687 | 2.98k | ssize_t |
688 | 2.98k | count, |
689 | 2.98k | n, |
690 | 2.98k | row, |
691 | 2.98k | y; |
692 | | |
693 | 2.98k | unsigned char |
694 | 2.98k | component_type; |
695 | | |
696 | | /* |
697 | | Open image file. |
698 | | */ |
699 | 2.98k | assert(image_info != (const ImageInfo *) NULL); |
700 | 2.98k | assert(image_info->signature == MagickCoreSignature); |
701 | 2.98k | assert(exception != (ExceptionInfo *) NULL); |
702 | 2.98k | assert(exception->signature == MagickCoreSignature); |
703 | 2.98k | if (IsEventLogging() != MagickFalse) |
704 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
705 | 0 | image_info->filename); |
706 | 2.98k | image=AcquireImage(image_info,exception); |
707 | 2.98k | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
708 | 2.98k | if (status == MagickFalse) |
709 | 0 | { |
710 | 0 | image=DestroyImageList(image); |
711 | 0 | return((Image *) NULL); |
712 | 0 | } |
713 | | /* |
714 | | Read DPX file header. |
715 | | */ |
716 | 2.98k | offset=0; |
717 | 2.98k | count=ReadBlob(image,4,(unsigned char *) magick); |
718 | 2.98k | offset+=count; |
719 | 2.98k | if ((count != 4) || ((LocaleNCompare(magick,"SDPX",4) != 0) && |
720 | 1.82k | (LocaleNCompare((char *) magick,"XPDS",4) != 0))) |
721 | 2.94k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
722 | 2.94k | image->endian=LSBEndian; |
723 | 2.94k | if (LocaleNCompare(magick,"SDPX",4) == 0) |
724 | 1.15k | image->endian=MSBEndian; |
725 | 2.94k | (void) memset(&dpx,0,sizeof(dpx)); |
726 | 2.94k | dpx.file.image_offset=ReadBlobLong(image); |
727 | 2.94k | offset+=4; |
728 | 2.94k | offset+=ReadBlob(image,sizeof(dpx.file.version),(unsigned char *) |
729 | 2.94k | dpx.file.version); |
730 | 2.94k | (void) FormatImageProperty(image,"dpx:file.version","%.8s",dpx.file.version); |
731 | 2.94k | dpx.file.file_size=ReadBlobLong(image); |
732 | 2.94k | offset+=4; |
733 | 2.94k | dpx.file.ditto_key=ReadBlobLong(image); |
734 | 2.94k | offset+=4; |
735 | 2.94k | if (dpx.file.ditto_key != ~0U) |
736 | 2.67k | (void) FormatImageProperty(image,"dpx:file.ditto.key","%u", |
737 | 2.67k | dpx.file.ditto_key); |
738 | 2.94k | dpx.file.generic_size=ReadBlobLong(image); |
739 | 2.94k | offset+=4; |
740 | 2.94k | dpx.file.industry_size=ReadBlobLong(image); |
741 | 2.94k | offset+=4; |
742 | 2.94k | dpx.file.user_size=ReadBlobLong(image); |
743 | 2.94k | offset+=4; |
744 | 2.94k | offset+=ReadBlob(image,sizeof(dpx.file.filename),(unsigned char *) |
745 | 2.94k | dpx.file.filename); |
746 | 2.94k | (void) FormatImageProperty(image,"dpx:file.filename","%.100s", |
747 | 2.94k | dpx.file.filename); |
748 | 2.94k | (void) FormatImageProperty(image,"document","%.100s",dpx.file.filename); |
749 | 2.94k | offset+=ReadBlob(image,sizeof(dpx.file.timestamp),(unsigned char *) |
750 | 2.94k | dpx.file.timestamp); |
751 | 2.94k | if (*dpx.file.timestamp != '\0') |
752 | 1.71k | (void) FormatImageProperty(image,"dpx:file.timestamp","%.24s", |
753 | 1.71k | dpx.file.timestamp); |
754 | 2.94k | offset+=ReadBlob(image,sizeof(dpx.file.creator),(unsigned char *) |
755 | 2.94k | dpx.file.creator); |
756 | 2.94k | if (*dpx.file.creator != '\0') |
757 | 1.70k | { |
758 | 1.70k | (void) FormatImageProperty(image,"dpx:file.creator","%.100s", |
759 | 1.70k | dpx.file.creator); |
760 | 1.70k | (void) FormatImageProperty(image,"software","%.100s",dpx.file.creator); |
761 | 1.70k | } |
762 | 2.94k | offset+=ReadBlob(image,sizeof(dpx.file.project),(unsigned char *) |
763 | 2.94k | dpx.file.project); |
764 | 2.94k | if (*dpx.file.project != '\0') |
765 | 1.88k | { |
766 | 1.88k | (void) FormatImageProperty(image,"dpx:file.project","%.200s", |
767 | 1.88k | dpx.file.project); |
768 | 1.88k | (void) FormatImageProperty(image,"comment","%.100s",dpx.file.project); |
769 | 1.88k | } |
770 | 2.94k | offset+=ReadBlob(image,sizeof(dpx.file.copyright),(unsigned char *) |
771 | 2.94k | dpx.file.copyright); |
772 | 2.94k | if (*dpx.file.copyright != '\0') |
773 | 1.75k | { |
774 | 1.75k | (void) FormatImageProperty(image,"dpx:file.copyright","%.200s", |
775 | 1.75k | dpx.file.copyright); |
776 | 1.75k | (void) FormatImageProperty(image,"copyright","%.100s", |
777 | 1.75k | dpx.file.copyright); |
778 | 1.75k | } |
779 | 2.94k | dpx.file.encrypt_key=ReadBlobLong(image); |
780 | 2.94k | offset+=4; |
781 | 2.94k | if (dpx.file.encrypt_key != ~0U) |
782 | 2.72k | (void) FormatImageProperty(image,"dpx:file.encrypt_key","%u", |
783 | 2.72k | dpx.file.encrypt_key); |
784 | 2.94k | offset+=ReadBlob(image,sizeof(dpx.file.reserve),(unsigned char *) |
785 | 2.94k | dpx.file.reserve); |
786 | | /* |
787 | | Read DPX image header. |
788 | | */ |
789 | 2.94k | dpx.image.orientation=ReadBlobShort(image); |
790 | 2.94k | if (dpx.image.orientation > 7) |
791 | 2.92k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
792 | 2.92k | offset+=2; |
793 | 2.92k | if (dpx.image.orientation != (unsigned short) ~0) |
794 | 2.92k | (void) FormatImageProperty(image,"dpx:image.orientation","%d", |
795 | 2.92k | dpx.image.orientation); |
796 | 2.92k | switch (dpx.image.orientation) |
797 | 2.92k | { |
798 | 0 | default: |
799 | 2.02k | case 0: image->orientation=TopLeftOrientation; break; |
800 | 532 | case 1: image->orientation=TopRightOrientation; break; |
801 | 15 | case 2: image->orientation=BottomLeftOrientation; break; |
802 | 32 | case 3: image->orientation=BottomRightOrientation; break; |
803 | 40 | case 4: image->orientation=LeftTopOrientation; break; |
804 | 49 | case 5: image->orientation=RightTopOrientation; break; |
805 | 23 | case 6: image->orientation=LeftBottomOrientation; break; |
806 | 208 | case 7: image->orientation=RightBottomOrientation; break; |
807 | 2.92k | } |
808 | 2.92k | dpx.image.number_elements=ReadBlobShort(image); |
809 | 2.92k | if ((dpx.image.number_elements < 1) || |
810 | 2.71k | (dpx.image.number_elements > MaxNumberImageElements)) |
811 | 2.70k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
812 | 2.70k | offset+=2; |
813 | 2.70k | dpx.image.pixels_per_line=ReadBlobLong(image); |
814 | 2.70k | offset+=4; |
815 | 2.70k | image->columns=dpx.image.pixels_per_line; |
816 | 2.70k | dpx.image.lines_per_element=ReadBlobLong(image); |
817 | 2.70k | offset+=4; |
818 | 2.70k | image->rows=dpx.image.lines_per_element; |
819 | 24.3k | for (i=0; i < 8; i++) |
820 | 21.6k | { |
821 | 21.6k | char |
822 | 21.6k | property[MagickPathExtent]; |
823 | | |
824 | 21.6k | dpx.image.image_element[i].data_sign=ReadBlobLong(image); |
825 | 21.6k | offset+=4; |
826 | 21.6k | dpx.image.image_element[i].low_data=ReadBlobLong(image); |
827 | 21.6k | offset+=4; |
828 | 21.6k | dpx.image.image_element[i].low_quantity=ReadBlobFloat(image); |
829 | 21.6k | offset+=4; |
830 | 21.6k | dpx.image.image_element[i].high_data=ReadBlobLong(image); |
831 | 21.6k | offset+=4; |
832 | 21.6k | dpx.image.image_element[i].high_quantity=ReadBlobFloat(image); |
833 | 21.6k | offset+=4; |
834 | 21.6k | dpx.image.image_element[i].descriptor=(unsigned char) ReadBlobByte(image); |
835 | 21.6k | offset++; |
836 | 21.6k | dpx.image.image_element[i].transfer_characteristic=(unsigned char) |
837 | 21.6k | ReadBlobByte(image); |
838 | 21.6k | (void) FormatLocaleString(property,MagickPathExtent, |
839 | 21.6k | "dpx:image.element[%lu].transfer-characteristic",(long) i); |
840 | 21.6k | (void) FormatImageProperty(image,property,"%s", |
841 | 21.6k | GetImageTransferCharacteristic((DPXTransferCharacteristic) |
842 | 21.6k | dpx.image.image_element[i].transfer_characteristic)); |
843 | 21.6k | offset++; |
844 | 21.6k | dpx.image.image_element[i].colorimetric=(unsigned char) ReadBlobByte(image); |
845 | 21.6k | offset++; |
846 | 21.6k | dpx.image.image_element[i].bit_size=(unsigned char) ReadBlobByte(image); |
847 | 21.6k | offset++; |
848 | 21.6k | dpx.image.image_element[i].packing=ReadBlobShort(image); |
849 | 21.6k | offset+=2; |
850 | 21.6k | dpx.image.image_element[i].encoding=ReadBlobShort(image); |
851 | 21.6k | offset+=2; |
852 | 21.6k | dpx.image.image_element[i].data_offset=ReadBlobLong(image); |
853 | 21.6k | offset+=4; |
854 | 21.6k | dpx.image.image_element[i].end_of_line_padding=ReadBlobLong(image); |
855 | 21.6k | offset+=4; |
856 | 21.6k | dpx.image.image_element[i].end_of_image_padding=ReadBlobLong(image); |
857 | 21.6k | offset+=4; |
858 | 21.6k | offset+=ReadBlob(image,sizeof(dpx.image.image_element[i].description), |
859 | 21.6k | (unsigned char *) dpx.image.image_element[i].description); |
860 | 21.6k | } |
861 | 2.70k | (void) SetImageColorspace(image,RGBColorspace,exception); |
862 | 2.70k | offset+=ReadBlob(image,sizeof(dpx.image.reserve),(unsigned char *) |
863 | 2.70k | dpx.image.reserve); |
864 | 2.70k | if (dpx.file.image_offset >= 1664U) |
865 | 1.45k | { |
866 | | /* |
867 | | Read DPX orientation header. |
868 | | */ |
869 | 1.45k | dpx.orientation.x_offset=ReadBlobLong(image); |
870 | 1.45k | offset+=4; |
871 | 1.45k | if (dpx.orientation.x_offset != ~0U) |
872 | 1.33k | (void) FormatImageProperty(image,"dpx:orientation.x_offset","%u", |
873 | 1.33k | dpx.orientation.x_offset); |
874 | 1.45k | dpx.orientation.y_offset=ReadBlobLong(image); |
875 | 1.45k | offset+=4; |
876 | 1.45k | if (dpx.orientation.y_offset != ~0U) |
877 | 1.33k | (void) FormatImageProperty(image,"dpx:orientation.y_offset","%u", |
878 | 1.33k | dpx.orientation.y_offset); |
879 | 1.45k | dpx.orientation.x_center=ReadBlobFloat(image); |
880 | 1.45k | offset+=4; |
881 | 1.45k | if (IsFloatDefined(dpx.orientation.x_center) != MagickFalse) |
882 | 1.36k | (void) FormatImageProperty(image,"dpx:orientation.x_center","%g", |
883 | 1.36k | (double) dpx.orientation.x_center); |
884 | 1.45k | dpx.orientation.y_center=ReadBlobFloat(image); |
885 | 1.45k | offset+=4; |
886 | 1.45k | if (IsFloatDefined(dpx.orientation.y_center) != MagickFalse) |
887 | 1.35k | (void) FormatImageProperty(image,"dpx:orientation.y_center","%g", |
888 | 1.35k | (double) dpx.orientation.y_center); |
889 | 1.45k | dpx.orientation.x_size=ReadBlobLong(image); |
890 | 1.45k | offset+=4; |
891 | 1.45k | if (dpx.orientation.x_size != ~0U) |
892 | 1.36k | (void) FormatImageProperty(image,"dpx:orientation.x_size","%u", |
893 | 1.36k | dpx.orientation.x_size); |
894 | 1.45k | dpx.orientation.y_size=ReadBlobLong(image); |
895 | 1.45k | offset+=4; |
896 | 1.45k | if (dpx.orientation.y_size != ~0U) |
897 | 1.37k | (void) FormatImageProperty(image,"dpx:orientation.y_size","%u", |
898 | 1.37k | dpx.orientation.y_size); |
899 | 1.45k | offset+=ReadBlob(image,sizeof(dpx.orientation.filename),(unsigned char *) |
900 | 1.45k | dpx.orientation.filename); |
901 | 1.45k | if (*dpx.orientation.filename != '\0') |
902 | 639 | (void) FormatImageProperty(image,"dpx:orientation.filename","%.100s", |
903 | 639 | dpx.orientation.filename); |
904 | 1.45k | offset+=ReadBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *) |
905 | 1.45k | dpx.orientation.timestamp); |
906 | 1.45k | if (*dpx.orientation.timestamp != '\0') |
907 | 600 | (void) FormatImageProperty(image,"dpx:orientation.timestamp","%.24s", |
908 | 600 | dpx.orientation.timestamp); |
909 | 1.45k | offset+=ReadBlob(image,sizeof(dpx.orientation.device),(unsigned char *) |
910 | 1.45k | dpx.orientation.device); |
911 | 1.45k | if (*dpx.orientation.device != '\0') |
912 | 620 | (void) FormatImageProperty(image,"dpx:orientation.device","%.32s", |
913 | 620 | dpx.orientation.device); |
914 | 1.45k | offset+=ReadBlob(image,sizeof(dpx.orientation.serial),(unsigned char *) |
915 | 1.45k | dpx.orientation.serial); |
916 | 1.45k | if (*dpx.orientation.serial != '\0') |
917 | 595 | (void) FormatImageProperty(image,"dpx:orientation.serial","%.32s", |
918 | 595 | dpx.orientation.serial); |
919 | 7.29k | for (i=0; i < 4; i++) |
920 | 5.83k | { |
921 | 5.83k | dpx.orientation.border[i]=ReadBlobShort(image); |
922 | 5.83k | offset+=2; |
923 | 5.83k | } |
924 | 1.45k | if ((dpx.orientation.border[0] != (unsigned short) (~0)) && |
925 | 1.34k | (dpx.orientation.border[1] != (unsigned short) (~0))) |
926 | 1.29k | (void) FormatImageProperty(image,"dpx:orientation.border","%dx%d%+d%+d", |
927 | 1.29k | dpx.orientation.border[0],dpx.orientation.border[1], |
928 | 1.29k | dpx.orientation.border[2],dpx.orientation.border[3]); |
929 | 4.37k | for (i=0; i < 2; i++) |
930 | 2.91k | { |
931 | 2.91k | dpx.orientation.aspect_ratio[i]=ReadBlobLong(image); |
932 | 2.91k | offset+=4; |
933 | 2.91k | } |
934 | 1.45k | if ((dpx.orientation.aspect_ratio[0] != ~0U) && |
935 | 1.38k | (dpx.orientation.aspect_ratio[1] != ~0U)) |
936 | 1.35k | (void) FormatImageProperty(image,"dpx:orientation.aspect_ratio", |
937 | 1.35k | "%ux%u",dpx.orientation.aspect_ratio[0], |
938 | 1.35k | dpx.orientation.aspect_ratio[1]); |
939 | 1.45k | offset+=ReadBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *) |
940 | 1.45k | dpx.orientation.reserve); |
941 | 1.45k | } |
942 | 2.70k | if (dpx.file.image_offset >= 1920U) |
943 | 1.37k | { |
944 | | /* |
945 | | Read DPX film header. |
946 | | */ |
947 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id); |
948 | 1.37k | if (*dpx.film.id != '\0') |
949 | 508 | (void) FormatImageProperty(image,"dpx:film.id","%.2s",dpx.film.id); |
950 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.type),(unsigned char *) |
951 | 1.37k | dpx.film.type); |
952 | 1.37k | if (*dpx.film.type != '\0') |
953 | 494 | (void) FormatImageProperty(image,"dpx:film.type","%.2s",dpx.film.type); |
954 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.offset),(unsigned char *) |
955 | 1.37k | dpx.film.offset); |
956 | 1.37k | if (*dpx.film.offset != '\0') |
957 | 499 | (void) FormatImageProperty(image,"dpx:film.offset","%.2s", |
958 | 499 | dpx.film.offset); |
959 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.prefix),(unsigned char *) |
960 | 1.37k | dpx.film.prefix); |
961 | 1.37k | if (*dpx.film.prefix != '\0') |
962 | 478 | (void) FormatImageProperty(image,"dpx:film.prefix","%.6s", |
963 | 478 | dpx.film.prefix); |
964 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.count),(unsigned char *) |
965 | 1.37k | dpx.film.count); |
966 | 1.37k | if (*dpx.film.count != '\0') |
967 | 472 | (void) FormatImageProperty(image,"dpx:film.count","%.4s", |
968 | 472 | dpx.film.count); |
969 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.format),(unsigned char *) |
970 | 1.37k | dpx.film.format); |
971 | 1.37k | if (*dpx.film.format != '\0') |
972 | 467 | (void) FormatImageProperty(image,"dpx:film.format","%.4s", |
973 | 467 | dpx.film.format); |
974 | 1.37k | dpx.film.frame_position=ReadBlobLong(image); |
975 | 1.37k | offset+=4; |
976 | 1.37k | if (dpx.film.frame_position != ~0U) |
977 | 1.30k | (void) FormatImageProperty(image,"dpx:film.frame_position","%u", |
978 | 1.30k | dpx.film.frame_position); |
979 | 1.37k | dpx.film.sequence_extent=ReadBlobLong(image); |
980 | 1.37k | offset+=4; |
981 | 1.37k | if (dpx.film.sequence_extent != ~0U) |
982 | 1.30k | (void) FormatImageProperty(image,"dpx:film.sequence_extent","%u", |
983 | 1.30k | dpx.film.sequence_extent); |
984 | 1.37k | dpx.film.held_count=ReadBlobLong(image); |
985 | 1.37k | offset+=4; |
986 | 1.37k | if (dpx.film.held_count != ~0U) |
987 | 1.29k | (void) FormatImageProperty(image,"dpx:film.held_count","%u", |
988 | 1.29k | dpx.film.held_count); |
989 | 1.37k | dpx.film.frame_rate=ReadBlobFloat(image); |
990 | 1.37k | offset+=4; |
991 | 1.37k | if (IsFloatDefined(dpx.film.frame_rate) != MagickFalse) |
992 | 1.29k | (void) FormatImageProperty(image,"dpx:film.frame_rate","%g", |
993 | 1.29k | (double) dpx.film.frame_rate); |
994 | 1.37k | dpx.film.shutter_angle=ReadBlobFloat(image); |
995 | 1.37k | offset+=4; |
996 | 1.37k | if (IsFloatDefined(dpx.film.shutter_angle) != MagickFalse) |
997 | 1.28k | (void) FormatImageProperty(image,"dpx:film.shutter_angle","%g", |
998 | 1.28k | (double) dpx.film.shutter_angle); |
999 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.frame_id),(unsigned char *) |
1000 | 1.37k | dpx.film.frame_id); |
1001 | 1.37k | if (*dpx.film.frame_id != '\0') |
1002 | 410 | (void) FormatImageProperty(image,"dpx:film.frame_id","%.32s", |
1003 | 410 | dpx.film.frame_id); |
1004 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.slate),(unsigned char *) |
1005 | 1.37k | dpx.film.slate); |
1006 | 1.37k | if (*dpx.film.slate != '\0') |
1007 | 379 | (void) FormatImageProperty(image,"dpx:film.slate","%.100s", |
1008 | 379 | dpx.film.slate); |
1009 | 1.37k | offset+=ReadBlob(image,sizeof(dpx.film.reserve),(unsigned char *) |
1010 | 1.37k | dpx.film.reserve); |
1011 | 1.37k | } |
1012 | 2.70k | if (dpx.file.image_offset >= 2048U) |
1013 | 1.34k | { |
1014 | | /* |
1015 | | Read DPX television header. |
1016 | | */ |
1017 | 1.34k | dpx.television.time_code=(unsigned int) ReadBlobLong(image); |
1018 | 1.34k | offset+=4; |
1019 | 1.34k | TimeCodeToString(dpx.television.time_code,value); |
1020 | 1.34k | (void) SetImageProperty(image,"dpx:television.time.code",value,exception); |
1021 | 1.34k | dpx.television.user_bits=(unsigned int) ReadBlobLong(image); |
1022 | 1.34k | offset+=4; |
1023 | 1.34k | TimeCodeToString(dpx.television.user_bits,value); |
1024 | 1.34k | (void) SetImageProperty(image,"dpx:television.user.bits",value,exception); |
1025 | 1.34k | dpx.television.interlace=(unsigned char) ReadBlobByte(image); |
1026 | 1.34k | offset++; |
1027 | 1.34k | if (dpx.television.interlace != 0) |
1028 | 1.17k | (void) FormatImageProperty(image,"dpx:television.interlace","%.20g", |
1029 | 1.17k | (double) dpx.television.interlace); |
1030 | 1.34k | dpx.television.field_number=(unsigned char) ReadBlobByte(image); |
1031 | 1.34k | offset++; |
1032 | 1.34k | if (dpx.television.field_number != 0) |
1033 | 1.18k | (void) FormatImageProperty(image,"dpx:television.field_number","%.20g", |
1034 | 1.18k | (double) dpx.television.field_number); |
1035 | 1.34k | dpx.television.video_signal=(unsigned char) ReadBlobByte(image); |
1036 | 1.34k | offset++; |
1037 | 1.34k | if (dpx.television.video_signal != 0) |
1038 | 1.17k | (void) FormatImageProperty(image,"dpx:television.video_signal","%.20g", |
1039 | 1.17k | (double) dpx.television.video_signal); |
1040 | 1.34k | dpx.television.padding=(unsigned char) ReadBlobByte(image); |
1041 | 1.34k | offset++; |
1042 | 1.34k | if (dpx.television.padding != 0) |
1043 | 1.19k | (void) FormatImageProperty(image,"dpx:television.padding","%d", |
1044 | 1.19k | dpx.television.padding); |
1045 | 1.34k | dpx.television.horizontal_sample_rate=ReadBlobFloat(image); |
1046 | 1.34k | offset+=4; |
1047 | 1.34k | if (IsFloatDefined(dpx.television.horizontal_sample_rate) != MagickFalse) |
1048 | 1.29k | (void) FormatImageProperty(image, |
1049 | 1.29k | "dpx:television.horizontal_sample_rate","%g", |
1050 | 1.29k | (double) dpx.television.horizontal_sample_rate); |
1051 | 1.34k | dpx.television.vertical_sample_rate=ReadBlobFloat(image); |
1052 | 1.34k | offset+=4; |
1053 | 1.34k | if (IsFloatDefined(dpx.television.vertical_sample_rate) != MagickFalse) |
1054 | 1.29k | (void) FormatImageProperty(image,"dpx:television.vertical_sample_rate", |
1055 | 1.29k | "%g",(double) dpx.television.vertical_sample_rate); |
1056 | 1.34k | dpx.television.frame_rate=ReadBlobFloat(image); |
1057 | 1.34k | offset+=4; |
1058 | 1.34k | if (IsFloatDefined(dpx.television.frame_rate) != MagickFalse) |
1059 | 1.28k | (void) FormatImageProperty(image,"dpx:television.frame_rate","%g", |
1060 | 1.28k | (double) dpx.television.frame_rate); |
1061 | 1.34k | dpx.television.time_offset=ReadBlobFloat(image); |
1062 | 1.34k | offset+=4; |
1063 | 1.34k | if (IsFloatDefined(dpx.television.time_offset) != MagickFalse) |
1064 | 1.29k | (void) FormatImageProperty(image,"dpx:television.time_offset","%g", |
1065 | 1.29k | (double) dpx.television.time_offset); |
1066 | 1.34k | dpx.television.gamma=ReadBlobFloat(image); |
1067 | 1.34k | offset+=4; |
1068 | 1.34k | if (IsFloatDefined(dpx.television.gamma) != MagickFalse) |
1069 | 1.30k | (void) FormatImageProperty(image,"dpx:television.gamma","%g", |
1070 | 1.30k | (double) dpx.television.gamma); |
1071 | 1.34k | dpx.television.black_level=ReadBlobFloat(image); |
1072 | 1.34k | offset+=4; |
1073 | 1.34k | if (IsFloatDefined(dpx.television.black_level) != MagickFalse) |
1074 | 1.31k | (void) FormatImageProperty(image,"dpx:television.black_level","%g", |
1075 | 1.31k | (double) dpx.television.black_level); |
1076 | 1.34k | dpx.television.black_gain=ReadBlobFloat(image); |
1077 | 1.34k | offset+=4; |
1078 | 1.34k | if (IsFloatDefined(dpx.television.black_gain) != MagickFalse) |
1079 | 1.32k | (void) FormatImageProperty(image,"dpx:television.black_gain","%g", |
1080 | 1.32k | (double) dpx.television.black_gain); |
1081 | 1.34k | dpx.television.break_point=ReadBlobFloat(image); |
1082 | 1.34k | offset+=4; |
1083 | 1.34k | if (IsFloatDefined(dpx.television.break_point) != MagickFalse) |
1084 | 1.32k | (void) FormatImageProperty(image,"dpx:television.break_point","%g", |
1085 | 1.32k | (double) dpx.television.break_point); |
1086 | 1.34k | dpx.television.white_level=ReadBlobFloat(image); |
1087 | 1.34k | offset+=4; |
1088 | 1.34k | if (IsFloatDefined(dpx.television.white_level) != MagickFalse) |
1089 | 1.33k | (void) FormatImageProperty(image,"dpx:television.white_level","%g", |
1090 | 1.33k | (double) dpx.television.white_level); |
1091 | 1.34k | dpx.television.integration_times=ReadBlobFloat(image); |
1092 | 1.34k | offset+=4; |
1093 | 1.34k | if (IsFloatDefined(dpx.television.integration_times) != MagickFalse) |
1094 | 1.32k | (void) FormatImageProperty(image,"dpx:television.integration_times", |
1095 | 1.32k | "%g",(double) dpx.television.integration_times); |
1096 | 1.34k | offset+=ReadBlob(image,sizeof(dpx.television.reserve),(unsigned char *) |
1097 | 1.34k | dpx.television.reserve); |
1098 | 1.34k | } |
1099 | 2.70k | if (dpx.file.image_offset > 2080U) |
1100 | 1.25k | { |
1101 | | /* |
1102 | | Read DPX user header. |
1103 | | */ |
1104 | 1.25k | offset+=ReadBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id); |
1105 | 1.25k | if (*dpx.user.id != '\0') |
1106 | 60 | (void) FormatImageProperty(image,"dpx:user.id","%.32s",dpx.user.id); |
1107 | 1.25k | if ((dpx.file.user_size != ~0U) && |
1108 | 1.18k | ((size_t) dpx.file.user_size > sizeof(dpx.user.id))) |
1109 | 1.04k | { |
1110 | 1.04k | size_t |
1111 | 1.04k | length; |
1112 | | |
1113 | 1.04k | StringInfo |
1114 | 1.04k | *profile; |
1115 | | |
1116 | 1.04k | length=dpx.file.user_size-sizeof(dpx.user.id); |
1117 | 1.04k | if ((MagickSizeType) length > GetBlobSize(image)) |
1118 | 754 | ThrowReaderException(CorruptImageError, |
1119 | 1.04k | "InsufficientImageDataInFile"); |
1120 | 294 | profile=AcquireProfileStringInfo("dpx:user-data",length,exception); |
1121 | 294 | if (profile == (StringInfo *) NULL) |
1122 | 0 | offset=SeekBlob(image,(MagickOffsetType) length,SEEK_CUR); |
1123 | 294 | else |
1124 | 294 | { |
1125 | 294 | offset+=ReadBlob(image,length,GetStringInfoDatum(profile)); |
1126 | 294 | (void) SetImageProfilePrivate(image,profile,exception); |
1127 | 294 | } |
1128 | 294 | } |
1129 | 1.25k | } |
1130 | 10.5k | for ( ; offset < (MagickOffsetType) dpx.file.image_offset; offset++) |
1131 | 9.15k | if (ReadBlobByte(image) == EOF) |
1132 | 581 | break; |
1133 | 1.94k | if (EOFBlob(image) != MagickFalse) |
1134 | 659 | { |
1135 | 659 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
1136 | 659 | image->filename); |
1137 | 659 | return(DestroyImageList(image)); |
1138 | 659 | } |
1139 | 1.28k | if (image_info->ping != MagickFalse) |
1140 | 3 | { |
1141 | 3 | (void) CloseBlob(image); |
1142 | 3 | return(GetFirstImageInList(image)); |
1143 | 3 | } |
1144 | 1.28k | status=SetImageExtent(image,image->columns,image->rows,exception); |
1145 | 1.28k | if (status == MagickFalse) |
1146 | 39 | return(DestroyImageList(image)); |
1147 | 1.24k | status=ResetImagePixels(image,exception); |
1148 | 1.24k | if (status == MagickFalse) |
1149 | 0 | return(DestroyImageList(image)); |
1150 | 7.61k | for (n=0; n < (ssize_t) dpx.image.number_elements; n++) |
1151 | 6.57k | { |
1152 | 6.57k | unsigned char |
1153 | 6.57k | *pixels; |
1154 | | |
1155 | | /* |
1156 | | Convert DPX raster image to pixel packets. |
1157 | | */ |
1158 | 6.57k | if ((dpx.image.image_element[n].data_offset != ~0U) && |
1159 | 6.18k | (dpx.image.image_element[n].data_offset != 0U)) |
1160 | 4.74k | { |
1161 | 4.74k | MagickOffsetType |
1162 | 4.74k | data_offset; |
1163 | | |
1164 | 4.74k | data_offset=(MagickOffsetType) dpx.image.image_element[n].data_offset; |
1165 | 4.74k | if (data_offset < offset) |
1166 | 2.92k | offset=SeekBlob(image,data_offset,SEEK_SET); |
1167 | 1.81k | else |
1168 | 280k | for ( ; offset < data_offset; offset++) |
1169 | 278k | if (ReadBlobByte(image) == EOF) |
1170 | 85 | break; |
1171 | 4.74k | if (offset != data_offset) |
1172 | 4.66k | ThrowReaderException(CorruptImageError,"UnableToReadImageData"); |
1173 | 4.66k | } |
1174 | 6.49k | SetPrimaryChromaticity((DPXColorimetric) |
1175 | 6.49k | dpx.image.image_element[n].colorimetric,&image->chromaticity); |
1176 | 6.49k | image->depth=dpx.image.image_element[n].bit_size; |
1177 | 6.49k | if ((image->depth == 0) || (image->depth > 32)) |
1178 | 6.47k | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
1179 | 6.47k | samples_per_pixel=1; |
1180 | 6.47k | quantum_type=GrayQuantum; |
1181 | 6.47k | component_type=dpx.image.image_element[n].descriptor; |
1182 | 6.47k | switch (component_type) |
1183 | 6.47k | { |
1184 | 362 | case CbYCrY422ComponentType: |
1185 | 362 | { |
1186 | 362 | samples_per_pixel=2; |
1187 | 362 | quantum_type=CbYCrYQuantum; |
1188 | 362 | break; |
1189 | 0 | } |
1190 | 203 | case CbYACrYA4224ComponentType: |
1191 | 399 | case CbYCr444ComponentType: |
1192 | 399 | { |
1193 | 399 | samples_per_pixel=3; |
1194 | 399 | quantum_type=CbYCrQuantum; |
1195 | 399 | break; |
1196 | 203 | } |
1197 | 668 | case RGBComponentType: |
1198 | 668 | { |
1199 | 668 | samples_per_pixel=3; |
1200 | 668 | quantum_type=RGBQuantum; |
1201 | 668 | break; |
1202 | 203 | } |
1203 | 202 | case ABGRComponentType: |
1204 | 435 | case RGBAComponentType: |
1205 | 435 | { |
1206 | 435 | image->alpha_trait=BlendPixelTrait; |
1207 | 435 | samples_per_pixel=4; |
1208 | 435 | quantum_type=RGBAQuantum; |
1209 | 435 | break; |
1210 | 202 | } |
1211 | 4.61k | default: |
1212 | 4.61k | break; |
1213 | 6.47k | } |
1214 | 6.47k | switch (component_type) |
1215 | 6.47k | { |
1216 | 362 | case CbYCrY422ComponentType: |
1217 | 565 | case CbYACrYA4224ComponentType: |
1218 | 761 | case CbYCr444ComponentType: |
1219 | 761 | { |
1220 | 761 | (void) SetImageColorspace(image,Rec709YCbCrColorspace,exception); |
1221 | 761 | break; |
1222 | 565 | } |
1223 | 474 | case LumaComponentType: |
1224 | 474 | { |
1225 | 474 | (void) SetImageColorspace(image,GRAYColorspace,exception); |
1226 | 474 | break; |
1227 | 565 | } |
1228 | 5.24k | default: |
1229 | 5.24k | { |
1230 | 5.24k | (void) SetImageColorspace(image,sRGBColorspace,exception); |
1231 | 5.24k | if (dpx.image.image_element[n].transfer_characteristic == LogarithmicColorimetric) |
1232 | 186 | (void) SetImageColorspace(image,LogColorspace,exception); |
1233 | 5.24k | if (dpx.image.image_element[n].transfer_characteristic == PrintingDensityColorimetric) |
1234 | 526 | (void) SetImageColorspace(image,LogColorspace,exception); |
1235 | 5.24k | break; |
1236 | 565 | } |
1237 | 6.47k | } |
1238 | 6.47k | extent=GetBytesPerRow(image->columns,samples_per_pixel,image->depth, |
1239 | 6.47k | dpx.image.image_element[n].packing == 0 ? MagickFalse : MagickTrue); |
1240 | | /* |
1241 | | DPX any-bit pixel format. |
1242 | | */ |
1243 | 6.47k | row=0; |
1244 | 6.47k | quantum_info=AcquireQuantumInfo(image_info,image); |
1245 | 6.47k | if (quantum_info == (QuantumInfo *) NULL) |
1246 | 6.47k | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
1247 | 6.47k | SetQuantumQuantum(quantum_info,32); |
1248 | 6.47k | SetQuantumPack(quantum_info,dpx.image.image_element[n].packing == 0 ? |
1249 | 4.27k | MagickTrue : MagickFalse); |
1250 | 6.47k | pixels=GetQuantumPixels(quantum_info); |
1251 | 98.7k | for (y=0; y < (ssize_t) image->rows; y++) |
1252 | 92.3k | { |
1253 | 92.3k | const void |
1254 | 92.3k | *stream; |
1255 | | |
1256 | 92.3k | MagickBooleanType |
1257 | 92.3k | sync; |
1258 | | |
1259 | 92.3k | Quantum |
1260 | 92.3k | *q; |
1261 | | |
1262 | 92.3k | size_t |
1263 | 92.3k | length; |
1264 | | |
1265 | 92.3k | ssize_t |
1266 | 92.3k | row_offset; |
1267 | | |
1268 | 92.3k | stream=ReadBlobStream(image,extent,pixels,&count); |
1269 | 92.3k | if (count != (ssize_t) extent) |
1270 | 114 | break; |
1271 | 92.2k | if ((image->progress_monitor != (MagickProgressMonitor) NULL) && |
1272 | 0 | (image->previous == (Image *) NULL)) |
1273 | 0 | { |
1274 | 0 | MagickBooleanType |
1275 | 0 | proceed; |
1276 | |
|
1277 | 0 | proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row, |
1278 | 0 | image->rows); |
1279 | 0 | if (proceed == MagickFalse) |
1280 | 0 | break; |
1281 | 0 | } |
1282 | 92.2k | row_offset=row++; |
1283 | 92.2k | q=QueueAuthenticPixels(image,0,row_offset,image->columns,1,exception); |
1284 | 92.2k | if (q == (Quantum *) NULL) |
1285 | 0 | break; |
1286 | 92.2k | length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
1287 | 92.2k | quantum_type,(unsigned char *) stream,exception); |
1288 | 92.2k | (void) length; |
1289 | 92.2k | sync=SyncAuthenticPixels(image,exception); |
1290 | 92.2k | if (sync == MagickFalse) |
1291 | 0 | break; |
1292 | 92.2k | } |
1293 | 6.47k | quantum_info=DestroyQuantumInfo(quantum_info); |
1294 | 6.47k | if (y < (ssize_t) image->rows) |
1295 | 6.36k | ThrowReaderException(CorruptImageError,"UnableToReadImageData"); |
1296 | 6.36k | SetQuantumImageType(image,quantum_type); |
1297 | 6.36k | if (EOFBlob(image) != MagickFalse) |
1298 | 0 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
1299 | 6.36k | image->filename); |
1300 | 6.36k | if ((i+1) < (ssize_t) dpx.image.number_elements) |
1301 | 178 | { |
1302 | | /* |
1303 | | Allocate next image structure. |
1304 | | */ |
1305 | 178 | AcquireNextImage(image_info,image,exception); |
1306 | 178 | if (GetNextImageInList(image) == (Image *) NULL) |
1307 | 0 | { |
1308 | 0 | status=MagickFalse; |
1309 | 0 | break; |
1310 | 0 | } |
1311 | 178 | image=SyncNextImageInList(image); |
1312 | 178 | image->columns=dpx.image.pixels_per_line; |
1313 | 178 | image->rows=dpx.image.lines_per_element; |
1314 | 178 | status=SetImageProgress(image,LoadImagesTag,TellBlob(image), |
1315 | 178 | GetBlobSize(image)); |
1316 | 178 | if (status == MagickFalse) |
1317 | 0 | break; |
1318 | 178 | } |
1319 | 6.36k | } |
1320 | 1.03k | if (CloseBlob(image) == MagickFalse) |
1321 | 0 | status=MagickFalse; |
1322 | 1.03k | if (status == MagickFalse) |
1323 | 0 | return(DestroyImageList(image)); |
1324 | 1.03k | return(GetFirstImageInList(image)); |
1325 | 1.03k | } |
1326 | | |
1327 | | /* |
1328 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1329 | | % % |
1330 | | % % |
1331 | | % % |
1332 | | % R e g i s t e r D P X I m a g e % |
1333 | | % % |
1334 | | % % |
1335 | | % % |
1336 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1337 | | % |
1338 | | % RegisterDPXImage() adds properties for the DPX image format to |
1339 | | % the list of supported formats. The properties include the image format |
1340 | | % tag, a method to read and/or write the format, whether the format |
1341 | | % supports the saving of more than one frame to the same file or blob, |
1342 | | % whether the format supports native in-memory I/O, and a brief |
1343 | | % description of the format. |
1344 | | % |
1345 | | % The format of the RegisterDPXImage method is: |
1346 | | % |
1347 | | % size_t RegisterDPXImage(void) |
1348 | | % |
1349 | | */ |
1350 | | ModuleExport size_t RegisterDPXImage(void) |
1351 | 10 | { |
1352 | 10 | MagickInfo |
1353 | 10 | *entry; |
1354 | | |
1355 | 10 | static const char |
1356 | 10 | *DPXNote = |
1357 | 10 | { |
1358 | 10 | "Digital Moving Picture Exchange Bitmap, Version 2.0.\n" |
1359 | 10 | "See SMPTE 268M-2003 specification at http://www.smtpe.org\n" |
1360 | 10 | }; |
1361 | | |
1362 | 10 | entry=AcquireMagickInfo("DPX","DPX","SMPTE 268M-2003 (DPX 2.0)"); |
1363 | 10 | entry->decoder=(DecodeImageHandler *) ReadDPXImage; |
1364 | 10 | entry->encoder=(EncodeImageHandler *) WriteDPXImage; |
1365 | 10 | entry->magick=(IsImageFormatHandler *) IsDPX; |
1366 | 10 | entry->flags^=CoderAdjoinFlag; |
1367 | 10 | entry->flags|=CoderDecoderSeekableStreamFlag; |
1368 | 10 | entry->flags|=CoderEndianSupportFlag; |
1369 | 10 | entry->note=ConstantString(DPXNote); |
1370 | 10 | (void) RegisterMagickInfo(entry); |
1371 | 10 | return(MagickImageCoderSignature); |
1372 | 10 | } |
1373 | | |
1374 | | /* |
1375 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1376 | | % % |
1377 | | % % |
1378 | | % % |
1379 | | % U n r e g i s t e r D P X I m a g e % |
1380 | | % % |
1381 | | % % |
1382 | | % % |
1383 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1384 | | % |
1385 | | % UnregisterDPXImage() removes format registrations made by the |
1386 | | % DPX module from the list of supported formats. |
1387 | | % |
1388 | | % The format of the UnregisterDPXImage method is: |
1389 | | % |
1390 | | % UnregisterDPXImage(void) |
1391 | | % |
1392 | | */ |
1393 | | ModuleExport void UnregisterDPXImage(void) |
1394 | 0 | { |
1395 | 0 | (void) UnregisterMagickInfo("DPX"); |
1396 | 0 | } |
1397 | | |
1398 | | /* |
1399 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1400 | | % % |
1401 | | % % |
1402 | | % % |
1403 | | % W r i t e D P X I m a g e % |
1404 | | % % |
1405 | | % % |
1406 | | % % |
1407 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1408 | | % |
1409 | | % WriteDPXImage() writes an image in DPX encoded image format. |
1410 | | % |
1411 | | % The format of the WriteDPXImage method is: |
1412 | | % |
1413 | | % MagickBooleanType WriteDPXImage(const ImageInfo *image_info, |
1414 | | % Image *image,ExceptionInfo *exception) |
1415 | | % |
1416 | | % A description of each parameter follows. |
1417 | | % |
1418 | | % o image_info: the image info. |
1419 | | % |
1420 | | % o image: The image. |
1421 | | % |
1422 | | % o exception: return any errors or warnings in this structure. |
1423 | | % |
1424 | | */ |
1425 | | |
1426 | | static unsigned int StringToTimeCode(const char *key) |
1427 | 154 | { |
1428 | 154 | char |
1429 | 154 | buffer[2]; |
1430 | | |
1431 | 154 | ssize_t |
1432 | 154 | i; |
1433 | | |
1434 | 154 | unsigned int |
1435 | 154 | shift, |
1436 | 154 | value; |
1437 | | |
1438 | 154 | value=0; |
1439 | 154 | shift=28; |
1440 | 154 | buffer[1]='\0'; |
1441 | 1.84k | for (i=0; (*key != 0) && (i < 11); i++) |
1442 | 1.69k | { |
1443 | 1.69k | if (isxdigit((int) ((unsigned char) *key)) == 0) |
1444 | 462 | { |
1445 | 462 | key++; |
1446 | 462 | continue; |
1447 | 462 | } |
1448 | 1.23k | buffer[0]=(*key++); |
1449 | 1.23k | value|=(unsigned int) ((strtol(buffer,(char **) NULL,16)) << shift); |
1450 | 1.23k | shift-=4; |
1451 | 1.23k | } |
1452 | 154 | return(value); |
1453 | 154 | } |
1454 | | |
1455 | | static inline const char *GetDPXProperty(const Image *image, |
1456 | | const char *property,ExceptionInfo *exception) |
1457 | 46.5k | { |
1458 | 46.5k | const char |
1459 | 46.5k | *value; |
1460 | | |
1461 | 46.5k | value=GetImageArtifact(image,property); |
1462 | 46.5k | if (value != (const char *) NULL) |
1463 | 0 | return(value); |
1464 | 46.5k | return(GetImageProperty(image,property,exception)); |
1465 | 46.5k | } |
1466 | | |
1467 | | static MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image, |
1468 | | ExceptionInfo *exception) |
1469 | 1.03k | { |
1470 | 1.03k | const char |
1471 | 1.03k | *value; |
1472 | | |
1473 | 1.03k | const StringInfo |
1474 | 1.03k | *profile; |
1475 | | |
1476 | 1.03k | DPXInfo |
1477 | 1.03k | dpx; |
1478 | | |
1479 | 1.03k | GeometryInfo |
1480 | 1.03k | geometry_info; |
1481 | | |
1482 | 1.03k | MagickBooleanType |
1483 | 1.03k | status; |
1484 | | |
1485 | 1.03k | MagickOffsetType |
1486 | 1.03k | offset; |
1487 | | |
1488 | 1.03k | MagickStatusType |
1489 | 1.03k | flags; |
1490 | | |
1491 | 1.03k | QuantumInfo |
1492 | 1.03k | *quantum_info; |
1493 | | |
1494 | 1.03k | QuantumType |
1495 | 1.03k | quantum_type; |
1496 | | |
1497 | 1.03k | const Quantum |
1498 | 1.03k | *p; |
1499 | | |
1500 | 1.03k | ssize_t |
1501 | 1.03k | i; |
1502 | | |
1503 | 1.03k | size_t |
1504 | 1.03k | channels, |
1505 | 1.03k | extent, |
1506 | 1.03k | samples_per_pixel; |
1507 | | |
1508 | 1.03k | ssize_t |
1509 | 1.03k | count, |
1510 | 1.03k | horizontal_factor, |
1511 | 1.03k | vertical_factor, |
1512 | 1.03k | y; |
1513 | | |
1514 | 1.03k | time_t |
1515 | 1.03k | seconds; |
1516 | | |
1517 | 1.03k | unsigned char |
1518 | 1.03k | component_type, |
1519 | 1.03k | *pixels; |
1520 | | |
1521 | | /* |
1522 | | Open output image file. |
1523 | | */ |
1524 | 1.03k | assert(image_info != (const ImageInfo *) NULL); |
1525 | 1.03k | assert(image_info->signature == MagickCoreSignature); |
1526 | 1.03k | assert(image != (Image *) NULL); |
1527 | 1.03k | assert(image->signature == MagickCoreSignature); |
1528 | 1.03k | if (IsEventLogging() != MagickFalse) |
1529 | 0 | (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
1530 | 1.03k | horizontal_factor=4; |
1531 | 1.03k | vertical_factor=4; |
1532 | 1.03k | if (image_info->sampling_factor != (char *) NULL) |
1533 | 0 | { |
1534 | 0 | flags=ParseGeometry(image_info->sampling_factor,&geometry_info); |
1535 | 0 | if ((flags & RhoValue) != 0) |
1536 | 0 | horizontal_factor=(ssize_t) geometry_info.rho; |
1537 | 0 | vertical_factor=horizontal_factor; |
1538 | 0 | if ((flags & SigmaValue) != 0) |
1539 | 0 | vertical_factor=(ssize_t) geometry_info.sigma; |
1540 | 0 | if ((horizontal_factor != 1) && (horizontal_factor != 2) && |
1541 | 0 | (horizontal_factor != 4) && (vertical_factor != 1) && |
1542 | 0 | (vertical_factor != 2) && (vertical_factor != 4)) |
1543 | 0 | ThrowWriterException(CorruptImageError,"UnexpectedSamplingFactor"); |
1544 | 0 | } |
1545 | 1.03k | if ((IsYCbCrCompatibleColorspace(image->colorspace) != MagickFalse) && |
1546 | 107 | ((horizontal_factor == 2) || (vertical_factor == 2))) |
1547 | 0 | if ((image->columns % 2) != 0) |
1548 | 0 | image->columns++; |
1549 | 1.03k | assert(exception != (ExceptionInfo *) NULL); |
1550 | 1.03k | assert(exception->signature == MagickCoreSignature); |
1551 | 1.03k | status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); |
1552 | 1.03k | if (status == MagickFalse) |
1553 | 0 | return(status); |
1554 | | /* |
1555 | | Write file header. |
1556 | | */ |
1557 | 1.03k | (void) memset(&dpx,0,sizeof(dpx)); |
1558 | 1.03k | offset=0; |
1559 | 1.03k | dpx.file.magic=0x53445058U; |
1560 | 1.03k | offset+=WriteBlobLong(image,dpx.file.magic); |
1561 | 1.03k | dpx.file.image_offset=0x2000U; |
1562 | 1.03k | profile=GetImageProfile(image,"dpx:user-data"); |
1563 | 1.03k | if (profile != (StringInfo *) NULL) |
1564 | 46 | { |
1565 | 46 | if (GetStringInfoLength(profile) > 1048576) |
1566 | 46 | ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); |
1567 | 46 | dpx.file.image_offset+=(unsigned int) GetStringInfoLength(profile); |
1568 | 46 | dpx.file.image_offset=(((dpx.file.image_offset+0x2000-1)/0x2000)*0x2000); |
1569 | 46 | } |
1570 | 1.03k | offset+=WriteBlobLong(image,dpx.file.image_offset); |
1571 | 1.03k | (void) CopyMagickString(dpx.file.version,"V2.0",sizeof(dpx.file.version)); |
1572 | 1.03k | offset+=WriteBlob(image,8,(unsigned char *) &dpx.file.version); |
1573 | 1.03k | channels=1; |
1574 | 1.03k | if (IsImageGray(image) == MagickFalse) |
1575 | 501 | channels=3; |
1576 | 1.03k | if (image->alpha_trait != UndefinedPixelTrait) |
1577 | 278 | channels++; |
1578 | 1.03k | dpx.file.file_size=(unsigned int) (channels*image->columns*image->rows+ |
1579 | 1.03k | dpx.file.image_offset); |
1580 | 1.03k | offset+=WriteBlobLong(image,dpx.file.file_size); |
1581 | 1.03k | dpx.file.ditto_key=1U; /* new frame */ |
1582 | 1.03k | offset+=WriteBlobLong(image,dpx.file.ditto_key); |
1583 | 1.03k | dpx.file.generic_size=0x00000680U; |
1584 | 1.03k | offset+=WriteBlobLong(image,dpx.file.generic_size); |
1585 | 1.03k | dpx.file.industry_size=0x00000180U; |
1586 | 1.03k | offset+=WriteBlobLong(image,dpx.file.industry_size); |
1587 | 1.03k | dpx.file.user_size=0; |
1588 | 1.03k | if (profile != (StringInfo *) NULL) |
1589 | 46 | { |
1590 | 46 | dpx.file.user_size+=(unsigned int) GetStringInfoLength(profile); |
1591 | 46 | dpx.file.user_size=(((dpx.file.user_size+0x2000-1)/0x2000)*0x2000); |
1592 | 46 | } |
1593 | 1.03k | offset+=WriteBlobLong(image,dpx.file.user_size); |
1594 | 1.03k | value=GetDPXProperty(image,"dpx:file.filename",exception); |
1595 | 1.03k | if (value != (const char *) NULL) |
1596 | 1.03k | (void) CopyMagickString(dpx.file.filename,value,sizeof(dpx.file.filename)); |
1597 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.file.filename),(unsigned char *) |
1598 | 1.03k | dpx.file.filename); |
1599 | 1.03k | seconds=GetMagickTime(); |
1600 | 1.03k | (void) FormatMagickTime(seconds,sizeof(dpx.file.timestamp), |
1601 | 1.03k | dpx.file.timestamp); |
1602 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.file.timestamp),(unsigned char *) |
1603 | 1.03k | dpx.file.timestamp); |
1604 | 1.03k | (void) CopyMagickString(dpx.file.creator,MagickAuthoritativeURL, |
1605 | 1.03k | sizeof(dpx.file.creator)); |
1606 | 1.03k | value=GetDPXProperty(image,"dpx:file.creator",exception); |
1607 | 1.03k | if (value != (const char *) NULL) |
1608 | 641 | (void) CopyMagickString(dpx.file.creator,value,sizeof(dpx.file.creator)); |
1609 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.file.creator),(unsigned char *) |
1610 | 1.03k | dpx.file.creator); |
1611 | 1.03k | value=GetDPXProperty(image,"dpx:file.project",exception); |
1612 | 1.03k | if (value != (const char *) NULL) |
1613 | 667 | (void) CopyMagickString(dpx.file.project,value,sizeof(dpx.file.project)); |
1614 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.file.project),(unsigned char *) |
1615 | 1.03k | dpx.file.project); |
1616 | 1.03k | value=GetDPXProperty(image,"dpx:file.copyright",exception); |
1617 | 1.03k | if (value != (const char *) NULL) |
1618 | 629 | (void) CopyMagickString(dpx.file.copyright,value, |
1619 | 629 | sizeof(dpx.file.copyright)); |
1620 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.file.copyright),(unsigned char *) |
1621 | 1.03k | dpx.file.copyright); |
1622 | 1.03k | dpx.file.encrypt_key=(~0U); |
1623 | 1.03k | offset+=WriteBlobLong(image,dpx.file.encrypt_key); |
1624 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.file.reserve),(unsigned char *) |
1625 | 1.03k | dpx.file.reserve); |
1626 | | /* |
1627 | | Write image header. |
1628 | | */ |
1629 | 1.03k | switch (image->orientation) |
1630 | 1.03k | { |
1631 | 0 | default: |
1632 | 523 | case TopLeftOrientation: dpx.image.orientation=0; break; |
1633 | 342 | case TopRightOrientation: dpx.image.orientation=1; break; |
1634 | 1 | case BottomLeftOrientation: dpx.image.orientation=2; break; |
1635 | 13 | case BottomRightOrientation: dpx.image.orientation=3; break; |
1636 | 4 | case LeftTopOrientation: dpx.image.orientation=4; break; |
1637 | 25 | case RightTopOrientation: dpx.image.orientation=5; break; |
1638 | 2 | case LeftBottomOrientation: dpx.image.orientation=6; break; |
1639 | 125 | case RightBottomOrientation: dpx.image.orientation=7; break; |
1640 | 1.03k | } |
1641 | 1.03k | offset+=WriteBlobShort(image,dpx.image.orientation); |
1642 | 1.03k | dpx.image.number_elements=1; |
1643 | 1.03k | offset+=WriteBlobShort(image,dpx.image.number_elements); |
1644 | 1.03k | if ((image->columns != (unsigned int) image->columns) || |
1645 | 1.03k | (image->rows != (unsigned int) image->rows)) |
1646 | 1.03k | ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); |
1647 | 1.03k | offset+=WriteBlobLong(image,(unsigned int) image->columns); |
1648 | 1.03k | offset+=WriteBlobLong(image,(unsigned int) image->rows); |
1649 | 9.31k | for (i=0; i < 8; i++) |
1650 | 8.28k | { |
1651 | 8.28k | dpx.image.image_element[i].data_sign=0U; |
1652 | 8.28k | offset+=WriteBlobLong(image,dpx.image.image_element[i].data_sign); |
1653 | 8.28k | dpx.image.image_element[i].low_data=0U; |
1654 | 8.28k | offset+=WriteBlobLong(image,dpx.image.image_element[i].low_data); |
1655 | 8.28k | dpx.image.image_element[i].low_quantity=0.0f; |
1656 | 8.28k | offset+=WriteBlobFloat(image,dpx.image.image_element[i].low_quantity); |
1657 | 8.28k | dpx.image.image_element[i].high_data=0U; |
1658 | 8.28k | offset+=WriteBlobLong(image,dpx.image.image_element[i].high_data); |
1659 | 8.28k | dpx.image.image_element[i].high_quantity=0.0f; |
1660 | 8.28k | offset+=WriteBlobFloat(image,dpx.image.image_element[i].high_quantity); |
1661 | 8.28k | dpx.image.image_element[i].descriptor=0; |
1662 | 8.28k | if (i == 0) |
1663 | 1.03k | switch (image->colorspace) |
1664 | 1.03k | { |
1665 | 0 | case Rec601YCbCrColorspace: |
1666 | 107 | case Rec709YCbCrColorspace: |
1667 | 107 | case YCbCrColorspace: |
1668 | 107 | { |
1669 | 107 | dpx.image.image_element[i].descriptor=CbYCr444ComponentType; |
1670 | 107 | if (image->alpha_trait != UndefinedPixelTrait) |
1671 | 28 | dpx.image.image_element[i].descriptor=CbYCrA4444ComponentType; |
1672 | 107 | break; |
1673 | 107 | } |
1674 | 928 | default: |
1675 | 928 | { |
1676 | 928 | dpx.image.image_element[i].descriptor=RGBComponentType; |
1677 | 928 | if (image->alpha_trait != UndefinedPixelTrait) |
1678 | 250 | dpx.image.image_element[i].descriptor=RGBAComponentType; |
1679 | 928 | if ((image_info->type != TrueColorType) && |
1680 | 928 | ((image->alpha_trait & BlendPixelTrait) == 0) && |
1681 | 678 | (IdentifyImageCoderGray(image,exception) != MagickFalse)) |
1682 | 483 | dpx.image.image_element[i].descriptor=LumaComponentType; |
1683 | 928 | break; |
1684 | 107 | } |
1685 | 1.03k | } |
1686 | 8.28k | offset+=WriteBlobByte(image,dpx.image.image_element[i].descriptor); |
1687 | 8.28k | dpx.image.image_element[i].transfer_characteristic=0; |
1688 | 8.28k | if (image->colorspace == LogColorspace) |
1689 | 480 | dpx.image.image_element[0].transfer_characteristic= |
1690 | 480 | PrintingDensityColorimetric; |
1691 | 8.28k | offset+=WriteBlobByte(image, |
1692 | 8.28k | dpx.image.image_element[i].transfer_characteristic); |
1693 | 8.28k | dpx.image.image_element[i].colorimetric=0; |
1694 | 8.28k | offset+=WriteBlobByte(image,dpx.image.image_element[i].colorimetric); |
1695 | 8.28k | dpx.image.image_element[i].bit_size=0; |
1696 | 8.28k | if (i == 0) |
1697 | 1.03k | dpx.image.image_element[i].bit_size=(unsigned char) image->depth; |
1698 | 8.28k | offset+=WriteBlobByte(image,dpx.image.image_element[i].bit_size); |
1699 | 8.28k | dpx.image.image_element[i].packing=0; |
1700 | 8.28k | if ((image->depth == 10) || (image->depth == 12)) |
1701 | 2.42k | dpx.image.image_element[i].packing=1; |
1702 | 8.28k | offset+=WriteBlobShort(image,dpx.image.image_element[i].packing); |
1703 | 8.28k | dpx.image.image_element[i].encoding=0; |
1704 | 8.28k | offset+=WriteBlobShort(image,dpx.image.image_element[i].encoding); |
1705 | 8.28k | dpx.image.image_element[i].data_offset=0U; |
1706 | 8.28k | if (i == 0) |
1707 | 1.03k | dpx.image.image_element[i].data_offset=dpx.file.image_offset; |
1708 | 8.28k | offset+=WriteBlobLong(image,dpx.image.image_element[i].data_offset); |
1709 | 8.28k | dpx.image.image_element[i].end_of_line_padding=0U; |
1710 | 8.28k | offset+=WriteBlobLong(image,dpx.image.image_element[i].end_of_line_padding); |
1711 | 8.28k | offset+=WriteBlobLong(image, |
1712 | 8.28k | dpx.image.image_element[i].end_of_image_padding); |
1713 | 8.28k | offset+=WriteBlob(image,sizeof(dpx.image.image_element[i].description), |
1714 | 8.28k | (unsigned char *) dpx.image.image_element[i].description); |
1715 | 8.28k | } |
1716 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.image.reserve),(unsigned char *) |
1717 | 1.03k | dpx.image.reserve); |
1718 | | /* |
1719 | | Write orientation header. |
1720 | | */ |
1721 | 1.03k | if ((image->rows != image->magick_rows) || |
1722 | 1.03k | (image->columns != image->magick_columns)) |
1723 | 0 | { |
1724 | | /* |
1725 | | These properties are not valid if image size changed. |
1726 | | */ |
1727 | 0 | (void) DeleteImageProperty(image,"dpx:orientation.x_offset"); |
1728 | 0 | (void) DeleteImageProperty(image,"dpx:orientation.y_offset"); |
1729 | 0 | (void) DeleteImageProperty(image,"dpx:orientation.x_center"); |
1730 | 0 | (void) DeleteImageProperty(image,"dpx:orientation.y_center"); |
1731 | 0 | (void) DeleteImageProperty(image,"dpx:orientation.x_size"); |
1732 | 0 | (void) DeleteImageProperty(image,"dpx:orientation.y_size"); |
1733 | 0 | } |
1734 | 1.03k | dpx.orientation.x_offset=0U; |
1735 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.x_offset",exception); |
1736 | 1.03k | if (value != (const char *) NULL) |
1737 | 108 | dpx.orientation.x_offset=(unsigned int) StringToUnsignedLong(value); |
1738 | 1.03k | offset+=WriteBlobLong(image,dpx.orientation.x_offset); |
1739 | 1.03k | dpx.orientation.y_offset=0U; |
1740 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.y_offset",exception); |
1741 | 1.03k | if (value != (const char *) NULL) |
1742 | 106 | dpx.orientation.y_offset=(unsigned int) StringToUnsignedLong(value); |
1743 | 1.03k | offset+=WriteBlobLong(image,dpx.orientation.y_offset); |
1744 | 1.03k | dpx.orientation.x_center=0.0f; |
1745 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.x_center",exception); |
1746 | 1.03k | if (value != (const char *) NULL) |
1747 | 118 | dpx.orientation.x_center=StringToFloat(value,(char **) NULL); |
1748 | 1.03k | offset+=WriteBlobFloat(image,dpx.orientation.x_center); |
1749 | 1.03k | dpx.orientation.y_center=0.0f; |
1750 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.y_center",exception); |
1751 | 1.03k | if (value != (const char *) NULL) |
1752 | 113 | dpx.orientation.y_center=StringToFloat(value,(char **) NULL); |
1753 | 1.03k | offset+=WriteBlobFloat(image,dpx.orientation.y_center); |
1754 | 1.03k | dpx.orientation.x_size=0U; |
1755 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.x_size",exception); |
1756 | 1.03k | if (value != (const char *) NULL) |
1757 | 113 | dpx.orientation.x_size=(unsigned int) StringToUnsignedLong(value); |
1758 | 1.03k | offset+=WriteBlobLong(image,dpx.orientation.x_size); |
1759 | 1.03k | dpx.orientation.y_size=0U; |
1760 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.y_size",exception); |
1761 | 1.03k | if (value != (const char *) NULL) |
1762 | 112 | dpx.orientation.y_size=(unsigned int) StringToUnsignedLong(value); |
1763 | 1.03k | offset+=WriteBlobLong(image,dpx.orientation.y_size); |
1764 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.filename",exception); |
1765 | 1.03k | if (value != (const char *) NULL) |
1766 | 90 | (void) CopyMagickString(dpx.orientation.filename,value, |
1767 | 90 | sizeof(dpx.orientation.filename)); |
1768 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.orientation.filename),(unsigned char *) |
1769 | 1.03k | dpx.orientation.filename); |
1770 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *) |
1771 | 1.03k | dpx.orientation.timestamp); |
1772 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.device",exception); |
1773 | 1.03k | if (value != (const char *) NULL) |
1774 | 90 | (void) CopyMagickString(dpx.orientation.device,value, |
1775 | 90 | sizeof(dpx.orientation.device)); |
1776 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.orientation.device),(unsigned char *) |
1777 | 1.03k | dpx.orientation.device); |
1778 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.serial",exception); |
1779 | 1.03k | if (value != (const char *) NULL) |
1780 | 84 | (void) CopyMagickString(dpx.orientation.serial,value, |
1781 | 84 | sizeof(dpx.orientation.serial)); |
1782 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.orientation.serial),(unsigned char *) |
1783 | 1.03k | dpx.orientation.serial); |
1784 | 5.17k | for (i=0; i < 4; i++) |
1785 | 4.14k | dpx.orientation.border[i]=0; |
1786 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.border",exception); |
1787 | 1.03k | if (value != (const char *) NULL) |
1788 | 107 | { |
1789 | 107 | flags=ParseGeometry(value,&geometry_info); |
1790 | 107 | if ((flags & SigmaValue) == 0) |
1791 | 0 | geometry_info.sigma=geometry_info.rho; |
1792 | 107 | dpx.orientation.border[0]=(unsigned short) (geometry_info.rho+0.5); |
1793 | 107 | dpx.orientation.border[1]=(unsigned short) (geometry_info.sigma+0.5); |
1794 | 107 | dpx.orientation.border[2]=(unsigned short) (geometry_info.xi+0.5); |
1795 | 107 | dpx.orientation.border[3]=(unsigned short) (geometry_info.psi+0.5); |
1796 | 107 | } |
1797 | 5.17k | for (i=0; i < 4; i++) |
1798 | 4.14k | offset+=WriteBlobShort(image,dpx.orientation.border[i]); |
1799 | 3.10k | for (i=0; i < 2; i++) |
1800 | 2.07k | dpx.orientation.aspect_ratio[i]=0U; |
1801 | 1.03k | value=GetDPXProperty(image,"dpx:orientation.aspect_ratio",exception); |
1802 | 1.03k | if (value != (const char *) NULL) |
1803 | 116 | { |
1804 | 116 | flags=ParseGeometry(value,&geometry_info); |
1805 | 116 | if ((flags & SigmaValue) == 0) |
1806 | 0 | geometry_info.sigma=geometry_info.rho; |
1807 | 116 | dpx.orientation.aspect_ratio[0]=(unsigned int) (geometry_info.rho+0.5); |
1808 | 116 | dpx.orientation.aspect_ratio[1]=(unsigned int) (geometry_info.sigma+0.5); |
1809 | 116 | } |
1810 | 3.10k | for (i=0; i < 2; i++) |
1811 | 2.07k | offset+=WriteBlobLong(image,dpx.orientation.aspect_ratio[i]); |
1812 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *) |
1813 | 1.03k | dpx.orientation.reserve); |
1814 | | /* |
1815 | | Write film header. |
1816 | | */ |
1817 | 1.03k | (void) memset(dpx.film.id,0,sizeof(dpx.film.id)); |
1818 | 1.03k | value=GetDPXProperty(image,"dpx:film.id",exception); |
1819 | 1.03k | if (value != (const char *) NULL) |
1820 | 55 | (void) CopyMagickString(dpx.film.id,value,sizeof(dpx.film.id)); |
1821 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id); |
1822 | 1.03k | (void) memset(dpx.film.type,0,sizeof(dpx.film.type)); |
1823 | 1.03k | value=GetDPXProperty(image,"dpx:film.type",exception); |
1824 | 1.03k | if (value != (const char *) NULL) |
1825 | 53 | (void) CopyMagickString(dpx.film.type,value,sizeof(dpx.film.type)); |
1826 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.type),(unsigned char *) |
1827 | 1.03k | dpx.film.type); |
1828 | 1.03k | (void) memset(dpx.film.offset,0,sizeof(dpx.film.offset)); |
1829 | 1.03k | value=GetDPXProperty(image,"dpx:film.offset",exception); |
1830 | 1.03k | if (value != (const char *) NULL) |
1831 | 55 | (void) CopyMagickString(dpx.film.offset,value,sizeof(dpx.film.offset)); |
1832 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.offset),(unsigned char *) |
1833 | 1.03k | dpx.film.offset); |
1834 | 1.03k | (void) memset(dpx.film.prefix,0,sizeof(dpx.film.prefix)); |
1835 | 1.03k | value=GetDPXProperty(image,"dpx:film.prefix",exception); |
1836 | 1.03k | if (value != (const char *) NULL) |
1837 | 60 | (void) CopyMagickString(dpx.film.prefix,value,sizeof(dpx.film.prefix)); |
1838 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.prefix),(unsigned char *) |
1839 | 1.03k | dpx.film.prefix); |
1840 | 1.03k | (void) memset(dpx.film.count,0,sizeof(dpx.film.count)); |
1841 | 1.03k | value=GetDPXProperty(image,"dpx:film.count",exception); |
1842 | 1.03k | if (value != (const char *) NULL) |
1843 | 58 | (void) CopyMagickString(dpx.film.count,value,sizeof(dpx.film.count)); |
1844 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.count),(unsigned char *) |
1845 | 1.03k | dpx.film.count); |
1846 | 1.03k | (void) memset(dpx.film.format,0,sizeof(dpx.film.format)); |
1847 | 1.03k | value=GetDPXProperty(image,"dpx:film.format",exception); |
1848 | 1.03k | if (value != (const char *) NULL) |
1849 | 53 | (void) CopyMagickString(dpx.film.format,value,sizeof(dpx.film.format)); |
1850 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.format),(unsigned char *) |
1851 | 1.03k | dpx.film.format); |
1852 | 1.03k | dpx.film.frame_position=0U; |
1853 | 1.03k | value=GetDPXProperty(image,"dpx:film.frame_position",exception); |
1854 | 1.03k | if (value != (const char *) NULL) |
1855 | 80 | dpx.film.frame_position=(unsigned int) StringToUnsignedLong(value); |
1856 | 1.03k | offset+=WriteBlobLong(image,dpx.film.frame_position); |
1857 | 1.03k | dpx.film.sequence_extent=0U; |
1858 | 1.03k | value=GetDPXProperty(image,"dpx:film.sequence_extent",exception); |
1859 | 1.03k | if (value != (const char *) NULL) |
1860 | 81 | dpx.film.sequence_extent=(unsigned int) StringToUnsignedLong(value); |
1861 | 1.03k | offset+=WriteBlobLong(image,dpx.film.sequence_extent); |
1862 | 1.03k | dpx.film.held_count=0U; |
1863 | 1.03k | value=GetDPXProperty(image,"dpx:film.held_count",exception); |
1864 | 1.03k | if (value != (const char *) NULL) |
1865 | 80 | dpx.film.held_count=(unsigned int) StringToUnsignedLong(value); |
1866 | 1.03k | offset+=WriteBlobLong(image,dpx.film.held_count); |
1867 | 1.03k | dpx.film.frame_rate=0.0f; |
1868 | 1.03k | value=GetDPXProperty(image,"dpx:film.frame_rate",exception); |
1869 | 1.03k | if (value != (const char *) NULL) |
1870 | 81 | dpx.film.frame_rate=StringToFloat(value,(char **) NULL); |
1871 | 1.03k | offset+=WriteBlobFloat(image,dpx.film.frame_rate); |
1872 | 1.03k | dpx.film.shutter_angle=0.0f; |
1873 | 1.03k | value=GetDPXProperty(image,"dpx:film.shutter_angle",exception); |
1874 | 1.03k | if (value != (const char *) NULL) |
1875 | 76 | dpx.film.shutter_angle=StringToFloat(value,(char **) NULL); |
1876 | 1.03k | offset+=WriteBlobFloat(image,dpx.film.shutter_angle); |
1877 | 1.03k | (void) memset(dpx.film.frame_id,0,sizeof(dpx.film.frame_id)); |
1878 | 1.03k | value=GetDPXProperty(image,"dpx:film.frame_id",exception); |
1879 | 1.03k | if (value != (const char *) NULL) |
1880 | 59 | (void) CopyMagickString(dpx.film.frame_id,value,sizeof(dpx.film.frame_id)); |
1881 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.frame_id),(unsigned char *) |
1882 | 1.03k | dpx.film.frame_id); |
1883 | 1.03k | value=GetDPXProperty(image,"dpx:film.slate",exception); |
1884 | 1.03k | if (value != (const char *) NULL) |
1885 | 57 | (void) CopyMagickString(dpx.film.slate,value,sizeof(dpx.film.slate)); |
1886 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.slate),(unsigned char *) |
1887 | 1.03k | dpx.film.slate); |
1888 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.film.reserve),(unsigned char *) |
1889 | 1.03k | dpx.film.reserve); |
1890 | | /* |
1891 | | Write television header. |
1892 | | */ |
1893 | 1.03k | value=GetDPXProperty(image,"dpx:television.time.code",exception); |
1894 | 1.03k | if (value != (const char *) NULL) |
1895 | 77 | dpx.television.time_code=StringToTimeCode(value); |
1896 | 1.03k | offset+=WriteBlobLong(image,dpx.television.time_code); |
1897 | 1.03k | value=GetDPXProperty(image,"dpx:television.user.bits",exception); |
1898 | 1.03k | if (value != (const char *) NULL) |
1899 | 77 | dpx.television.user_bits=StringToTimeCode(value); |
1900 | 1.03k | offset+=WriteBlobLong(image,dpx.television.user_bits); |
1901 | 1.03k | value=GetDPXProperty(image,"dpx:television.interlace",exception); |
1902 | 1.03k | if (value != (const char *) NULL) |
1903 | 47 | dpx.television.interlace=(unsigned char) StringToLong(value); |
1904 | 1.03k | offset+=WriteBlobByte(image,dpx.television.interlace); |
1905 | 1.03k | value=GetDPXProperty(image,"dpx:television.field_number",exception); |
1906 | 1.03k | if (value != (const char *) NULL) |
1907 | 54 | dpx.television.field_number=(unsigned char) StringToLong(value); |
1908 | 1.03k | offset+=WriteBlobByte(image,dpx.television.field_number); |
1909 | 1.03k | dpx.television.video_signal=0; |
1910 | 1.03k | value=GetDPXProperty(image,"dpx:television.video_signal",exception); |
1911 | 1.03k | if (value != (const char *) NULL) |
1912 | 48 | dpx.television.video_signal=(unsigned char) StringToLong(value); |
1913 | 1.03k | offset+=WriteBlobByte(image,dpx.television.video_signal); |
1914 | 1.03k | dpx.television.padding=0; |
1915 | 1.03k | value=GetDPXProperty(image,"dpx:television.padding",exception); |
1916 | 1.03k | if (value != (const char *) NULL) |
1917 | 48 | dpx.television.padding=(unsigned char) StringToLong(value); |
1918 | 1.03k | offset+=WriteBlobByte(image,dpx.television.padding); |
1919 | 1.03k | dpx.television.horizontal_sample_rate=0.0f; |
1920 | 1.03k | value=GetDPXProperty(image,"dpx:television.horizontal_sample_rate", |
1921 | 1.03k | exception); |
1922 | 1.03k | if (value != (const char *) NULL) |
1923 | 70 | dpx.television.horizontal_sample_rate=StringToFloat(value,(char **) NULL); |
1924 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.horizontal_sample_rate); |
1925 | 1.03k | dpx.television.vertical_sample_rate=0.0f; |
1926 | 1.03k | value=GetDPXProperty(image,"dpx:television.vertical_sample_rate",exception); |
1927 | 1.03k | if (value != (const char *) NULL) |
1928 | 69 | dpx.television.vertical_sample_rate=StringToFloat(value,(char **) NULL); |
1929 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.vertical_sample_rate); |
1930 | 1.03k | dpx.television.frame_rate=0.0f; |
1931 | 1.03k | value=GetDPXProperty(image,"dpx:television.frame_rate",exception); |
1932 | 1.03k | if (value != (const char *) NULL) |
1933 | 70 | dpx.television.frame_rate=StringToFloat(value,(char **) NULL); |
1934 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.frame_rate); |
1935 | 1.03k | dpx.television.time_offset=0.0f; |
1936 | 1.03k | value=GetDPXProperty(image,"dpx:television.time_offset",exception); |
1937 | 1.03k | if (value != (const char *) NULL) |
1938 | 75 | dpx.television.time_offset=StringToFloat(value,(char **) NULL); |
1939 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.time_offset); |
1940 | 1.03k | dpx.television.gamma=0.0f; |
1941 | 1.03k | value=GetDPXProperty(image,"dpx:television.gamma",exception); |
1942 | 1.03k | if (value != (const char *) NULL) |
1943 | 74 | dpx.television.gamma=StringToFloat(value,(char **) NULL); |
1944 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.gamma); |
1945 | 1.03k | dpx.television.black_level=0.0f; |
1946 | 1.03k | value=GetDPXProperty(image,"dpx:television.black_level",exception); |
1947 | 1.03k | if (value != (const char *) NULL) |
1948 | 74 | dpx.television.black_level=StringToFloat(value,(char **) NULL); |
1949 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.black_level); |
1950 | 1.03k | dpx.television.black_gain=0.0f; |
1951 | 1.03k | value=GetDPXProperty(image,"dpx:television.black_gain",exception); |
1952 | 1.03k | if (value != (const char *) NULL) |
1953 | 73 | dpx.television.black_gain=StringToFloat(value,(char **) NULL); |
1954 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.black_gain); |
1955 | 1.03k | dpx.television.break_point=0.0f; |
1956 | 1.03k | value=GetDPXProperty(image,"dpx:television.break_point",exception); |
1957 | 1.03k | if (value != (const char *) NULL) |
1958 | 71 | dpx.television.break_point=StringToFloat(value,(char **) NULL); |
1959 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.break_point); |
1960 | 1.03k | dpx.television.white_level=0.0f; |
1961 | 1.03k | value=GetDPXProperty(image,"dpx:television.white_level",exception); |
1962 | 1.03k | if (value != (const char *) NULL) |
1963 | 71 | dpx.television.white_level=StringToFloat(value,(char **) NULL); |
1964 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.white_level); |
1965 | 1.03k | dpx.television.integration_times=0.0f; |
1966 | 1.03k | value=GetDPXProperty(image,"dpx:television.integration_times",exception); |
1967 | 1.03k | if (value != (const char *) NULL) |
1968 | 68 | dpx.television.integration_times=StringToFloat(value,(char **) NULL); |
1969 | 1.03k | offset+=WriteBlobFloat(image,dpx.television.integration_times); |
1970 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.television.reserve),(unsigned char *) |
1971 | 1.03k | dpx.television.reserve); |
1972 | | /* |
1973 | | Write user header. |
1974 | | */ |
1975 | 1.03k | value=GetDPXProperty(image,"dpx:user.id",exception); |
1976 | 1.03k | if (value != (const char *) NULL) |
1977 | 32 | (void) CopyMagickString(dpx.user.id,value,sizeof(dpx.user.id)); |
1978 | 1.03k | offset+=WriteBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id); |
1979 | 1.03k | if (profile != (StringInfo *) NULL) |
1980 | 46 | offset+=WriteBlob(image,GetStringInfoLength(profile), |
1981 | 46 | GetStringInfoDatum(profile)); |
1982 | 6.67M | while (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset) |
1983 | 6.67M | { |
1984 | 6.67M | count=WriteBlobByte(image,0x00); |
1985 | 6.67M | if (count != 1) |
1986 | 0 | { |
1987 | 0 | ThrowFileException(exception,FileOpenError,"UnableToWriteFile", |
1988 | 0 | image->filename); |
1989 | 0 | break; |
1990 | 0 | } |
1991 | 6.67M | offset+=count; |
1992 | 6.67M | } |
1993 | | /* |
1994 | | Convert pixel packets to DPX raster image. |
1995 | | */ |
1996 | 1.03k | quantum_info=AcquireQuantumInfo(image_info,image); |
1997 | 1.03k | if (quantum_info == (QuantumInfo *) NULL) |
1998 | 1.03k | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
1999 | 1.03k | SetQuantumQuantum(quantum_info,32); |
2000 | 1.03k | SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ? |
2001 | 732 | MagickTrue : MagickFalse); |
2002 | 1.03k | samples_per_pixel=1; |
2003 | 1.03k | quantum_type=GrayQuantum; |
2004 | 1.03k | component_type=dpx.image.image_element[0].descriptor; |
2005 | 1.03k | switch (component_type) |
2006 | 1.03k | { |
2007 | 0 | case CbYCrY422ComponentType: |
2008 | 0 | { |
2009 | 0 | samples_per_pixel=2; |
2010 | 0 | quantum_type=CbYCrYQuantum; |
2011 | 0 | break; |
2012 | 0 | } |
2013 | 0 | case CbYACrYA4224ComponentType: |
2014 | 79 | case CbYCr444ComponentType: |
2015 | 79 | { |
2016 | 79 | samples_per_pixel=3; |
2017 | 79 | quantum_type=CbYCrQuantum; |
2018 | 79 | break; |
2019 | 0 | } |
2020 | 195 | case RGBComponentType: |
2021 | 195 | { |
2022 | 195 | samples_per_pixel=3; |
2023 | 195 | quantum_type=RGBQuantum; |
2024 | 195 | break; |
2025 | 0 | } |
2026 | 0 | case ABGRComponentType: |
2027 | 250 | case RGBAComponentType: |
2028 | 250 | { |
2029 | 250 | samples_per_pixel=4; |
2030 | 250 | quantum_type=RGBAQuantum; |
2031 | 250 | break; |
2032 | 0 | } |
2033 | 511 | default: |
2034 | 511 | { |
2035 | 511 | if (channels == 1) |
2036 | 434 | break; |
2037 | 77 | quantum_type=RGBAQuantum; |
2038 | 77 | if (image->alpha_trait != UndefinedPixelTrait) |
2039 | 28 | quantum_type=RGBQuantum; |
2040 | 77 | if (IsYCbCrCompatibleColorspace(image->colorspace) != MagickFalse) |
2041 | 28 | { |
2042 | 28 | quantum_type=CbYCrQuantum; |
2043 | 28 | if (image->alpha_trait != UndefinedPixelTrait) |
2044 | 28 | quantum_type=CbYCrAQuantum; |
2045 | 28 | if ((horizontal_factor == 2) || (vertical_factor == 2)) |
2046 | 0 | quantum_type=CbYCrYQuantum; |
2047 | 28 | } |
2048 | 77 | break; |
2049 | 511 | } |
2050 | 1.03k | } |
2051 | 1.03k | extent=GetBytesPerRow(image->columns,samples_per_pixel,image->depth, |
2052 | 1.03k | dpx.image.image_element[0].packing == 0 ? MagickFalse : MagickTrue); |
2053 | 1.03k | pixels=(unsigned char *) GetQuantumPixels(quantum_info); |
2054 | 30.4k | for (y=0; y < (ssize_t) image->rows; y++) |
2055 | 29.4k | { |
2056 | 29.4k | size_t |
2057 | 29.4k | length; |
2058 | | |
2059 | 29.4k | p=GetVirtualPixels(image,0,y,image->columns,1,exception); |
2060 | 29.4k | if (p == (const Quantum *) NULL) |
2061 | 0 | break; |
2062 | 29.4k | length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
2063 | 29.4k | quantum_type,pixels,exception); |
2064 | 29.4k | if (length == 0) |
2065 | 0 | break; |
2066 | 29.4k | count=WriteBlob(image,extent,pixels); |
2067 | 29.4k | if (count != (ssize_t) extent) |
2068 | 0 | break; |
2069 | 29.4k | status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, |
2070 | 29.4k | image->rows); |
2071 | 29.4k | if (status == MagickFalse) |
2072 | 0 | break; |
2073 | 29.4k | } |
2074 | 1.03k | quantum_info=DestroyQuantumInfo(quantum_info); |
2075 | 1.03k | if (y < (ssize_t) image->rows) |
2076 | 1.03k | ThrowWriterException(CorruptImageError,"UnableToWriteImageData"); |
2077 | 1.03k | if (CloseBlob(image) == MagickFalse) |
2078 | 0 | status=MagickFalse; |
2079 | 1.03k | return(status); |
2080 | 1.03k | } |