source: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/NikonCapture.pm@ 34921

Last change on this file since 34921 was 34921, checked in by anupama, 3 years ago

Committing the improvements to EmbeddedMetaPlugin's processing of Keywords vs other metadata fields. Keywords were literally stored as arrays of words rather than phrases in PDFs (at least in Diego's sample PDF), whereas other meta fields like Subjects and Creators stored them as arrays of phrases. To get both to work, Kathy updated EXIF to a newer version, to retrieve the actual EXIF values stored in the PDF. And Kathy and Dr Bainbridge came up with a new option that I added called apply_join_before_split_to_metafields that's a regex which can list the metadata fields to apply the join_before_split to and whcih previously always got applied to all metadata fields. Now it's applied to any *Keywords metafields by default, as that's the metafield we have experience of that behaves differently to the others, as it stores by word instead of phrases. Tested on Diego's sample PDF. Diego has double-checked it to works on his sample PDF too, setting the split char to ; and turning on the join_before_split and leaving apply_join_before_split_to_metafields at its default of .*Keywords. File changes are strings.properties for the tooltip, the plugin introducing the option and working with it and Kathy's EXIF updates affecting cpan/File and cpan/Image.

File size: 28.1 KB
Line 
1#------------------------------------------------------------------------------
2# File: NikonCapture.pm
3#
4# Description: Read/write Nikon Capture information
5#
6# Revisions: 11/08/2005 - P. Harvey Created
7# 10/10/2008 - P. Harvey Updated for Capture NX 2
8# 16/04/2011 - P. Harvey Decode NikonCaptureEditVersions
9#
10# References: 1) http://www.cybercom.net/~dcoffin/dcraw/
11# IB) Iliah Borg private communication (LibRaw)
12#------------------------------------------------------------------------------
13
14package Image::ExifTool::NikonCapture;
15
16use strict;
17use vars qw($VERSION);
18use Image::ExifTool qw(:DataAccess :Utils);
19use Image::ExifTool::Exif;
20
21$VERSION = '1.14';
22
23sub ProcessNikonCapture($$$);
24
25# common print conversions
26my %offOn = ( 0 => 'Off', 1 => 'On' );
27my %noYes = ( 0 => 'No', 1 => 'Yes' );
28my %unsharpColor = (
29 0 => 'RGB',
30 1 => 'Red',
31 2 => 'Green',
32 3 => 'Blue',
33 4 => 'Yellow',
34 5 => 'Magenta',
35 6 => 'Cyan',
36);
37
38# Nikon Capture data (ref PH)
39%Image::ExifTool::NikonCapture::Main = (
40 PROCESS_PROC => \&ProcessNikonCapture,
41 WRITE_PROC => \&WriteNikonCapture,
42 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
43 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
44 NOTES => q{
45 This information is written by the Nikon Capture software in tag 0x0e01 of
46 the maker notes of NEF images.
47 },
48 # 0x007ddc9d contains contrast information
49 0x008ae85e => {
50 Name => 'LCHEditor',
51 Writable => 'int8u',
52 PrintConv => \%offOn,
53 },
54 0x0c89224b => {
55 Name => 'ColorAberrationControl',
56 Writable => 'int8u',
57 PrintConv => \%offOn,
58 },
59 0x116fea21 => {
60 Name => 'HighlightData',
61 SubDirectory => {
62 TagTable => 'Image::ExifTool::NikonCapture::HighlightData',
63 },
64 },
65 0x2175eb78 => {
66 Name => 'D-LightingHQ',
67 Writable => 'int8u',
68 PrintConv => \%offOn,
69 },
70 0x2fc08431 => {
71 Name => 'StraightenAngle',
72 Writable => 'double',
73 },
74 0x374233e0 => {
75 Name => 'CropData',
76 SubDirectory => {
77 TagTable => 'Image::ExifTool::NikonCapture::CropData',
78 },
79 },
80 0x39c456ac => {
81 Name => 'PictureCtrl',
82 SubDirectory => {
83 TagTable => 'Image::ExifTool::NikonCapture::PictureCtrl',
84 },
85 },
86 0x3cfc73c6 => {
87 Name => 'RedEyeData',
88 SubDirectory => {
89 TagTable => 'Image::ExifTool::NikonCapture::RedEyeData',
90 },
91 },
92 0x3d136244 => {
93 Name => 'EditVersionName',
94 Writable => 'string', # (null terminated)
95 },
96 # 0x3e726567 added when I rotated by 90 degrees
97 0x416391c6 => {
98 Name => 'QuickFix',
99 Writable => 'int8u',
100 PrintConv => \%offOn,
101 },
102 0x56a54260 => {
103 Name => 'Exposure',
104 SubDirectory => {
105 TagTable => 'Image::ExifTool::NikonCapture::Exposure',
106 },
107 },
108 0x5f0e7d23 => {
109 Name => 'ColorBooster',
110 Writable => 'int8u',
111 PrintConv => \%offOn,
112 },
113 0x6a6e36b6 => {
114 Name => 'D-LightingHQSelected',
115 Writable => 'int8u',
116 PrintConv => \%noYes,
117 },
118 0x753dcbc0 => {
119 Name => 'NoiseReduction',
120 Writable => 'int8u',
121 PrintConv => \%offOn,
122 },
123 0x76a43200 => {
124 Name => 'UnsharpMask',
125 Writable => 'int8u',
126 PrintConv => \%offOn,
127 },
128 0x76a43201 => {
129 Name => 'Curves',
130 Writable => 'int8u',
131 PrintConv => \%offOn,
132 },
133 0x76a43202 => {
134 Name => 'ColorBalanceAdj',
135 Writable => 'int8u',
136 PrintConv => \%offOn,
137 },
138 0x76a43203 => {
139 Name => 'AdvancedRaw',
140 Writable => 'int8u',
141 PrintConv => \%offOn,
142 },
143 0x76a43204 => {
144 Name => 'WhiteBalanceAdj',
145 Writable => 'int8u',
146 PrintConv => \%offOn,
147 },
148 0x76a43205 => {
149 Name => 'VignetteControl',
150 Writable => 'int8u',
151 PrintConv => \%offOn,
152 },
153 0x76a43206 => {
154 Name => 'FlipHorizontal',
155 Writable => 'int8u',
156 PrintConv => \%noYes,
157 },
158 0x76a43207 => { # rotation angle in degrees
159 Name => 'Rotation',
160 Writable => 'int16u',
161 },
162 0x083a1a25 => {
163 Name => 'HistogramXML',
164 Writable => 'undef',
165 Binary => 1,
166 AdjustSize => 4, # patch Nikon bug
167 },
168 0x84589434 => {
169 Name => 'BrightnessData',
170 SubDirectory => {
171 TagTable => 'Image::ExifTool::NikonCapture::Brightness',
172 },
173 },
174 # 0x88f55e48 - related to QuickFix
175 0x890ff591 => {
176 Name => 'D-LightingHQData',
177 SubDirectory => {
178 TagTable => 'Image::ExifTool::NikonCapture::DLightingHQ',
179 },
180 },
181 0x926f13e0 => {
182 Name => 'NoiseReductionData',
183 SubDirectory => {
184 TagTable => 'Image::ExifTool::NikonCapture::NoiseReduction',
185 },
186 },
187 0x9ef5f6e0 => {
188 Name => 'IPTCData',
189 SubDirectory => {
190 TagTable => 'Image::ExifTool::IPTC::Main',
191 },
192 },
193 # 0xa7264a72 - related to QuickFix
194 0xab5eca5e => {
195 Name => 'PhotoEffects',
196 Writable => 'int8u',
197 PrintConv => \%offOn,
198 },
199 0xac6bd5c0 => {
200 Name => 'VignetteControlIntensity',
201 Writable => 'int16s',
202 },
203 0xb0384e1e => {
204 Name => 'PhotoEffectsData',
205 SubDirectory => {
206 TagTable => 'Image::ExifTool::NikonCapture::PhotoEffects',
207 },
208 },
209 0xb999a36f => {
210 Name => 'ColorBoostData',
211 SubDirectory => {
212 TagTable => 'Image::ExifTool::NikonCapture::ColorBoost',
213 },
214 },
215 0xbf3c6c20 => {
216 Name => 'WBAdjData',
217 SubDirectory => {
218 TagTable => 'Image::ExifTool::NikonCapture::WBAdjData',
219 },
220 },
221 0xce5554aa => {
222 Name => 'D-LightingHS',
223 Writable => 'int8u',
224 PrintConv => \%offOn,
225 },
226 0xe2173c47 => {
227 Name => 'PictureControl',
228 Writable => 'int8u',
229 PrintConv => \%offOn,
230 },
231 0xe37b4337 => {
232 Name => 'D-LightingHSData',
233 SubDirectory => {
234 TagTable => 'Image::ExifTool::NikonCapture::DLightingHS',
235 },
236 },
237 0xe42b5161 => {
238 Name => 'UnsharpData',
239 SubDirectory => {
240 TagTable => 'Image::ExifTool::NikonCapture::UnsharpData',
241 },
242 },
243 0xe9651831 => {
244 Name => 'PhotoEffectHistoryXML',
245 Binary => 1,
246 Writable => 'undef',
247 },
248 0xfe28a44f => {
249 Name => 'AutoRedEye',
250 Writable => 'int8u',
251 PrintConv => \%offOn, # (have seen a value of 28 here for older software?)
252 },
253 0xfe443a45 => {
254 Name => 'ImageDustOff',
255 Writable => 'int8u',
256 PrintConv => \%offOn,
257 },
258);
259
260%Image::ExifTool::NikonCapture::UnsharpData = (
261 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
262 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
263 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
264 WRITABLE => 1,
265 FORMAT => 'int8u',
266 FIRST_ENTRY => 0,
267 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
268 0 => 'UnsharpCount',
269 19 => { Name => 'Unsharp1Color', Format => 'int16u', PrintConv => \%unsharpColor },
270 23 => { Name => 'Unsharp1Intensity', Format => 'int16u' },
271 25 => { Name => 'Unsharp1HaloWidth', Format => 'int16u' },
272 27 => 'Unsharp1Threshold',
273 46 => { Name => 'Unsharp2Color', Format => 'int16u', PrintConv => \%unsharpColor },
274 50 => { Name => 'Unsharp2Intensity', Format => 'int16u' },
275 52 => { Name => 'Unsharp2HaloWidth', Format => 'int16u' },
276 54 => 'Unsharp2Threshold',
277 73 => { Name => 'Unsharp3Color', Format => 'int16u', PrintConv => \%unsharpColor },
278 77 => { Name => 'Unsharp3Intensity', Format => 'int16u' },
279 79 => { Name => 'Unsharp3HaloWidth', Format => 'int16u' },
280 81 => 'Unsharp3Threshold',
281 100 => { Name => 'Unsharp4Color', Format => 'int16u', PrintConv => \%unsharpColor },
282 104 => { Name => 'Unsharp4Intensity', Format => 'int16u' },
283 106 => { Name => 'Unsharp4HaloWidth', Format => 'int16u' },
284 108 => 'Unsharp4Threshold',
285 # there could be more, but I grow bored of this... :P
286);
287
288%Image::ExifTool::NikonCapture::DLightingHS = (
289 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
290 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
291 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
292 WRITABLE => 1,
293 FORMAT => 'int32u',
294 FIRST_ENTRY => 0,
295 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
296 0 => 'D-LightingHSAdjustment',
297 1 => 'D-LightingHSColorBoost',
298);
299
300%Image::ExifTool::NikonCapture::DLightingHQ = (
301 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
302 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
303 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
304 WRITABLE => 1,
305 FORMAT => 'int32u',
306 FIRST_ENTRY => 0,
307 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
308 0 => 'D-LightingHQShadow',
309 1 => 'D-LightingHQHighlight',
310 2 => 'D-LightingHQColorBoost',
311);
312
313%Image::ExifTool::NikonCapture::ColorBoost = (
314 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
315 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
316 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
317 WRITABLE => 1,
318 FORMAT => 'int8u',
319 FIRST_ENTRY => 0,
320 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
321 0 => {
322 Name => 'ColorBoostType',
323 PrintConv => {
324 0 => 'Nature',
325 1 => 'People',
326 },
327 },
328 1 => {
329 Name => 'ColorBoostLevel',
330 Format => 'int32u',
331 },
332);
333
334%Image::ExifTool::NikonCapture::WBAdjData = (
335 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
336 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
337 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
338 WRITABLE => 1,
339 FORMAT => 'int8u',
340 FIRST_ENTRY => 0,
341 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
342 0x00 => {
343 Name => 'WBAdjRedBalance',
344 Format => 'double',
345 },
346 0x08 => {
347 Name => 'WBAdjBlueBalance',
348 Format => 'double',
349 },
350 0x10 => {
351 Name => 'WBAdjMode',
352 PrintConv => {
353 1 => 'Use Gray Point',
354 2 => 'Recorded Value',
355 3 => 'Use Temperature',
356 4 => 'Calculate Automatically',
357 5 => 'Auto2', #IB
358 6 => 'Underwater', #IB
359 7 => 'Auto1',
360 },
361 },
362 0x14 => { #IB
363 Name => 'WBAdjLighting',
364 Format => 'int16u',
365 PrintHex => 1,
366 PrintConv => {
367 0x000 => 'None',
368 0x100 => 'Incandescent',
369 0x200 => 'Daylight (direct sunlight)',
370 0x201 => 'Daylight (shade)',
371 0x202 => 'Daylight (cloudy)',
372 0x300 => 'Standard Fluorescent (warm white)',
373 0x301 => 'Standard Fluorescent (3700K)',
374 0x302 => 'Standard Fluorescent (cool white)',
375 0x303 => 'Standard Fluorescent (5000K)',
376 0x304 => 'Standard Fluorescent (daylight)',
377 0x305 => 'Standard Fluorescent (high temperature mercury vapor)',
378 0x400 => 'High Color Rendering Fluorescent (warm white)',
379 0x401 => 'High Color Rendering Fluorescent (3700K)',
380 0x402 => 'High Color Rendering Fluorescent (cool white)',
381 0x403 => 'High Color Rendering Fluorescent (5000K)',
382 0x404 => 'High Color Rendering Fluorescent (daylight)',
383 0x500 => 'Flash',
384 0x501 => 'Flash (FL-G1 filter)',
385 0x502 => 'Flash (FL-G2 filter)',
386 0x503 => 'Flash (TN-A1 filter)',
387 0x504 => 'Flash (TN-A2 filter)',
388 0x600 => 'Sodium Vapor Lamps',
389 # 0x1002 => seen for WBAdjMode modes of Underwater and Calculate Automatically
390 },
391 },
392 0x18 => {
393 Name => 'WBAdjTemperature',
394 Format => 'int16u',
395 },
396 0x25 => {
397 Name => 'WBAdjTint',
398 Format => 'int32s',
399 },
400);
401
402%Image::ExifTool::NikonCapture::PhotoEffects = (
403 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
404 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
405 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
406 WRITABLE => 1,
407 FORMAT => 'int8u',
408 FIRST_ENTRY => 0,
409 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
410 0 => {
411 Name => 'PhotoEffectsType',
412 PrintConv => {
413 0 => 'None',
414 1 => 'B&W',
415 2 => 'Sepia',
416 3 => 'Tinted',
417 },
418 },
419 4 => {
420 Name => 'PhotoEffectsRed',
421 Format => 'int16s',
422 },
423 6 => {
424 Name => 'PhotoEffectsGreen',
425 Format => 'int16s',
426 },
427 8 => {
428 Name => 'PhotoEffectsBlue',
429 Format => 'int16s',
430 },
431);
432
433%Image::ExifTool::NikonCapture::Brightness = (
434 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
435 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
436 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
437 WRITABLE => 1,
438 FORMAT => 'int8u',
439 FIRST_ENTRY => 0,
440 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
441 0 => {
442 Name => 'BrightnessAdj',
443 Format => 'double',
444 ValueConv => '$val * 50',
445 ValueConvInv => '$val / 50',
446 },
447 8 => {
448 Name => 'EnhanceDarkTones',
449 PrintConv => \%offOn,
450 },
451);
452
453%Image::ExifTool::NikonCapture::NoiseReduction = (
454 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
455 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
456 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
457 WRITABLE => 1,
458 FORMAT => 'int8u',
459 FIRST_ENTRY => 0,
460 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
461 0x04 => {
462 Name => 'EdgeNoiseReduction',
463 PrintConv => \%offOn,
464 },
465 0x05 => {
466 Name => 'ColorMoireReductionMode',
467 PrintConv => {
468 0 => 'Off',
469 1 => 'Low',
470 2 => 'Medium',
471 3 => 'High',
472 },
473 },
474 0x09 => {
475 Name => 'NoiseReductionIntensity',
476 Format => 'int32u',
477 },
478 0x0d => {
479 Name => 'NoiseReductionSharpness',
480 Format => 'int32u',
481 },
482 0x11 => {
483 Name => 'NoiseReductionMethod',
484 Format => 'int16u',
485 PrintConv => {
486 0 => 'Faster',
487 1 => 'Better Quality',
488 2 => 'Better Quality 2013',
489 },
490 },
491 0x15 => {
492 Name => 'ColorMoireReduction',
493 PrintConv => \%offOn,
494 },
495 0x17 => {
496 Name => 'NoiseReduction',
497 PrintConv => \%offOn,
498 },
499 0x18 => {
500 Name => 'ColorNoiseReductionIntensity',
501 Format => 'int32u',
502 },
503 0x1c => {
504 Name => 'ColorNoiseReductionSharpness',
505 Format => 'int32u',
506 },
507);
508
509%Image::ExifTool::NikonCapture::CropData = (
510 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
511 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
512 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
513 WRITABLE => 1,
514 FORMAT => 'int8u',
515 FIRST_ENTRY => 0,
516 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
517 0x1e => {
518 Name => 'CropLeft',
519 Format => 'double',
520 ValueConv => '$val / 2',
521 ValueConvInv => '$val * 2',
522 },
523 0x26 => {
524 Name => 'CropTop',
525 Format => 'double',
526 ValueConv => '$val / 2',
527 ValueConvInv => '$val * 2',
528 },
529 0x2e => {
530 Name => 'CropRight',
531 Format => 'double',
532 ValueConv => '$val / 2',
533 ValueConvInv => '$val * 2',
534 },
535 0x36 => {
536 Name => 'CropBottom',
537 Format => 'double',
538 ValueConv => '$val / 2',
539 ValueConvInv => '$val * 2',
540 },
541 0x8e => {
542 Name => 'CropOutputWidthInches',
543 Format => 'double',
544 },
545 0x96 => {
546 Name => 'CropOutputHeightInches',
547 Format => 'double',
548 },
549 0x9e => {
550 Name => 'CropScaledResolution',
551 Format => 'double',
552 },
553 0xae => {
554 Name => 'CropSourceResolution',
555 Format => 'double',
556 ValueConv => '$val / 2',
557 ValueConvInv => '$val * 2',
558 },
559 0xb6 => {
560 Name => 'CropOutputResolution',
561 Format => 'double',
562 },
563 0xbe => {
564 Name => 'CropOutputScale',
565 Format => 'double',
566 },
567 0xc6 => {
568 Name => 'CropOutputWidth',
569 Format => 'double',
570 },
571 0xce => {
572 Name => 'CropOutputHeight',
573 Format => 'double',
574 },
575 0xd6 => {
576 Name => 'CropOutputPixels',
577 Format => 'double',
578 },
579);
580
581%Image::ExifTool::NikonCapture::PictureCtrl = (
582 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
583 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
584 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
585 WRITABLE => 1,
586 FORMAT => 'int8u',
587 FIRST_ENTRY => 0,
588 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
589 0x00 => {
590 Name => 'PictureControlActive',
591 PrintConv => \%offOn,
592 },
593 0x13 => {
594 Name => 'PictureControlMode',
595 Format => 'string[16]',
596 },
597 # 0x29 changes with Hue and Sharpening
598 0x2a => {
599 Name => 'QuickAdjust',
600 ValueConv => '$val - 128',
601 ValueConvInv => '$val + 128',
602 },
603 0x2b => {
604 Name => 'SharpeningAdj',
605 ValueConv => '$val ? $val - 128 : "Auto"',
606 ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
607 },
608 0x2c => {
609 Name => 'ContrastAdj',
610 ValueConv => '$val ? $val - 128 : "Auto"',
611 ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
612 },
613 0x2d => {
614 Name => 'BrightnessAdj',
615 ValueConv => '$val ? $val - 128 : "Auto"', # no "Auto" mode (yet) for this setting
616 ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
617 },
618 0x2e => {
619 Name => 'SaturationAdj',
620 ValueConv => '$val ? $val - 128 : "Auto"',
621 ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
622 },
623 0x2f => {
624 Name => 'HueAdj',
625 ValueConv => '$val - 128',
626 ValueConvInv => '$val + 128',
627 },
628 # 0x37 changed from 0 to 2 when Picture Control is enabled (and no active DLighting)
629);
630
631%Image::ExifTool::NikonCapture::RedEyeData = (
632 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
633 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
634 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
635 WRITABLE => 1,
636 FORMAT => 'int8u',
637 FIRST_ENTRY => 0,
638 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
639 0 => {
640 Name => 'RedEyeCorrection',
641 PrintConv => {
642 0 => 'Off',
643 1 => 'Automatic',
644 2 => 'Click on Eyes',
645 },
646 },
647);
648
649%Image::ExifTool::NikonCapture::Exposure = (
650 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
651 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
652 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
653 WRITABLE => 1,
654 FORMAT => 'int8u',
655 FIRST_ENTRY => 0,
656 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
657 0x00 => {
658 Name => 'ExposureAdj',
659 Format => 'int16s',
660 ValueConv => '$val / 100',
661 ValueConvInv => '$val * 100',
662 },
663 0x12 => {
664 Name => 'ExposureAdj2',
665 Format => 'double',
666 PrintConv => 'sprintf("%.4f", $val)',
667 PrintConvInv => '$val',
668 },
669 0x24 => {
670 Name => 'ActiveD-Lighting',
671 PrintConv => \%offOn,
672 },
673 0x25 => {
674 Name => 'ActiveD-LightingMode',
675 PrintConv => {
676 0 => 'Unchanged',
677 1 => 'Off',
678 2 => 'Low',
679 3 => 'Normal',
680 4 => 'High',
681 6 => 'Extra High',
682 7 => 'Extra High 1',
683 8 => 'Extra High 2',
684 },
685 },
686);
687
688%Image::ExifTool::NikonCapture::HighlightData = (
689 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
690 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
691 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
692 WRITABLE => 1,
693 FORMAT => 'int8s',
694 FIRST_ENTRY => 0,
695 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
696 0 => 'ShadowProtection',
697 1 => 'SaturationAdj',
698 6 => 'HighlightProtection',
699);
700
701#------------------------------------------------------------------------------
702# write Nikon Capture data (ref 1)
703# Inputs: 0) ExifTool object reference, 1) reference to directory information
704# 2) pointer to tag table
705# Returns: 1 on success
706sub WriteNikonCapture($$$)
707{
708 my ($et, $dirInfo, $tagTablePtr) = @_;
709 $et or return 1; # allow dummy access to autoload this package
710
711 # no need to edit this information unless necessary
712 unless ($$et{EDIT_DIRS}{MakerNotes} or $$et{EDIT_DIRS}{IPTC}) {
713 return undef;
714 }
715 my $dataPt = $$dirInfo{DataPt};
716 my $dirStart = $$dirInfo{DirStart};
717 my $dirLen = $$dirInfo{DirLen};
718 if ($dirLen < 22) {
719 $et->Warn('Short Nikon Capture Data',1);
720 return undef;
721 }
722 # make sure the capture data is properly contained
723 SetByteOrder('II');
724 my $tagID = Get32u($dataPt, $dirStart);
725 # sometimes size includes 18 header bytes, and other times it doesn't (eg. ViewNX 2.1.1)
726 my $size = Get32u($dataPt, $dirStart + 18);
727 my $pad = $dirLen - $size - 18;
728 unless ($tagID == 0x7a86a940 and ($pad >= 0 or $pad == -18)) {
729 $et->Warn('Unrecognized Nikon Capture Data header');
730 return undef;
731 }
732 # determine if there is any data after this block
733 if ($pad > 0) {
734 $pad = substr($$dataPt, $dirStart + 18 + $size, $pad);
735 $dirLen = $size + 18;
736 } else {
737 $pad = '';
738 }
739 my $outBuff = '';
740 my $pos;
741 my $newTags = $et->GetNewTagInfoHash($tagTablePtr);
742 my $dirEnd = $dirStart + $dirLen;
743
744 # loop through all entries in the Nikon Capture data
745 for ($pos=$dirStart+22; $pos+22<$dirEnd; $pos+=22+$size) {
746 $tagID = Get32u($dataPt, $pos);
747 $size = Get32u($dataPt, $pos + 18) - 4;
748 last if $size < 0 or $pos + 22 + $size > $dirEnd;
749 my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID);
750 if ($tagInfo) {
751 my $newVal;
752 if ($$tagInfo{SubDirectory}) {
753 # rewrite the subdirectory
754 my %subdirInfo = (
755 DataPt => $dataPt,
756 DirStart => $pos + 22,
757 DirLen => $size,
758 );
759 my $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable});
760 # ignore minor errors in IPTC since there is typically trailing garbage
761 my $oldSetting = $et->Options('IgnoreMinorErrors');
762 $$tagInfo{Name} =~ /IPTC/ and $et->Options(IgnoreMinorErrors => 1);
763 # rewrite the directory
764 $newVal = $et->WriteDirectory(\%subdirInfo, $subTable);
765 # restore our original options
766 $et->Options(IgnoreMinorErrors => $oldSetting);
767 } elsif ($$newTags{$tagID}) {
768 # get new value for this tag if we are writing it
769 my $format = $$tagInfo{Format} || $$tagInfo{Writable};
770 my $oldVal = ReadValue($dataPt,$pos+22,$format,1,$size);
771 my $nvHash = $et->GetNewValueHash($tagInfo);
772 if ($et->IsOverwriting($nvHash, $oldVal)) {
773 my $val = $et->GetNewValue($tagInfo);
774 $newVal = WriteValue($val, $$tagInfo{Writable}) if defined $val;
775 if (defined $newVal and length $newVal) {
776 ++$$et{CHANGED};
777 } else {
778 undef $newVal;
779 $et->Warn("Can't delete $$tagInfo{Name}");
780 }
781 }
782 }
783 if (defined $newVal) {
784 next unless length $newVal; # don't write zero length information
785 # write the new value
786 $outBuff .= substr($$dataPt, $pos, 18);
787 $outBuff .= Set32u(length($newVal) + 4);
788 $outBuff .= $newVal;
789 next;
790 }
791 }
792 # rewrite the existing information
793 $outBuff .= substr($$dataPt, $pos, 22 + $size);
794 }
795 unless ($pos == $dirEnd) {
796 if ($pos == $dirEnd - 4) {
797 # it seems that sometimes (NX2) the main block size is wrong by 4 bytes
798 # (did they forget to include the size word?)
799 $outBuff .= substr($$dataPt, $pos, 4);
800 } else {
801 $et->Warn('Nikon Capture Data improperly terminated',1);
802 return undef;
803 }
804 }
805 # add the header and return the new directory
806 return substr($$dataPt, $dirStart, 18) .
807 Set32u(length($outBuff) + 4) .
808 $outBuff . $pad;
809}
810
811#------------------------------------------------------------------------------
812# process Nikon Capture data (ref 1)
813# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
814# Returns: 1 on success
815sub ProcessNikonCaptureEditVersions($$$)
816{
817 my ($et, $dirInfo, $tagTablePtr) = @_;
818 my $dataPt = $$dirInfo{DataPt};
819 my $dirStart = $$dirInfo{DirStart};
820 my $dirLen = $$dirInfo{DirLen};
821 my $dirEnd = $dirStart + $dirLen;
822 my $verbose = $et->Options('Verbose');
823 SetByteOrder('II');
824 return 0 unless $dirLen > 4;
825 my $num = Get32u($dataPt, $dirStart);
826 my $pos = $dirStart + 4;
827 $verbose and $et->VerboseDir('NikonCaptureEditVersions', $num);
828 while ($num) {
829 last if $pos + 4 > $dirEnd;
830 my $len = Get32u($dataPt, $pos);
831 last if $pos + $len + 4 > $dirEnd;
832 my %dirInfo = (
833 DirName => 'NikonCapture',
834 Parent => 'NikonCaptureEditVersions',
835 DataPt => $dataPt,
836 DirStart => $pos + 4,
837 DirLen => $len,
838 );
839 $$et{DOC_NUM} = ++$$et{DOC_COUNT};
840 $et->ProcessDirectory(\%dirInfo, $tagTablePtr);
841 --$num;
842 $pos += $len + 4;
843 }
844 delete $$et{DOC_NUM};
845 return 1;
846}
847
848#------------------------------------------------------------------------------
849# process Nikon Capture data (ref 1)
850# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
851# Returns: 1 on success
852sub ProcessNikonCapture($$$)
853{
854 my ($et, $dirInfo, $tagTablePtr) = @_;
855 my $dataPt = $$dirInfo{DataPt};
856 my $dirStart = $$dirInfo{DirStart};
857 my $dirLen = $$dirInfo{DirLen};
858 my $dirEnd = $dirStart + $dirLen;
859 my $verbose = $et->Options('Verbose');
860 my $success = 0;
861 SetByteOrder('II');
862 $verbose and $et->VerboseDir('NikonCapture', 0, $dirLen);
863 my $pos;
864 for ($pos=$dirStart+22; $pos+22<$dirEnd; ) {
865 my $tagID = Get32u($dataPt, $pos);
866 my $size = Get32u($dataPt, $pos + 18) - 4;
867 $pos += 22;
868 last if $size < 0 or $pos + $size > $dirEnd;
869 my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID);
870 if ($tagInfo or $verbose) {
871 my ($format, $value);
872 # (note that Writable will be 0 for Unknown tags)
873 $tagInfo and $format = ($$tagInfo{Format} || $$tagInfo{Writable});
874 # generate a reasonable default format type for short values
875 if (not $format and ($size == 1 or $size == 2 or $size == 4)) {
876 $format = 'int' . ($size * 8) . 'u';
877 }
878 if ($format) {
879 my $count = 1;
880 if ($format eq 'string' or $format eq 'undef') {
881 # patch Nikon bug in size of some values (HistogramXML)
882 $size += $$tagInfo{AdjustSize} if $tagInfo and $$tagInfo{AdjustSize};
883 $count = $size;
884 }
885 $value = ReadValue($dataPt,$pos,$format,$count,$size);
886 } elsif ($size == 1) {
887 $value = substr($$dataPt, $pos, $size);
888 }
889 $et->HandleTag($tagTablePtr, $tagID, $value,
890 DataPt => $dataPt,
891 DataPos => $$dirInfo{DataPos},
892 Base => $$dirInfo{Base},
893 Start => $pos,
894 Size => $size,
895 ) and $success = 1;
896 }
897 $pos += $size;
898 }
899 return $success;
900}
901
9021; # end
903
904__END__
905
906=head1 NAME
907
908Image::ExifTool::NikonCapture - Read/write Nikon Capture information
909
910=head1 SYNOPSIS
911
912This module is loaded automatically by Image::ExifTool when required.
913
914=head1 DESCRIPTION
915
916This module contains routines to read and write Nikon Capture information in
917the maker notes of NEF images.
918
919=head1 AUTHOR
920
921Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
922
923This library is free software; you can redistribute it and/or modify it
924under the same terms as Perl itself.
925
926=head1 REFERENCES
927
928=over 4
929
930=item L<http://www.cybercom.net/~dcoffin/dcraw/>
931
932=back
933
934=head1 SEE ALSO
935
936L<Image::ExifTool::TagNames/NikonCapture Tags>,
937L<Image::ExifTool::TagNames/Nikon Tags>,
938L<Image::ExifTool(3pm)|Image::ExifTool>
939
940=cut
Note: See TracBrowser for help on using the repository browser.