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 |
|
---|
14 | package Image::ExifTool::NikonCapture;
|
---|
15 |
|
---|
16 | use strict;
|
---|
17 | use vars qw($VERSION);
|
---|
18 | use Image::ExifTool qw(:DataAccess :Utils);
|
---|
19 | use Image::ExifTool::Exif;
|
---|
20 |
|
---|
21 | $VERSION = '1.14';
|
---|
22 |
|
---|
23 | sub ProcessNikonCapture($$$);
|
---|
24 |
|
---|
25 | # common print conversions
|
---|
26 | my %offOn = ( 0 => 'Off', 1 => 'On' );
|
---|
27 | my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
---|
28 | my %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
|
---|
706 | sub 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
|
---|
815 | sub 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
|
---|
852 | sub 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 |
|
---|
902 | 1; # end
|
---|
903 |
|
---|
904 | __END__
|
---|
905 |
|
---|
906 | =head1 NAME
|
---|
907 |
|
---|
908 | Image::ExifTool::NikonCapture - Read/write Nikon Capture information
|
---|
909 |
|
---|
910 | =head1 SYNOPSIS
|
---|
911 |
|
---|
912 | This module is loaded automatically by Image::ExifTool when required.
|
---|
913 |
|
---|
914 | =head1 DESCRIPTION
|
---|
915 |
|
---|
916 | This module contains routines to read and write Nikon Capture information in
|
---|
917 | the maker notes of NEF images.
|
---|
918 |
|
---|
919 | =head1 AUTHOR
|
---|
920 |
|
---|
921 | Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
|
---|
922 |
|
---|
923 | This library is free software; you can redistribute it and/or modify it
|
---|
924 | under 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 |
|
---|
936 | L<Image::ExifTool::TagNames/NikonCapture Tags>,
|
---|
937 | L<Image::ExifTool::TagNames/Nikon Tags>,
|
---|
938 | L<Image::ExifTool(3pm)|Image::ExifTool>
|
---|
939 |
|
---|
940 | =cut
|
---|