source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/NikonCapture.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

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