exiftool_vendored 12.56.0 → 12.58.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +35 -2
  3. data/bin/META.json +1 -1
  4. data/bin/META.yml +1 -1
  5. data/bin/README +2 -2
  6. data/bin/config_files/rotate_regions.config +1 -1
  7. data/bin/exiftool +95 -47
  8. data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  9. data/bin/lib/Image/ExifTool/APE.pm +2 -2
  10. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +19 -15
  11. data/bin/lib/Image/ExifTool/Canon.pm +26 -6
  12. data/bin/lib/Image/ExifTool/DJI.pm +28 -2
  13. data/bin/lib/Image/ExifTool/Exif.pm +24 -5
  14. data/bin/lib/Image/ExifTool/FlashPix.pm +6 -2
  15. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
  16. data/bin/lib/Image/ExifTool/GPS.pm +7 -2
  17. data/bin/lib/Image/ExifTool/JPEG.pm +14 -2
  18. data/bin/lib/Image/ExifTool/Jpeg2000.pm +5 -5
  19. data/bin/lib/Image/ExifTool/LNK.pm +5 -4
  20. data/bin/lib/Image/ExifTool/MIE.pm +3 -3
  21. data/bin/lib/Image/ExifTool/MPEG.pm +2 -2
  22. data/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
  23. data/bin/lib/Image/ExifTool/Minolta.pm +6 -7
  24. data/bin/lib/Image/ExifTool/Nikon.pm +998 -903
  25. data/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  26. data/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  27. data/bin/lib/Image/ExifTool/Olympus.pm +3 -1
  28. data/bin/lib/Image/ExifTool/Pentax.pm +8 -5
  29. data/bin/lib/Image/ExifTool/Photoshop.pm +38 -7
  30. data/bin/lib/Image/ExifTool/QuickTime.pm +23 -7
  31. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +3 -1
  32. data/bin/lib/Image/ExifTool/README +19 -2
  33. data/bin/lib/Image/ExifTool/RIFF.pm +3 -3
  34. data/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
  35. data/bin/lib/Image/ExifTool/Sigma.pm +5 -4
  36. data/bin/lib/Image/ExifTool/Sony.pm +23 -1
  37. data/bin/lib/Image/ExifTool/TagLookup.pm +4670 -4628
  38. data/bin/lib/Image/ExifTool/TagNames.pod +261 -89
  39. data/bin/lib/Image/ExifTool/Validate.pm +5 -5
  40. data/bin/lib/Image/ExifTool/WriteExif.pl +42 -0
  41. data/bin/lib/Image/ExifTool/Writer.pl +39 -17
  42. data/bin/lib/Image/ExifTool/XMP.pm +2 -2
  43. data/bin/lib/Image/ExifTool.pm +94 -33
  44. data/bin/lib/Image/ExifTool.pod +4 -4
  45. data/bin/perl-Image-ExifTool.spec +1 -1
  46. data/lib/exiftool_vendored/version.rb +1 -1
  47. metadata +2 -2
@@ -64,11 +64,12 @@ use Image::ExifTool::Exif;
64
64
  use Image::ExifTool::GPS;
65
65
  use Image::ExifTool::XMP;
66
66
 
67
- $VERSION = '4.18';
67
+ $VERSION = '4.20';
68
68
 
69
69
  sub LensIDConv($$$);
70
70
  sub ProcessNikonAVI($$$);
71
71
  sub ProcessNikonMOV($$$);
72
+ sub ProcessNikonEncrypted($$$);
72
73
  sub FormatString($);
73
74
  sub ProcessNikonCaptureEditVersions($$$);
74
75
  sub PrintAFPoints($$);
@@ -83,9 +84,8 @@ sub GetAFPointGrid($$;$);
83
84
  The Nikon LensID is constructed as a Composite tag from the raw hex values
84
85
  of 8 other tags: LensIDNumber, LensFStops, MinFocalLength, MaxFocalLength,
85
86
  MaxApertureAtMinFocal, MaxApertureAtMaxFocal, MCUVersion and LensType, in
86
- that order. Multiple lenses with the same LensID are differentiated by
87
- decimal values in the list below. The user-defined "Lenses" list may be
88
- used to specify the lens for ExifTool to choose in these cases (see the
87
+ that order. The user-defined "Lenses" list may be used to specify the lens
88
+ for ExifTool to choose in these cases (see the
89
89
  L<sample config file|../config.html> for details).
90
90
  },
91
91
  OTHER => \&LensIDConv,
@@ -880,6 +880,12 @@ my %bracketProgramZ9 = (
880
880
  9 => '9F',
881
881
  );
882
882
 
883
+ my %dynamicAfAreaModesZ9 = (
884
+ 0 => 'Small',
885
+ 1 => 'Medium',
886
+ 2 => 'Large',
887
+ );
888
+
883
889
  my %flashControlModeZ7 = (
884
890
  0 => 'TTL',
885
891
  1 => 'Auto External Flash',
@@ -1112,6 +1118,14 @@ my %offLowNormalHighZ7 = (
1112
1118
  3 => 'High',
1113
1119
  );
1114
1120
 
1121
+ my %releaseModeZ7 = (
1122
+ 0 => 'Continuous Low',
1123
+ 1 => 'Continuous High',
1124
+ 2 => 'Continuous High (Extended)',
1125
+ 4 => 'Timer',
1126
+ 5 => 'Single Frame',
1127
+ );
1128
+
1115
1129
  my %secondarySlotFunctionZ9 = (
1116
1130
  0 => 'Overflow',
1117
1131
  1 => 'Backup',
@@ -1509,9 +1523,7 @@ my %base64coord = (
1509
1523
  0x0006 => { Name => 'Sharpness', Writable => 'string' },
1510
1524
  0x0007 => {
1511
1525
  Name => 'FocusMode',
1512
- DataMember => 'FocusMode',
1513
1526
  Writable => 'string',
1514
- RawConv => '$$self{FocusMode} = $val',
1515
1527
  },
1516
1528
  # FlashSetting (better named FlashSyncMode, ref 28) values:
1517
1529
  # "Normal", "Slow", "Rear Slow", "RED-EYE", "RED-EYE SLOW"
@@ -1812,6 +1824,7 @@ my %base64coord = (
1812
1824
  Name => 'ShutterMode',
1813
1825
  Writable => 'int16u',
1814
1826
  RawConv => '$$self{ShutterMode} = $val',
1827
+ DataMember => 'ShutterMode',
1815
1828
  PrintConv => {
1816
1829
  0 => 'Mechanical',
1817
1830
  16 => 'Electronic',
@@ -2059,7 +2072,6 @@ my %base64coord = (
2059
2072
  SubDirectory => {
2060
2073
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD40',
2061
2074
  DecryptStart => 4,
2062
- DecryptLen => 748,
2063
2075
  ByteOrder => 'BigEndian',
2064
2076
  },
2065
2077
  },
@@ -2069,7 +2081,6 @@ my %base64coord = (
2069
2081
  SubDirectory => {
2070
2082
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD80',
2071
2083
  DecryptStart => 4,
2072
- DecryptLen => 765,
2073
2084
  # (Capture NX can change the makernote byte order, but this stays big-endian)
2074
2085
  ByteOrder => 'BigEndian',
2075
2086
  },
@@ -2080,7 +2091,6 @@ my %base64coord = (
2080
2091
  SubDirectory => {
2081
2092
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD90',
2082
2093
  DecryptStart => 4,
2083
- DecryptLen => 0x398,
2084
2094
  ByteOrder => 'BigEndian',
2085
2095
  },
2086
2096
  },
@@ -2090,7 +2100,6 @@ my %base64coord = (
2090
2100
  SubDirectory => {
2091
2101
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3a',
2092
2102
  DecryptStart => 4,
2093
- DecryptLen => 0x318,
2094
2103
  ByteOrder => 'BigEndian',
2095
2104
  },
2096
2105
  },
@@ -2100,7 +2109,6 @@ my %base64coord = (
2100
2109
  SubDirectory => {
2101
2110
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3b',
2102
2111
  DecryptStart => 4,
2103
- DecryptLen => 0x321,
2104
2112
  ByteOrder => 'BigEndian',
2105
2113
  },
2106
2114
  },
@@ -2110,7 +2118,6 @@ my %base64coord = (
2110
2118
  SubDirectory => {
2111
2119
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3X',
2112
2120
  DecryptStart => 4,
2113
- DecryptLen => 0x323,
2114
2121
  ByteOrder => 'BigEndian',
2115
2122
  },
2116
2123
  },
@@ -2120,7 +2127,6 @@ my %base64coord = (
2120
2127
  SubDirectory => {
2121
2128
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3S',
2122
2129
  DecryptStart => 4,
2123
- DecryptLen => 0x2e9,
2124
2130
  ByteOrder => 'BigEndian',
2125
2131
  },
2126
2132
  },
@@ -2131,7 +2137,6 @@ my %base64coord = (
2131
2137
  SubDirectory => {
2132
2138
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD300a',
2133
2139
  DecryptStart => 4,
2134
- DecryptLen => 813,
2135
2140
  ByteOrder => 'BigEndian',
2136
2141
  },
2137
2142
  },
@@ -2142,7 +2147,6 @@ my %base64coord = (
2142
2147
  SubDirectory => {
2143
2148
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD300b',
2144
2149
  DecryptStart => 4,
2145
- DecryptLen => 825,
2146
2150
  ByteOrder => 'BigEndian',
2147
2151
  },
2148
2152
  },
@@ -2153,7 +2157,6 @@ my %base64coord = (
2153
2157
  SubDirectory => {
2154
2158
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD300S',
2155
2159
  DecryptStart => 4,
2156
- DecryptLen => 827,
2157
2160
  ByteOrder => 'BigEndian',
2158
2161
  },
2159
2162
  },
@@ -2164,17 +2167,33 @@ my %base64coord = (
2164
2167
  SubDirectory => {
2165
2168
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD700',
2166
2169
  DecryptStart => 4,
2167
- DecryptLen => 0x358,
2168
2170
  ByteOrder => 'BigEndian',
2169
2171
  },
2170
2172
  },
2173
+ { #28 (D780 firmware version 1.00)
2174
+ Condition => '$$valPt =~ /^0245/',
2175
+ Name => 'ShotInfoD780',
2176
+ SubDirectory => {
2177
+ TagTable => 'Image::ExifTool::Nikon::ShotInfoD780',
2178
+ DecryptStart => 4,
2179
+ ByteOrder => 'LittleEndian',
2180
+ },
2181
+ },
2182
+ { #28 (D7500 firmware version 1.00h)
2183
+ Condition => '$$valPt =~ /^0242/',
2184
+ Name => 'ShotInfoD7500',
2185
+ SubDirectory => {
2186
+ TagTable => 'Image::ExifTool::Nikon::ShotInfoD7500',
2187
+ DecryptStart => 4,
2188
+ ByteOrder => 'LittleEndian',
2189
+ },
2190
+ },
2171
2191
  { #PH (D800 firmware 1.01a)
2172
2192
  Condition => '$$valPt =~ /^0222/',
2173
2193
  Name => 'ShotInfoD800',
2174
2194
  SubDirectory => {
2175
2195
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD800',
2176
2196
  DecryptStart => 4,
2177
- DecryptLen => 0x720,
2178
2197
  ByteOrder => 'BigEndian',
2179
2198
  },
2180
2199
  },
@@ -2184,8 +2203,6 @@ my %base64coord = (
2184
2203
  SubDirectory => {
2185
2204
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD810',
2186
2205
  DecryptStart => 4,
2187
- DecryptLen => 0x36f4 + 12,
2188
- DecryptMore => 'Get32u(\$data, 0x84) + 12',
2189
2206
  ByteOrder => 'LittleEndian',
2190
2207
  },
2191
2208
  },
@@ -2195,8 +2212,6 @@ my %base64coord = (
2195
2212
  SubDirectory => {
2196
2213
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD850',
2197
2214
  DecryptStart => 4,
2198
- DecryptLen => 0x2efb + 12,
2199
- DecryptMore => 'Get32u(\$data, 0xa0) + 12',
2200
2215
  ByteOrder => 'LittleEndian',
2201
2216
  },
2202
2217
  },
@@ -2209,7 +2224,6 @@ my %base64coord = (
2209
2224
  SubDirectory => {
2210
2225
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD5000',
2211
2226
  DecryptStart => 4,
2212
- DecryptLen => 0x39a,
2213
2227
  ByteOrder => 'BigEndian',
2214
2228
  },
2215
2229
  },
@@ -2219,7 +2233,6 @@ my %base64coord = (
2219
2233
  SubDirectory => {
2220
2234
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD5100',
2221
2235
  DecryptStart => 4,
2222
- DecryptLen => 0x430,
2223
2236
  ByteOrder => 'BigEndian',
2224
2237
  },
2225
2238
  },
@@ -2229,7 +2242,6 @@ my %base64coord = (
2229
2242
  SubDirectory => {
2230
2243
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD5200',
2231
2244
  DecryptStart => 4,
2232
- DecryptLen => 0xd00,
2233
2245
  ByteOrder => 'BigEndian',
2234
2246
  },
2235
2247
  },
@@ -2239,7 +2251,6 @@ my %base64coord = (
2239
2251
  SubDirectory => {
2240
2252
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD7000',
2241
2253
  DecryptStart => 4,
2242
- DecryptLen => 0x448,
2243
2254
  ByteOrder => 'BigEndian',
2244
2255
  },
2245
2256
  },
@@ -2249,7 +2260,6 @@ my %base64coord = (
2249
2260
  SubDirectory => {
2250
2261
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD4',
2251
2262
  DecryptStart => 4,
2252
- DecryptLen => 0x789,
2253
2263
  ByteOrder => 'BigEndian',
2254
2264
  },
2255
2265
  },
@@ -2259,29 +2269,15 @@ my %base64coord = (
2259
2269
  SubDirectory => {
2260
2270
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD4S',
2261
2271
  DecryptStart => 4,
2262
- DecryptLen => 0x3697,
2263
- ByteOrder => 'LittleEndian',
2264
- },
2265
- },
2266
- { #28 (D5 firmware version 1.10a)
2267
- Condition => '$$valPt =~ /^0238/',
2268
- Name => 'ShotInfoD5',
2269
- SubDirectory => {
2270
- TagTable => 'Image::ExifTool::Nikon::ShotInfoD500',
2271
- DecryptStart => 4,
2272
- DecryptLen => 0x2c24 + 12,
2273
- DecryptMore => 'Get32u(\$data, 0xa8) + 0x2ea5 - 0x2c90',
2274
2272
  ByteOrder => 'LittleEndian',
2275
2273
  },
2276
2274
  },
2277
- { # (D500 firmware version 1.00)
2278
- Condition => '$$valPt =~ /^0239/',
2275
+ { #28 (D500 firmware version 1.00 and D5 firmware version 1.10a)
2276
+ Condition => '$$valPt =~ /^023[89]/',
2279
2277
  Name => 'ShotInfoD500',
2280
2278
  SubDirectory => {
2281
2279
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD500',
2282
2280
  DecryptStart => 4,
2283
- DecryptLen => 0x2cb2 + 4,
2284
- DecryptMore => 'Get32u(\$data, 0xa8) + 0x2ea5 - 0x2c90',
2285
2281
  ByteOrder => 'LittleEndian',
2286
2282
  },
2287
2283
  },
@@ -2291,7 +2287,6 @@ my %base64coord = (
2291
2287
  SubDirectory => {
2292
2288
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD6',
2293
2289
  DecryptStart => 4,
2294
- DecryptLen => 0xc292 + 720, # thru decoded parts of Offset 32
2295
2290
  ByteOrder => 'LittleEndian',
2296
2291
  },
2297
2292
  },
@@ -2301,7 +2296,6 @@ my %base64coord = (
2301
2296
  SubDirectory => {
2302
2297
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD610',
2303
2298
  DecryptStart => 4,
2304
- DecryptLen => 0x7ff,
2305
2299
  ByteOrder => 'BigEndian',
2306
2300
  },
2307
2301
  },
@@ -2312,8 +2306,6 @@ my %base64coord = (
2312
2306
  SubDirectory => {
2313
2307
  TagTable => 'Image::ExifTool::Nikon::ShotInfoZ7II',
2314
2308
  DecryptStart => 4,
2315
- # TODO: eventually set the length dynamically according to actual offsets!
2316
- DecryptLen => 0xd04e + 860, # thru decoded MenuSettingsZ7II
2317
2309
  ByteOrder => 'LittleEndian',
2318
2310
  },
2319
2311
  },
@@ -2323,8 +2315,6 @@ my %base64coord = (
2323
2315
  SubDirectory => {
2324
2316
  TagTable => 'Image::ExifTool::Nikon::ShotInfoZ9',
2325
2317
  DecryptStart => 4,
2326
- # TODO: eventually set the length dynamically according to actual offsets!
2327
- DecryptLen => 0xec4b + 2196, # decoded thru end of Offset26
2328
2318
  ByteOrder => 'LittleEndian',
2329
2319
  },
2330
2320
  },
@@ -2333,10 +2323,9 @@ my %base64coord = (
2333
2323
  Name => 'ShotInfo02xx',
2334
2324
  SubDirectory => {
2335
2325
  TagTable => 'Image::ExifTool::Nikon::ShotInfo',
2336
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2337
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2326
+ ProcessProc => \&ProcessNikonEncrypted,
2327
+ WriteProc => \&ProcessNikonEncrypted,
2338
2328
  DecryptStart => 4,
2339
- DecryptLen => 0x251,
2340
2329
  ByteOrder => 'BigEndian',
2341
2330
  },
2342
2331
  },
@@ -2400,11 +2389,10 @@ my %base64coord = (
2400
2389
  Name => 'ColorBalance0205',
2401
2390
  SubDirectory => {
2402
2391
  TagTable => 'Image::ExifTool::Nikon::ColorBalance2',
2403
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2404
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2392
+ ProcessProc => \&ProcessNikonEncrypted,
2393
+ WriteProc => \&ProcessNikonEncrypted,
2405
2394
  DecryptStart => 4,
2406
- DecryptLen => 22, # 284 bytes encrypted, but don't need to decrypt it all
2407
- DirOffset => 14,
2395
+ DirOffset => 14, # (start of directory relative to DecryptStart)
2408
2396
  },
2409
2397
  },
2410
2398
  { # (D3/D3X/D300/D700=0209,D300S=0212,D3S=0214)
@@ -2412,10 +2400,9 @@ my %base64coord = (
2412
2400
  Name => 'ColorBalance0209',
2413
2401
  SubDirectory => {
2414
2402
  TagTable => 'Image::ExifTool::Nikon::ColorBalance4',
2415
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2416
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2403
+ ProcessProc => \&ProcessNikonEncrypted,
2404
+ WriteProc => \&ProcessNikonEncrypted,
2417
2405
  DecryptStart => 284,
2418
- DecryptLen => 18, # 324 bytes encrypted, but don't need to decrypt it all
2419
2406
  DirOffset => 10,
2420
2407
  },
2421
2408
  },
@@ -2424,10 +2411,9 @@ my %base64coord = (
2424
2411
  Name => 'ColorBalance02',
2425
2412
  SubDirectory => {
2426
2413
  TagTable => 'Image::ExifTool::Nikon::ColorBalance2',
2427
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2428
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2414
+ ProcessProc => \&ProcessNikonEncrypted,
2415
+ WriteProc => \&ProcessNikonEncrypted,
2429
2416
  DecryptStart => 284,
2430
- DecryptLen => 14, # don't need to decrypt it all
2431
2417
  DirOffset => 6,
2432
2418
  },
2433
2419
  },
@@ -2436,10 +2422,9 @@ my %base64coord = (
2436
2422
  Name => 'ColorBalance0211',
2437
2423
  SubDirectory => {
2438
2424
  TagTable => 'Image::ExifTool::Nikon::ColorBalance4',
2439
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2440
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2425
+ ProcessProc => \&ProcessNikonEncrypted,
2426
+ WriteProc => \&ProcessNikonEncrypted,
2441
2427
  DecryptStart => 284,
2442
- DecryptLen => 24, # don't need to decrypt it all
2443
2428
  DirOffset => 16,
2444
2429
  },
2445
2430
  },
@@ -2448,10 +2433,9 @@ my %base64coord = (
2448
2433
  Name => 'ColorBalance0213',
2449
2434
  SubDirectory => {
2450
2435
  TagTable => 'Image::ExifTool::Nikon::ColorBalance2',
2451
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2452
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2436
+ ProcessProc => \&ProcessNikonEncrypted,
2437
+ WriteProc => \&ProcessNikonEncrypted,
2453
2438
  DecryptStart => 284,
2454
- DecryptLen => 18, # don't need to decrypt it all
2455
2439
  DirOffset => 10,
2456
2440
  },
2457
2441
  },
@@ -2460,10 +2444,9 @@ my %base64coord = (
2460
2444
  Name => 'ColorBalance0215',
2461
2445
  SubDirectory => {
2462
2446
  TagTable => 'Image::ExifTool::Nikon::ColorBalance4',
2463
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2464
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2447
+ ProcessProc => \&ProcessNikonEncrypted,
2448
+ WriteProc => \&ProcessNikonEncrypted,
2465
2449
  DecryptStart => 284,
2466
- DecryptLen => 12, # don't need to decrypt it all
2467
2450
  DirOffset => 4,
2468
2451
  },
2469
2452
  },
@@ -2472,9 +2455,9 @@ my %base64coord = (
2472
2455
  Condition => '$$valPt =~ /^0[26]/',
2473
2456
  SubDirectory => {
2474
2457
  TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown',
2475
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2458
+ ProcessProc => \&ProcessNikonEncrypted,
2459
+ WriteProc => \&ProcessNikonEncrypted, # (necessary to recrypt this if serial number changed)
2476
2460
  DecryptStart => 284,
2477
- DecryptLen => 10, # (arbitrary)
2478
2461
  },
2479
2462
  },
2480
2463
  { # (1J1/1J2/1V1=0400, 1V2=0401, 1J3/1S1=0402, 1AW1=0403, Z6/Z7=0800)
@@ -2482,9 +2465,9 @@ my %base64coord = (
2482
2465
  Condition => '$$valPt =~ /^0[48]/',
2483
2466
  SubDirectory => {
2484
2467
  TagTable => 'Image::ExifTool::Nikon::ColorBalanceUnknown',
2485
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2468
+ ProcessProc => \&ProcessNikonEncrypted,
2469
+ WriteProc => \&ProcessNikonEncrypted, # (necessary to recrypt this if serial number changed)
2486
2470
  DecryptStart => 4,
2487
- DecryptLen => 10, # (arbitrary)
2488
2471
  },
2489
2472
  },
2490
2473
  {
@@ -2513,8 +2496,8 @@ my %base64coord = (
2513
2496
  Name => 'LensData0201',
2514
2497
  SubDirectory => {
2515
2498
  TagTable => 'Image::ExifTool::Nikon::LensData01',
2516
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2517
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2499
+ ProcessProc => \&ProcessNikonEncrypted,
2500
+ WriteProc => \&ProcessNikonEncrypted,
2518
2501
  DecryptStart => 4,
2519
2502
  },
2520
2503
  },
@@ -2523,8 +2506,8 @@ my %base64coord = (
2523
2506
  Name => 'LensData0204',
2524
2507
  SubDirectory => {
2525
2508
  TagTable => 'Image::ExifTool::Nikon::LensData0204',
2526
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2527
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2509
+ ProcessProc => \&ProcessNikonEncrypted,
2510
+ WriteProc => \&ProcessNikonEncrypted,
2528
2511
  DecryptStart => 4,
2529
2512
  },
2530
2513
  },
@@ -2533,8 +2516,8 @@ my %base64coord = (
2533
2516
  Name => 'LensData0400',
2534
2517
  SubDirectory => {
2535
2518
  TagTable => 'Image::ExifTool::Nikon::LensData0400',
2536
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2537
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2519
+ ProcessProc => \&ProcessNikonEncrypted,
2520
+ WriteProc => \&ProcessNikonEncrypted,
2538
2521
  DecryptStart => 4,
2539
2522
  },
2540
2523
  },
@@ -2543,8 +2526,8 @@ my %base64coord = (
2543
2526
  Name => 'LensData0402',
2544
2527
  SubDirectory => {
2545
2528
  TagTable => 'Image::ExifTool::Nikon::LensData0402',
2546
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2547
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2529
+ ProcessProc => \&ProcessNikonEncrypted,
2530
+ WriteProc => \&ProcessNikonEncrypted,
2548
2531
  DecryptStart => 4,
2549
2532
  },
2550
2533
  },
@@ -2553,8 +2536,8 @@ my %base64coord = (
2553
2536
  Name => 'LensData0403',
2554
2537
  SubDirectory => {
2555
2538
  TagTable => 'Image::ExifTool::Nikon::LensData0403',
2556
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2557
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2539
+ ProcessProc => \&ProcessNikonEncrypted,
2540
+ WriteProc => \&ProcessNikonEncrypted,
2558
2541
  DecryptStart => 4,
2559
2542
  },
2560
2543
  },
@@ -2563,8 +2546,8 @@ my %base64coord = (
2563
2546
  Name => 'LensData0800',
2564
2547
  SubDirectory => {
2565
2548
  TagTable => 'Image::ExifTool::Nikon::LensData0800',
2566
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2567
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2549
+ ProcessProc => \&ProcessNikonEncrypted,
2550
+ WriteProc => \&ProcessNikonEncrypted,
2568
2551
  DecryptStart => 4,
2569
2552
  ByteOrder => 'LittleEndian',
2570
2553
  },
@@ -2573,8 +2556,8 @@ my %base64coord = (
2573
2556
  Name => 'LensDataUnknown',
2574
2557
  SubDirectory => {
2575
2558
  TagTable => 'Image::ExifTool::Nikon::LensDataUnknown',
2576
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2577
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
2559
+ ProcessProc => \&ProcessNikonEncrypted,
2560
+ WriteProc => \&ProcessNikonEncrypted,
2578
2561
  DecryptStart => 4,
2579
2562
  },
2580
2563
  },
@@ -5279,7 +5262,7 @@ my %nikonFocalConversions = (
5279
5262
  Name => 'NewLensData',
5280
5263
  Format => 'undef[17]',
5281
5264
  RawConv => '$$self{NewLensData} = 1 unless $val =~ /^.\0+$/s; undef',
5282
- Hidden => 1,
5265
+ #Hidden => 1,
5283
5266
  },
5284
5267
  0x30 => { #PH
5285
5268
  Name => 'LensID',
@@ -5305,12 +5288,14 @@ my %nikonFocalConversions = (
5305
5288
  23 => 'Nikkor Z 14-24mm f/2.8 S', #IB
5306
5289
  24 => 'Nikkor Z MC 105mm f/2.8 VR S', #IB
5307
5290
  25 => 'Nikkor Z 40mm f/2', #28
5291
+ 26 => 'Nikkor Z DX 18-140mm f/3.5-6.3 VR', #IB
5308
5292
  27 => 'Nikkor Z MC 50mm f/2.8', #IB
5309
5293
  28 => 'Nikkor Z 100-400mm f/4.5-5.6 VR S', #28
5310
5294
  29 => 'Nikkor Z 28mm f/2.8', #IB
5311
5295
  30 => 'Nikkor Z 400mm f/2.8 TC VR S', #28
5312
5296
  31 => 'Nikkor Z 24-120 f/4', #28
5313
5297
  32 => 'Nikkor Z 800mm f/6.3 VR S', #28
5298
+ 35 => 'Nikkor Z 28-75mm f/2.8', #IB
5314
5299
  36 => 'Nikkor Z 400mm f/4.5 VR S', #IB
5315
5300
  37 => 'Nikkor Z 600mm f/4 TC VR S', #28
5316
5301
  39 => 'Nikkor Z 17-28mm f/2.8', #IB
@@ -5322,7 +5307,7 @@ my %nikonFocalConversions = (
5322
5307
  Name => 'LensMountType',
5323
5308
  RawConv => '$$self{LensMountType} = $val', # 0=> DSLR lens via FTZ style adapter; 1=> Native Z lens;
5324
5309
  Format => 'int8u',
5325
- Unknown => 1,
5310
+ #Unknown => 1,
5326
5311
  PrintConv => {
5327
5312
  0 => 'F-mount Lens',
5328
5313
  1 => 'Z-mount Lens',
@@ -5385,7 +5370,7 @@ my %nikonFocalConversions = (
5385
5370
  Name => 'LensPositionAbsolute', # <=0 at infinity. Typical value at CFD might be 58000. Only valid for Z-mount lenses.
5386
5371
  Condition => '$$self{NewLensData} and $$self{LensMountType} and $$self{LensMountType} == 1',
5387
5372
  Format => 'int32s',
5388
- Unknown => 1,
5373
+ #Unknown => 1,
5389
5374
  },
5390
5375
  );
5391
5376
 
@@ -5508,8 +5493,6 @@ my %nikonFocalConversions = (
5508
5493
  Format => 'int32u',
5509
5494
  Priority => 0,
5510
5495
  },
5511
- # note: DecryptLen currently set to 0x251
5512
-
5513
5496
  # 0x55c - int16u[2400] TiffMeteringImage2: 60x40 image (ShotInfoVersion 0800, ref JR)
5514
5497
  # 0x181c - int16u[1200] TiffMeteringImage?: 60x20 image for some NEF's (ShotInfoVersion 0800, ref JR)
5515
5498
  # 0x217c - int16u[2400] TiffMeteringImage3: 60x40 image (ShotInfoVersion 0800, ref JR)
@@ -5521,8 +5504,8 @@ my %nikonFocalConversions = (
5521
5504
 
5522
5505
  # shot information for D40 and D40X (encrypted) - ref PH
5523
5506
  %Image::ExifTool::Nikon::ShotInfoD40 = (
5524
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5525
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5507
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5508
+ WRITE_PROC => \&ProcessNikonEncrypted,
5526
5509
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5527
5510
  VARS => { ID_LABEL => 'Index' },
5528
5511
  IS_SUBDIR => [ 729 ],
@@ -5552,13 +5535,12 @@ my %nikonFocalConversions = (
5552
5535
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD40',
5553
5536
  },
5554
5537
  },
5555
- # note: DecryptLen currently set to 748
5556
5538
  );
5557
5539
 
5558
5540
  # shot information for D80 (encrypted) - ref JD
5559
5541
  %Image::ExifTool::Nikon::ShotInfoD80 = (
5560
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5561
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5542
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5543
+ WRITE_PROC => \&ProcessNikonEncrypted,
5562
5544
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5563
5545
  VARS => { ID_LABEL => 'Index' },
5564
5546
  IS_SUBDIR => [ 748 ],
@@ -5632,13 +5614,12 @@ my %nikonFocalConversions = (
5632
5614
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD80',
5633
5615
  },
5634
5616
  },
5635
- # note: DecryptLen currently set to 765
5636
5617
  );
5637
5618
 
5638
5619
  # shot information for D90 (encrypted) - ref PH
5639
5620
  %Image::ExifTool::Nikon::ShotInfoD90 = (
5640
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5641
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5621
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5622
+ WRITE_PROC => \&ProcessNikonEncrypted,
5642
5623
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5643
5624
  VARS => { ID_LABEL => 'Index' },
5644
5625
  IS_SUBDIR => [ 0x374 ],
@@ -5678,13 +5659,12 @@ my %nikonFocalConversions = (
5678
5659
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD90',
5679
5660
  },
5680
5661
  },
5681
- # note: DecryptLen currently set to 0x398
5682
5662
  );
5683
5663
 
5684
5664
  # shot information for the D3 firmware 0.37 and 1.00 (encrypted) - ref PH
5685
5665
  %Image::ExifTool::Nikon::ShotInfoD3a = (
5686
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5687
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5666
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5667
+ WRITE_PROC => \&ProcessNikonEncrypted,
5688
5668
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5689
5669
  VARS => { ID_LABEL => 'Index' },
5690
5670
  IS_SUBDIR => [ 0x301 ],
@@ -5742,13 +5722,12 @@ my %nikonFocalConversions = (
5742
5722
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5743
5723
  },
5744
5724
  },
5745
- # note: DecryptLen currently set to 0x318
5746
5725
  );
5747
5726
 
5748
5727
  # shot information for the D3 firmware 1.10, 2.00 and 2.01 (encrypted) - ref PH
5749
5728
  %Image::ExifTool::Nikon::ShotInfoD3b = (
5750
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5751
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5729
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5730
+ WRITE_PROC => \&ProcessNikonEncrypted,
5752
5731
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5753
5732
  VARS => { ID_LABEL => 'Index' },
5754
5733
  IS_SUBDIR => [ 0x30a ],
@@ -5837,13 +5816,12 @@ my %nikonFocalConversions = (
5837
5816
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5838
5817
  },
5839
5818
  },
5840
- # note: DecryptLen currently set to 0x321
5841
5819
  );
5842
5820
 
5843
5821
  # shot information for the D3X firmware 1.00 (encrypted) - ref PH
5844
5822
  %Image::ExifTool::Nikon::ShotInfoD3X = (
5845
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5846
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5823
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5824
+ WRITE_PROC => \&ProcessNikonEncrypted,
5847
5825
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5848
5826
  VARS => { ID_LABEL => 'Index' },
5849
5827
  IS_SUBDIR => [ 0x30b ],
@@ -5883,13 +5861,12 @@ my %nikonFocalConversions = (
5883
5861
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5884
5862
  },
5885
5863
  },
5886
- # note: DecryptLen currently set to 0x323
5887
5864
  );
5888
5865
 
5889
5866
  # shot information for the D3S firmware 0.16 and 1.00 (encrypted) - ref PH
5890
5867
  %Image::ExifTool::Nikon::ShotInfoD3S = (
5891
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5892
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5868
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5869
+ WRITE_PROC => \&ProcessNikonEncrypted,
5893
5870
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5894
5871
  VARS => { ID_LABEL => 'Index' },
5895
5872
  IS_SUBDIR => [ 0x2ce ],
@@ -5938,13 +5915,12 @@ my %nikonFocalConversions = (
5938
5915
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5939
5916
  },
5940
5917
  },
5941
- # note: DecryptLen currently set to 0x2e9
5942
5918
  );
5943
5919
 
5944
5920
  # shot information for the D300 firmware 1.00 (encrypted) - ref JD
5945
5921
  %Image::ExifTool::Nikon::ShotInfoD300a = (
5946
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5947
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
5922
+ PROCESS_PROC => \&ProcessNikonEncrypted,
5923
+ WRITE_PROC => \&ProcessNikonEncrypted,
5948
5924
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
5949
5925
  VARS => { ID_LABEL => 'Index' },
5950
5926
  IS_SUBDIR => [ 790 ],
@@ -6031,13 +6007,12 @@ my %nikonFocalConversions = (
6031
6007
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6032
6008
  },
6033
6009
  },
6034
- # note: DecryptLen currently set to 813
6035
6010
  );
6036
6011
 
6037
6012
  # shot information for the D300 firmware 1.10 (encrypted) - ref PH
6038
6013
  %Image::ExifTool::Nikon::ShotInfoD300b = (
6039
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6040
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6014
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6015
+ WRITE_PROC => \&ProcessNikonEncrypted,
6041
6016
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6042
6017
  VARS => { ID_LABEL => 'Index' },
6043
6018
  DATAMEMBER => [ 4 ],
@@ -6182,13 +6157,12 @@ my %nikonFocalConversions = (
6182
6157
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6183
6158
  },
6184
6159
  },
6185
- # note: DecryptLen currently set to 825
6186
6160
  );
6187
6161
 
6188
6162
  # shot information for the D300S firmware 1.00 (encrypted) - ref PH
6189
6163
  %Image::ExifTool::Nikon::ShotInfoD300S = (
6190
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6191
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6164
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6165
+ WRITE_PROC => \&ProcessNikonEncrypted,
6192
6166
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6193
6167
  VARS => { ID_LABEL => 'Index' },
6194
6168
  IS_SUBDIR => [ 804 ],
@@ -6228,13 +6202,12 @@ my %nikonFocalConversions = (
6228
6202
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6229
6203
  },
6230
6204
  },
6231
- # note: DecryptLen currently set to 827
6232
6205
  );
6233
6206
 
6234
6207
  # shot information for the D700 firmware 1.02f (encrypted) - ref 29
6235
6208
  %Image::ExifTool::Nikon::ShotInfoD700 = (
6236
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6237
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6209
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6210
+ WRITE_PROC => \&ProcessNikonEncrypted,
6238
6211
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6239
6212
  VARS => { ID_LABEL => 'Index' },
6240
6213
  IS_SUBDIR => [ 804 ],
@@ -6274,13 +6247,45 @@ my %nikonFocalConversions = (
6274
6247
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD700',
6275
6248
  },
6276
6249
  },
6277
- # note: DecryptLen currently set to 852
6250
+ );
6251
+
6252
+ # shot information for the D780 - ref #28
6253
+ %Image::ExifTool::Nikon::ShotInfoD780 = (
6254
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6255
+ WRITE_PROC => \&ProcessNikonEncrypted,
6256
+ CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6257
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
6258
+ DATAMEMBER => [ 0x04 ],
6259
+ IS_SUBDIR => [ 0x9c ],
6260
+ WRITABLE => 1,
6261
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6262
+ NOTES => 'These tags are extracted from encrypted data in images from the D780.',
6263
+ 0x00 => {
6264
+ Name => 'ShotInfoVersion',
6265
+ Format => 'string[4]',
6266
+ Writable => 0,
6267
+ },
6268
+ 0x04 => {
6269
+ Name => 'FirmwareVersion',
6270
+ DataMember => 'FirmwareVersion',
6271
+ Format => 'string[5]',
6272
+ Writable => 0,
6273
+ RawConv => '$$self{FirmwareVersion} = $val',
6274
+ },
6275
+ 0x9c => {
6276
+ Name => 'OrientOffset',
6277
+ Format => 'int32u',
6278
+ SubDirectory => {
6279
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
6280
+ Start => '$val',
6281
+ },
6282
+ },
6278
6283
  );
6279
6284
 
6280
6285
  # shot information for the D5000 firmware 1.00 (encrypted) - ref PH
6281
6286
  %Image::ExifTool::Nikon::ShotInfoD5000 = (
6282
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6283
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6287
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6288
+ WRITE_PROC => \&ProcessNikonEncrypted,
6284
6289
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6285
6290
  VARS => { ID_LABEL => 'Index' },
6286
6291
  IS_SUBDIR => [ 0x378 ],
@@ -6320,13 +6325,12 @@ my %nikonFocalConversions = (
6320
6325
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5000',
6321
6326
  },
6322
6327
  },
6323
- # note: DecryptLen currently set to 0x39a
6324
6328
  );
6325
6329
 
6326
6330
  # shot information for the D5100 firmware 1.00f (encrypted) - ref PH
6327
6331
  %Image::ExifTool::Nikon::ShotInfoD5100 = (
6328
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6329
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6332
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6333
+ WRITE_PROC => \&ProcessNikonEncrypted,
6330
6334
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6331
6335
  VARS => { ID_LABEL => 'Index' },
6332
6336
  IS_SUBDIR => [ 0x407 ],
@@ -6355,13 +6359,12 @@ my %nikonFocalConversions = (
6355
6359
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5100',
6356
6360
  },
6357
6361
  },
6358
- # note: DecryptLen currently set to 0x430
6359
6362
  );
6360
6363
 
6361
6364
  # shot information for the D5200 firmware 1.00 (encrypted) - ref PH
6362
6365
  %Image::ExifTool::Nikon::ShotInfoD5200 = (
6363
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6364
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6366
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6367
+ WRITE_PROC => \&ProcessNikonEncrypted,
6365
6368
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6366
6369
  VARS => { ID_LABEL => 'Index' },
6367
6370
  IS_SUBDIR => [ 0xcd5 ],
@@ -6393,13 +6396,12 @@ my %nikonFocalConversions = (
6393
6396
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5200',
6394
6397
  },
6395
6398
  },
6396
- # note: DecryptLen currently set to 0xd00
6397
6399
  );
6398
6400
 
6399
6401
  # shot information for the D7000 firmware 1.01d (encrypted) - ref 29
6400
6402
  %Image::ExifTool::Nikon::ShotInfoD7000 = (
6401
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6402
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6403
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6404
+ WRITE_PROC => \&ProcessNikonEncrypted,
6403
6405
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6404
6406
  VARS => { ID_LABEL => 'Index' },
6405
6407
  IS_SUBDIR => [ 1028 ],
@@ -6441,10 +6443,43 @@ my %nikonFocalConversions = (
6441
6443
  },
6442
6444
  );
6443
6445
 
6446
+ # shot information for the D7500 - ref #28
6447
+ %Image::ExifTool::Nikon::ShotInfoD7500 = (
6448
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6449
+ WRITE_PROC => \&ProcessNikonEncrypted,
6450
+ CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6451
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x0c },
6452
+ DATAMEMBER => [ 0x04 ],
6453
+ IS_SUBDIR => [ 0xa0 ],
6454
+ WRITABLE => 1,
6455
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6456
+ NOTES => 'These tags are extracted from encrypted data in images from the D7500.',
6457
+ 0x00 => {
6458
+ Name => 'ShotInfoVersion',
6459
+ Format => 'string[4]',
6460
+ Writable => 0,
6461
+ },
6462
+ 0x04 => {
6463
+ Name => 'FirmwareVersion',
6464
+ DataMember => 'FirmwareVersion',
6465
+ Format => 'string[5]',
6466
+ Writable => 0,
6467
+ RawConv => '$$self{FirmwareVersion} = $val',
6468
+ },
6469
+ 0xa0 => {
6470
+ Name => 'OrientOffset',
6471
+ Format => 'int32u',
6472
+ SubDirectory => {
6473
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
6474
+ Start => '$val',
6475
+ },
6476
+ },
6477
+ );
6478
+
6444
6479
  # shot information for the D800 firmware 1.01a (encrypted) - ref PH
6445
6480
  %Image::ExifTool::Nikon::ShotInfoD800 = (
6446
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6447
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6481
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6482
+ WRITE_PROC => \&ProcessNikonEncrypted,
6448
6483
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6449
6484
  VARS => { ID_LABEL => 'Index' },
6450
6485
  IS_SUBDIR => [ 0x6ec ],
@@ -6559,20 +6594,17 @@ my %nikonFocalConversions = (
6559
6594
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD800',
6560
6595
  },
6561
6596
  },
6562
- # note: DecryptLen currently set to 0x720
6563
6597
  );
6564
6598
 
6565
6599
  # shot information for the D5 firmware 1.10a and D500 firmware 1.01 (encrypted) - ref 28
6566
6600
  %Image::ExifTool::Nikon::ShotInfoD500 = (
6567
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6568
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
6601
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6602
+ WRITE_PROC => \&ProcessNikonEncrypted,
6569
6603
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6570
- VARS => { ID_LABEL => 'Index' },
6571
- DATAMEMBER => [ 0x04, 0x10, 0x14, 0x2c, 0x50, 0x58, 0xa0, 0xa8, 0xb0,
6572
- 0x07b0, 0x086c, 0x0e7c, 0x0eea, 0x2c23, 0x2c8f ],
6573
- IS_SUBDIR => [ 0x0eeb ],
6604
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x0c },
6605
+ DATAMEMBER => [ 0x04 ],
6606
+ IS_SUBDIR => [ 0x10, 0x14, 0x2c, 0x50, 0x58, 0xa0, 0xa8 ],
6574
6607
  WRITABLE => 1,
6575
- FIRST_ENTRY => 0,
6576
6608
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6577
6609
  NOTES => 'These tags are extracted from encrypted data in images from the D5 and D500.',
6578
6610
  0x00 => {
@@ -6589,73 +6621,66 @@ my %nikonFocalConversions = (
6589
6621
  },
6590
6622
  0x10 => {
6591
6623
  Name => 'RotationInfoOffset',
6592
- DataMember => 'RotationInfoOffset',
6593
6624
  Format => 'int32u',
6594
- Writable => 0,
6595
- Hidden => 1,
6596
- RawConv => '$$self{RotationInfoOffset} = $val || 0x10000000; undef', # (ignore if 0)
6625
+ SubDirectory => {
6626
+ TagTable => 'Image::ExifTool::Nikon::RotationInfoD500',
6627
+ Start => '$val',
6628
+ }
6597
6629
  },
6598
6630
  0x14 => {
6599
6631
  Name => 'JPGInfoOffset',
6600
- DataMember => 'JPGInfoOffset',
6601
6632
  Format => 'int32u',
6602
- Writable => 0,
6603
- Hidden => 1,
6604
- RawConv => '$$self{JPGInfoOffset} = $val || 0x10000000; undef', # (ignore if 0)
6633
+ SubDirectory => {
6634
+ TagTable => 'Image::ExifTool::Nikon::JPGInfoD500',
6635
+ Start => '$val',
6636
+ }
6605
6637
  },
6606
6638
  0x2c => {
6607
- Name => 'BracketingInfoOffset',
6608
- DataMember => 'BracketingInfoOffset',
6639
+ Name => 'BracketingOffset',
6609
6640
  Format => 'int32u',
6610
- Writable => 0,
6611
- Hidden => 1,
6612
- RawConv => '$$self{BracketingInfoOffset} = $val || 0x10000000; undef', # (ignore if 0)
6641
+ SubDirectory => {
6642
+ TagTable => 'Image::ExifTool::Nikon::BracketingInfoD500',
6643
+ Start => '$val',
6644
+ }
6613
6645
  },
6614
6646
  0x50 => {
6615
6647
  Name => 'ShootingMenuOffset',
6616
- DataMember => 'ShootingMenuOffset',
6617
6648
  Format => 'int32u',
6618
- Writable => 0,
6619
- Hidden => 1,
6620
- RawConv => '$$self{ShootingMenuOffset} = $val || 0x10000000; undef', # (ignore if 0)
6649
+ SubDirectory => {
6650
+ TagTable => 'Image::ExifTool::Nikon::ShootingMenuD500',
6651
+ Start => '$val',
6652
+ }
6621
6653
  },
6622
6654
  0x58 => {
6623
6655
  Name => 'CustomSettingsOffset',
6624
- DataMember => 'CustomSettingsOffset',
6625
6656
  Format => 'int32u',
6626
- Writable => 0,
6627
- Hidden => 1,
6628
- RawConv => '$$self{CustomSettingsOffset} = $val || 0x10000000; undef', # (ignore if 0)
6657
+ SubDirectory => {
6658
+ TagTable => 'Image::ExifTool::Nikon::CustomSettingsD500',
6659
+ Start => '$val',
6660
+ }
6629
6661
  },
6630
6662
  0xa0 => {
6631
6663
  Name => 'OrientationOffset',
6632
- DataMember => 'OrientationOffset',
6633
6664
  Format => 'int32u',
6634
- Writable => 0,
6635
- Hidden => 1,
6636
- RawConv => '$$self{OrientationOffset} = $val || 0x10000000; undef', # (ignore if 0)
6665
+ SubDirectory => {
6666
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
6667
+ Start => '$val',
6668
+ }
6637
6669
  },
6638
6670
  0xa8 => {
6639
6671
  Name => 'OtherOffset',
6640
- DataMember => 'OtherOffset',
6641
6672
  Format => 'int32u',
6642
- Writable => 0,
6643
- Hidden => 1,
6644
- RawConv => '$$self{OtherOffset} = $val || 0x10000000; undef', # (ignore if 0)
6645
- },
6646
- #
6647
- # Tag ID's below are the offsets for a D500 JPEG image, but these offsets change
6648
- # for various image types according to the offset table above
6649
- #
6650
- ### 0xb0 - RotationInfo start
6651
- 0xb0 => {
6652
- Name => 'Hook1',
6653
- Hidden => 1,
6654
- RawConv => 'undef',
6655
- # account for variable location of Rotation data
6656
- Hook => '$varSize = $$self{RotationInfoOffset} - 0xb0',
6673
+ SubDirectory => {
6674
+ TagTable => 'Image::ExifTool::Nikon::OtherInfoD500',
6675
+ Start => '$val',
6676
+ }
6657
6677
  },
6658
- 0xca => {
6678
+ );
6679
+
6680
+ %Image::ExifTool::Nikon::RotationInfoD500 = (
6681
+ %binaryDataAttrs,
6682
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6683
+ 0x1a => {
6659
6684
  Name => 'Rotation',
6660
6685
  Mask => 0x03,
6661
6686
  PrintConv => {
@@ -6665,32 +6690,29 @@ my %nikonFocalConversions = (
6665
6690
  3 => 'Rotate 180',
6666
6691
  },
6667
6692
  },
6668
- 0x0d0 => {
6693
+ 0x20 => {
6669
6694
  Name => 'Interval',
6670
6695
  # prior version of the d% firmware do not support this tag, nor does the D500 (at least thru firmware 1.3)
6671
6696
  Condition => '$$self{Model} eq "NIKON D5" and $$self{FirmwareVersion} ge "1.40"',
6672
6697
  PrintConv => '$val > 0 ? sprintf("%.0f", $val) : ""',
6673
6698
  },
6674
- 0x0d4 => {
6699
+ 0x24 => {
6675
6700
  Name => 'IntervalFrame',
6676
6701
  # prior version of the d% firmware do not support this tag, nor does the D500 (at least thru firmware 1.3)
6677
6702
  Condition => '$$self{Model} eq "NIKON D5" and $$self{FirmwareVersion} ge "1.40"',
6678
6703
  PrintConv => '$val > 0 ? sprintf("%.0f", $val) : ""',
6679
6704
  },
6680
- 0x05e2 => {
6705
+ 0x0532 => {
6681
6706
  Name => 'FlickerReductionIndicator',
6682
6707
  Mask => 0x01,
6683
6708
  PrintConv => { 0 => 'On', 1 => 'Off' },
6684
6709
  },
6685
- ### 0x07b0 - JPEGInfo start
6686
- 0x07b0 => {
6687
- Name => 'Hook2',
6688
- Hidden => 1,
6689
- RawConv => 'undef',
6690
- # account for variable location of Shooting Menu data
6691
- Hook => '$varSize = $$self{JPGInfoOffset} - 0x07b0',
6692
- },
6693
- 0x07d4 => {
6710
+ );
6711
+
6712
+ %Image::ExifTool::Nikon::JPGInfoD500 = (
6713
+ %binaryDataAttrs,
6714
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6715
+ 0x24 => {
6694
6716
  Name => 'JPGCompression',
6695
6717
  Mask => 0x01,
6696
6718
  PrintConv => {
@@ -6698,16 +6720,12 @@ my %nikonFocalConversions = (
6698
6720
  1 => 'Optimal Quality',
6699
6721
  },
6700
6722
  },
6701
- ### 0x0830 - ? start
6702
- ### 0x086c - BracketingInfo start
6703
- 0x086c => {
6704
- Name => 'Hook3',
6705
- Hidden => 1,
6706
- RawConv => 'undef',
6707
- # account for variable location of Shooting Menu data
6708
- Hook => '$varSize = $$self{BracketingInfoOffset} - 0x086c',
6709
- },
6710
- 0x087b => {
6723
+ );
6724
+
6725
+ %Image::ExifTool::Nikon::BracketingInfoD500 = (
6726
+ %binaryDataAttrs,
6727
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6728
+ 0x0f => {
6711
6729
  Name => 'AEBracketingSteps',
6712
6730
  Condition => '$$self{FILE_TYPE} ne "TIFF"', # (covers NEF and TIFF)
6713
6731
  Mask => 0xff,
@@ -6765,7 +6783,7 @@ my %nikonFocalConversions = (
6765
6783
  0xd6 => '5F3',
6766
6784
  },
6767
6785
  },
6768
- 0x087c => {
6786
+ 0x10 => {
6769
6787
  Name => 'WBBracketingSteps',
6770
6788
  Condition => '$$self{FILE_TYPE} ne "TIFF"', # (covers NEF and TIFF)
6771
6789
  Mask => 0xff,
@@ -6808,7 +6826,7 @@ my %nikonFocalConversions = (
6808
6826
  0x28 => '9F 3',
6809
6827
  },
6810
6828
  },
6811
- 0x0883 => {
6829
+ 0x17 => {
6812
6830
  Name => 'ADLBracketingStep',
6813
6831
  Mask => 0xf0,
6814
6832
  PrintConv => {
@@ -6820,7 +6838,7 @@ my %nikonFocalConversions = (
6820
6838
  8 => 'Auto',
6821
6839
  },
6822
6840
  },
6823
- 0x0884 => {
6841
+ 0x18 => {
6824
6842
  Name => 'ADLBracketingType',
6825
6843
  Mask => 0x0f,
6826
6844
  PrintConv => {
@@ -6831,23 +6849,12 @@ my %nikonFocalConversions = (
6831
6849
  4 => '5 Shots',
6832
6850
  },
6833
6851
  },
6834
- ### 0x0887 - ? start
6835
- ### 0x089f - ? start
6836
- ### 0x0929 - ? start
6837
- ### 0x09c9 - ? start
6838
- ### 0x0ac5 - ? start
6839
- ### 0x0bc1 - ? start
6840
- ### 0x0cbd - ? start
6841
- ### 0x0d98 - ? start
6842
- ### 0x0e7d - ShootingMenuOffset start
6843
- 0x0e7c => {
6844
- Name => 'Hook4',
6845
- Hidden => 1,
6846
- RawConv => 'undef',
6847
- # account for variable location of Shooting Menu data
6848
- Hook => '$varSize = $$self{ShootingMenuOffset} - 0x0e7d',
6849
- },
6850
- 0x0e7d => {
6852
+ );
6853
+
6854
+ %Image::ExifTool::Nikon::ShootingMenuD500 = (
6855
+ %binaryDataAttrs,
6856
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6857
+ 0x00 => {
6851
6858
  Name => 'PhotoShootingMenuBank',
6852
6859
  Mask => 0x03,
6853
6860
  PrintConv => {
@@ -6857,7 +6864,7 @@ my %nikonFocalConversions = (
6857
6864
  3 => 'D',
6858
6865
  },
6859
6866
  },
6860
- 0x0e7f => {
6867
+ 0x02 => {
6861
6868
  Name => 'PrimarySlot',
6862
6869
  Condition => '$$self{Model} =~ /\bD500\b/',
6863
6870
  Notes => 'D500 only',
@@ -6867,7 +6874,7 @@ my %nikonFocalConversions = (
6867
6874
  1 => 'SD Card',
6868
6875
  },
6869
6876
  },
6870
- 0x0e81 => {
6877
+ 0x04 => {
6871
6878
  Name => 'ISOAutoShutterTime',
6872
6879
  Mask => 0x3f,
6873
6880
  PrintConv => {
@@ -6910,7 +6917,7 @@ my %nikonFocalConversions = (
6910
6917
  36 => 'Auto (Fastest)',
6911
6918
  },
6912
6919
  },
6913
- 0x0e82 => {
6920
+ 0x05 => {
6914
6921
  Name => 'ISOAutoHiLimit',
6915
6922
  Mask => 0xff,
6916
6923
  PrintHex => 1,
@@ -6958,7 +6965,7 @@ my %nikonFocalConversions = (
6958
6965
  0x72 => 'ISO Hi 5.0',
6959
6966
  },
6960
6967
  },
6961
- 0x0e84 => {
6968
+ 0x07 => {
6962
6969
  Name => 'FlickerReduction',
6963
6970
  Mask => 0x20,
6964
6971
  PrintConv => {
@@ -6966,7 +6973,7 @@ my %nikonFocalConversions = (
6966
6973
  1 => 'Disable',
6967
6974
  },
6968
6975
  },
6969
- 3716.1 => { # (0x0e84)
6976
+ 7.1 => {
6970
6977
  Name => 'PhotoShootingMenuBankImageArea',
6971
6978
  Mask => 0x07,
6972
6979
  PrintConv => {
@@ -6977,16 +6984,14 @@ my %nikonFocalConversions = (
6977
6984
  4 => '1.3x (18x12)',
6978
6985
  },
6979
6986
  },
6980
- ### 0x0ec4 - ? start
6981
- ### 0x0eeb - CustomSettings start
6982
- 0x0eea => {
6983
- Name => 'Hook5',
6984
- Hidden => 1,
6985
- RawConv => 'undef',
6986
- # account for variable location of CustomSettings data
6987
- Hook => '$varSize = $$self{CustomSettingsOffset} - 0x0eeb',
6988
- },
6989
- 0x0eeb => [{
6987
+ );
6988
+
6989
+ %Image::ExifTool::Nikon::CustomSettingsD500 = (
6990
+ %binaryDataAttrs,
6991
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6992
+ IS_SUBDIR => [ 0x00 ],
6993
+ VARS => { ALLOW_REPROCESS => 1 }, # (necessary because subdirectory is at offset 0)
6994
+ 0x00 => [{
6990
6995
  Name => 'CustomSettingsD5',
6991
6996
  Condition => '$$self{Model} =~ /\bD5\b/',
6992
6997
  Format => 'undef[90]',
@@ -7000,7 +7005,7 @@ my %nikonFocalConversions = (
7000
7005
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD500',
7001
7006
  },
7002
7007
  }],
7003
- # 0x0f68 => { #this decode works, but involves more bits than should be necessary
7008
+ # 0x7d => { #this decode works, but involves more bits than should be necessary
7004
7009
  # Name => 'ShutterTrigger',
7005
7010
  # Mask => 0xff,
7006
7011
  # PrintConv => {
@@ -7009,51 +7014,13 @@ my %nikonFocalConversions = (
7009
7014
  # 195 => 'Shutter Button',
7010
7015
  # },
7011
7016
  # },
7012
- ### 0x2c24 - OrientationInfo start (D5 firmware 1.10b)
7013
- 0x2c23 => {
7014
- Name => 'Hook6',
7015
- Hidden => 1,
7016
- RawConv => 'undef',
7017
- # account for variable location of OrientationInfo data
7018
- Hook => '$varSize = $$self{OrientationOffset} - 0x2c24',
7019
- },
7020
- 0x2c24 => {
7021
- Name => 'RollAngle',
7022
- Format => 'fixed32u',
7023
- Notes => 'converted to degrees of clockwise camera roll',
7024
- ValueConv => '$val <= 180 ? $val : $val - 360',
7025
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7026
- PrintConv => 'sprintf("%.1f", $val)',
7027
- PrintConvInv => '$val',
7028
- },
7029
- 0x2c28 => {
7030
- Name => 'PitchAngle',
7031
- Format => 'fixed32u',
7032
- Notes => 'converted to degrees of upward camera tilt',
7033
- ValueConv => '$val <= 180 ? $val : $val - 360',
7034
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7035
- PrintConv => 'sprintf("%.1f", $val)',
7036
- PrintConvInv => '$val',
7037
- },
7038
- 0x2c2c => {
7039
- Name => 'YawAngle',
7040
- Format => 'fixed32u',
7041
- Notes => 'the camera yaw angle when shooting in portrait orientation',
7042
- ValueConv => '$val <= 180 ? $val : $val - 360',
7043
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7044
- PrintConv => 'sprintf("%.1f", $val)',
7045
- PrintConvInv => '$val',
7046
- },
7047
- ### 0x2c90 - OtherInfo start (D500 firmware 1.20d)
7048
- 0x2c8f => {
7049
- Name => 'Hook7',
7050
- Hidden => 1,
7051
- RawConv => 'undef',
7052
- # account for variable location of OtherInfo data
7053
- Hook => '$varSize = $$self{OtherOffset} - 0x2c90',
7054
- },
7017
+ );
7018
+
7019
+ %Image::ExifTool::Nikon::OtherInfoD500 = (
7020
+ %binaryDataAttrs,
7021
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7055
7022
  # (needs testing)
7056
- #0x2cb2 => {
7023
+ #0x22 => {
7057
7024
  # Name => 'ExtendedPhotoShootingBanks',
7058
7025
  # Mask => 0x01,
7059
7026
  # PrintConv => {
@@ -7062,7 +7029,7 @@ my %nikonFocalConversions = (
7062
7029
  # },
7063
7030
  #},
7064
7031
  # (may not be reliable and is found elsewhere)
7065
- #0x2ea2 => {
7032
+ #0x212 => {
7066
7033
  # Name => 'Rotation',
7067
7034
  # Condition => '$$self{Model} =~ /\bD500\b/',
7068
7035
  # Notes => 'D500 firmware 1.1x',
@@ -7074,7 +7041,7 @@ my %nikonFocalConversions = (
7074
7041
  # 3 => 'Rotate 180',
7075
7042
  # },
7076
7043
  #},
7077
- 0x2ea4 => { #PH
7044
+ 0x214 => { #PH
7078
7045
  Name => 'NikonMeteringMode',
7079
7046
  Condition => '$$self{Model} =~ /\bD500\b/', # (didn't seem to work for D5, but I need more samples)
7080
7047
  Notes => 'D500 only',
@@ -7086,18 +7053,16 @@ my %nikonFocalConversions = (
7086
7053
  3 => 'Highlight'
7087
7054
  },
7088
7055
  },
7089
- # note: DecryptLen currently set to OtherOffset + 0x2ea5 - 0x2c90
7090
7056
  );
7091
7057
 
7092
7058
  # shot information for the D6 firmware 1.00 (encrypted) - ref 28
7093
7059
  %Image::ExifTool::Nikon::ShotInfoD6 = (
7094
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7095
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7060
+ PROCESS_PROC => \&ProcessNikonEncrypted,
7061
+ WRITE_PROC => \&ProcessNikonEncrypted,
7096
7062
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
7097
- VARS => { ID_LABEL => 'Index' },
7098
- DATAMEMBER => [ 0x30, 0x60, 0x9c, 0xa4, 0x75e7, 0x760c, 0x7610, 0xc219, 0xc292, 0xc40e, 0xc412, 0xc4a6, 0xc4be ],
7063
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
7064
+ IS_SUBDIR => [ 0x30, 0x9c, 0xa4 ],
7099
7065
  WRITABLE => 1,
7100
- FIRST_ENTRY => 0,
7101
7066
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7102
7067
  NOTES => 'These tags are extracted from encrypted data in images from the D6.',
7103
7068
  0x00 => {
@@ -7112,159 +7077,111 @@ my %nikonFocalConversions = (
7112
7077
  },
7113
7078
  0x24 => {
7114
7079
  Name => 'NumberOffsets', # (number of entries in offset table. offsets are from start of ShotInfo data)
7115
- DataMember => 'NumberOffsets',
7116
7080
  Format => 'int32u',
7117
7081
  Writable => 0,
7118
7082
  Hidden => 1,
7119
7083
  },
7120
7084
  0x30 => {
7121
- Name => 'Offset3',
7122
- DataMember => 'Offset3',
7085
+ Name => 'SequenceOffset',
7123
7086
  Format => 'int32u',
7124
- Writable => 0,
7125
- Hidden => 1,
7126
- RawConv => '$$self{Offset3} = $val || 0x10000000; undef', # (ignore if 0)
7127
- },
7128
- 0x60 => {
7129
- Name => 'Offset15',
7130
- DataMember => 'Offset15',
7131
- Format => 'int32u',
7132
- Writable => 0,
7133
- Hidden => 1,
7134
- RawConv => '$$self{Offset15} = $val || 0x10000000; undef', # (ignore if 0)
7087
+ SubDirectory => {
7088
+ TagTable => 'Image::ExifTool::Nikon::SeqInfoD6',
7089
+ Start => '$val',
7090
+ },
7135
7091
  },
7136
7092
  0x9c => {
7137
7093
  Name => 'OrientationOffset',
7138
- DataMember => 'OrientationOffset',
7139
7094
  Format => 'int32u',
7140
- Writable => 0,
7141
- Hidden => 1,
7142
- RawConv => '$$self{OrientationOffset} = $val || 0x10000000; undef', # (ignore if 0)
7095
+ SubDirectory => {
7096
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
7097
+ Start => '$val',
7098
+ },
7143
7099
  },
7144
7100
  0xa4 => {
7145
- Name => 'Offset32',
7146
- DataMember => 'Offset32',
7101
+ Name => 'IntervalOffset',
7147
7102
  Format => 'int32u',
7148
- Writable => 0,
7149
- Hidden => 1,
7150
- RawConv => '$$self{Offset32} = $val || 0x10000000; undef', # (ignore if 0)
7151
- },
7152
- ### 0x75e8 - Offset3 info start (D6 firmware 1.33)
7153
- 0x75e7 => {
7154
- Name => 'Hook1',
7155
- Hidden => 1,
7156
- RawConv => 'undef',
7157
- # account for variable location of Offset5 data
7158
- Hook => '$varSize = $$self{Offset3} - 0x75e8',
7103
+ SubDirectory => {
7104
+ TagTable => 'Image::ExifTool::Nikon::IntervalInfoD6',
7105
+ Start => '$val',
7106
+ }
7159
7107
  },
7160
- 0x760c => {
7108
+ );
7109
+
7110
+ %Image::ExifTool::Nikon::SeqInfoD6 = (
7111
+ %binaryDataAttrs,
7112
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7113
+ DATAMEMBER => [ 0x24, 0x28 ],
7114
+ 0x24 => {
7161
7115
  Name => 'IntervalShooting',
7162
7116
  RawConv => '$$self{IntervalShooting} = $val',
7163
7117
  Format => 'int16u',
7164
7118
  PrintConv => q{
7165
7119
  return 'Off' if $val == 0 ;
7166
- my $i = sprintf("Interval %.0f of %.0f",$val, $$self{IntervalShootingIntervals}); #something like "Interval 1 of 3"
7167
- my $f = $$self{IntervalShootingShotsPerInterval} > 1 ? sprintf(" Frame %.0f of %.0f",$$self{IntervalFrame}, $$self{IntervalShootingShotsPerInterval}): '' ; #something like "Frame 1 of 3" or blank
7120
+ my $i = sprintf("Interval %.0f of %.0f",$val, $$self{IntervalShootingIntervals}||0); #something like "Interval 1 of 3"
7121
+ my $f = ($$self{IntervalShootingShotsPerInterval}||0) > 1 ? sprintf(" Frame %.0f of %.0f",$$self{IntervalFrame}||0, $$self{IntervalShootingShotsPerInterval}||0): '' ; #something like "Frame 1 of 3" or blank
7168
7122
  return "On: $i$f"
7169
- #$val == 0 ? 'Off' : sprintf("On: Interval %.0f of %.0f Frame %.0f of %.0f",$val, $$self{IntervalShootingIntervals}, $$self{IntervalFrame}, $$self{IntervalShootingShotsPerInterval}),
7123
+ #$val == 0 ? 'Off' : sprintf("On: Interval %.0f of %.0f Frame %.0f of %.0f",$val, $$self{IntervalShootingIntervals}||0, $$self{IntervalFrame}||0, $$self{IntervalShootingShotsPerInterval}||0),
7170
7124
  },
7171
7125
  },
7172
- 0x7610 => {
7126
+ 0x28 => {
7173
7127
  Name => 'IntervalFrame',
7174
7128
  RawConv => '$$self{IntervalFrame} = $val',
7175
7129
  Condition => '$$self{IntervalShooting} > 0',
7176
7130
  Format => 'int16u',
7177
7131
  Hidden => 1,
7178
7132
  },
7179
- ### 0xc21a - OrientationInfo start (D6 firmware 1.00) (0xc952 for firmware 1.33)
7180
- 0xc219 => {
7181
- Name => 'Hook2',
7182
- Hidden => 1,
7183
- RawConv => 'undef',
7184
- # account for variable location of OrientationInfo data
7185
- Hook => '$varSize = $$self{OrientationOffset} - 0xc21a',
7186
- },
7187
- 0xc21a => {
7188
- Name => 'RollAngle',
7189
- Format => 'fixed32u',
7190
- Notes => 'converted to degrees of clockwise camera roll',
7191
- ValueConv => '$val <= 180 ? $val : $val - 360',
7192
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7193
- PrintConv => 'sprintf("%.1f", $val)',
7194
- PrintConvInv => '$val',
7195
- },
7196
- 0xc21e => {
7197
- Name => 'PitchAngle',
7198
- Format => 'fixed32u',
7199
- Notes => 'converted to degrees of upward camera tilt',
7200
- ValueConv => '$val <= 180 ? $val : $val - 360',
7201
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7202
- PrintConv => 'sprintf("%.1f", $val)',
7203
- PrintConvInv => '$val',
7204
- },
7205
- 0xc222 => {
7206
- Name => 'YawAngle',
7207
- Format => 'fixed32u',
7208
- Notes => 'the camera yaw angle when shooting in portrait orientation',
7209
- ValueConv => '$val <= 180 ? $val : $val - 360',
7210
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7211
- PrintConv => 'sprintf("%.1f", $val)',
7212
- PrintConvInv => '$val',
7213
- },
7214
- ### 0xc9c6 - Offset32 start (D6 firmware 1.33)
7215
- 0xc292 => {
7216
- Name => 'Hook3',
7217
- Hidden => 1,
7218
- RawConv => 'undef',
7219
- # account for variable location of data
7220
- Hook => '$varSize = $$self{Offset32} - 0xc292',
7221
- },
7222
- 0xc40e => {
7133
+ );
7134
+
7135
+ %Image::ExifTool::Nikon::IntervalInfoD6 = (
7136
+ %binaryDataAttrs,
7137
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7138
+ DATAMEMBER => [ 0x17c, 0x180, 0x214, 0x22c ],
7139
+ 0x17c => {
7223
7140
  Name => 'Intervals',
7224
7141
  Format => 'int32u',
7225
7142
  RawConv => '$$self{IntervalShootingIntervals} = $val',
7226
7143
  Condition => '$$self{IntervalShooting} > 0',
7227
7144
  },
7228
- 0xc412 => {
7145
+ 0x180 => {
7229
7146
  Name => 'ShotsPerInterval',
7230
7147
  Format => 'int32u',
7231
7148
  RawConv => '$$self{IntervalShootingShotsPerInterval} = $val',
7232
7149
  Condition => '$$self{IntervalShooting} > 0',
7233
7150
  },
7234
- 0xc416 => {
7151
+ 0x184 => {
7235
7152
  Name => 'IntervalExposureSmoothing',
7236
7153
  Condition => '$$self{IntervalShooting} > 0',
7237
7154
  Format => 'int8u',
7238
7155
  PrintConv => \%offOn,
7239
7156
  },
7240
- 0xc418 => {
7157
+ 0x186 => {
7241
7158
  Name => 'IntervalPriority',
7242
7159
  Condition => '$$self{IntervalShooting} > 0',
7243
7160
  Format => 'int8u',
7244
7161
  PrintConv => \%offOn,
7245
7162
  },
7246
- 0xc43a => {
7163
+ 0x1a8 => {
7247
7164
  Name => 'FocusShiftNumberShots',
7248
7165
  },
7249
- 0xc43e => {
7166
+ 0x1ac => {
7250
7167
  Name => 'FocusShiftStepWidth',
7251
7168
  },
7252
- 0xc442 => {
7169
+ 0x1b0 => {
7253
7170
  Name => 'FocusShiftInterval',
7254
7171
  PrintConv => '$val == 1? "1 Second" : sprintf("%.0f Seconds",$val)',
7255
7172
  },
7256
- 0xc446 => {
7173
+ 0x1b4 => {
7257
7174
  Name => 'FocusShiftExposureLock',
7258
7175
  PrintConv => \%offOn,
7259
7176
  },
7260
- #0xc49c => HighISONoiseReduction
7261
- 0xc4a0 => {
7177
+ #0x20a => HighISONoiseReduction
7178
+ 0x20e => {
7262
7179
  Name => 'DiffractionCompensation',
7263
7180
  Format => 'int8u',
7264
7181
  PrintConv => \%offOn,
7265
7182
  },
7266
- #0xc4a1 => {Name => 'FlickerReductionShooting',}, #redundant with tag in NikonSettings
7267
- 0xc4a6 => {
7183
+ #0x20f => {Name => 'FlickerReductionShooting',}, #redundant with tag in NikonSettings
7184
+ 0x214 => {
7268
7185
  Name => 'FlashControlMode', #this and nearby tag values for flash may be set from either the Photo Shooting Menu or using the Flash unit menu
7269
7186
  RawConv => '$$self{FlashControlMode} = $val',
7270
7187
  PrintConv => {
@@ -7275,14 +7192,14 @@ my %nikonFocalConversions = (
7275
7192
  4 => 'Repeating Flash',
7276
7193
  },
7277
7194
  },
7278
- 0xc4ac => {
7195
+ 0x21a => {
7279
7196
  Name => 'FlashGNDistance',
7280
7197
  Condition => '$$self{FlashControlMode} == 2',
7281
7198
  Unknown => 1,
7282
7199
  ValueConv => '$val + 3',
7283
7200
  PrintConv => \%flashGNDistance,
7284
7201
  },
7285
- 0xc4b0 => {
7202
+ 0x21e => {
7286
7203
  Name => 'FlashOutput', #range[0,24] with 0=>Full; 1=>50%; then decreasing flash power in 1/3 stops to 0.39% (1/256 full power). #also found in FlashInfoUnknown at offset 0x0a (with different mappings)
7287
7204
  Condition => '$$self{FlashControlMode} >= 3',
7288
7205
  Unknown => 1,
@@ -7291,7 +7208,7 @@ my %nikonFocalConversions = (
7291
7208
  PrintConv => '$val>0.99 ? "Full" : sprintf("%.1f%%",$val*100)',
7292
7209
  PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1',
7293
7210
  },
7294
- 0xc4ba => {
7211
+ 0x228 => {
7295
7212
  Name => 'FlashRemoteControl',
7296
7213
  Unknown => 1,
7297
7214
  PrintConv => {
@@ -7300,12 +7217,12 @@ my %nikonFocalConversions = (
7300
7217
  2 => 'Remote Repeating',
7301
7218
  },
7302
7219
  },
7303
- 0xc4be => {
7220
+ 0x22c => {
7304
7221
  Name => 'FlashMasterControlMode', #tag name chosen for compatibility with those found in FlashInfo0102 & FlashInfo0103
7305
7222
  RawConv => '$$self{FlashGroupOptionsMasterMode} = $val',
7306
7223
  PrintConv => \%flashGroupOptionsMode,
7307
7224
  },
7308
- 0xc4c0 => {
7225
+ 0x22e => {
7309
7226
  Name => 'FlashMasterCompensation',
7310
7227
  Unknown => 1,
7311
7228
  Format => 'int8s',
@@ -7315,7 +7232,7 @@ my %nikonFocalConversions = (
7315
7232
  PrintConv => '$val ? sprintf("%+.1f",$val) : 0',
7316
7233
  PrintConvInv => '$val',
7317
7234
  },
7318
- 0xc4c4 => {
7235
+ 0x232 => {
7319
7236
  Name => 'FlashMasterOutput',
7320
7237
  Unknown => 1,
7321
7238
  Condition => '$$self{FlashGroupOptionsMasterMode} == 1', #only for Mode=M
@@ -7324,7 +7241,7 @@ my %nikonFocalConversions = (
7324
7241
  PrintConv => '$val>0.99 ? "Full" : sprintf("%.1f%%",$val*100)',
7325
7242
  PrintConvInv => '$val=~/(\d+)/ ? $1/100 : 1',
7326
7243
  },
7327
- 0xc4c6 => {
7244
+ 0x234 => {
7328
7245
  Name => 'FlashWirelessOption',
7329
7246
  Unknown => 1,
7330
7247
  PrintConv => {
@@ -7332,7 +7249,7 @@ my %nikonFocalConversions = (
7332
7249
  1 => 'Off',
7333
7250
  },
7334
7251
  },
7335
- 0xc55c => {
7252
+ 0x2ca => {
7336
7253
  Name => 'MovieType',
7337
7254
  Unknown => 1,
7338
7255
  PrintConv => {
@@ -7340,13 +7257,12 @@ my %nikonFocalConversions = (
7340
7257
  1 => 'MP4',
7341
7258
  },
7342
7259
  },
7343
- # note: DecryptLen currently set to 0xc9c6 + 720
7344
7260
  );
7345
7261
 
7346
7262
  # shot information for the D610 firmware 1.00 (encrypted) - ref PH
7347
7263
  %Image::ExifTool::Nikon::ShotInfoD610 = (
7348
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7349
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7264
+ PROCESS_PROC => \&ProcessNikonEncrypted,
7265
+ WRITE_PROC => \&ProcessNikonEncrypted,
7350
7266
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
7351
7267
  VARS => { ID_LABEL => 'Index' },
7352
7268
  IS_SUBDIR => [ 0x07cf ],
@@ -7371,25 +7287,19 @@ my %nikonFocalConversions = (
7371
7287
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD610',
7372
7288
  },
7373
7289
  },
7374
- # note: DecryptLen currently set to 0x7ff
7375
7290
  );
7376
7291
 
7377
7292
  # shot information for the D810 firmware 1.00(PH)/1.01 (encrypted) - ref 28
7378
7293
  %Image::ExifTool::Nikon::ShotInfoD810 = (
7379
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7380
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7294
+ PROCESS_PROC => \&ProcessNikonEncrypted,
7295
+ WRITE_PROC => \&ProcessNikonEncrypted,
7381
7296
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
7382
- VARS => { ID_LABEL => 'Index' },
7383
- DATAMEMBER => [ 0x04, 0x24, 0x38, 0x40, 0x84, 0x01d0, 0x175e, 0x185d, 0x18ab ],
7384
- IS_SUBDIR => [ 0x18ab ],
7297
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x0c },
7298
+ DATAMEMBER => [ 0x04 ],
7299
+ IS_SUBDIR => [ 0x10, 0x24, 0x38, 0x40, 0x84 ],
7385
7300
  WRITABLE => 1,
7386
- FIRST_ENTRY => 0,
7387
7301
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7388
- NOTES => q{
7389
- These tags are extracted from encrypted data in images from the D810. Note
7390
- that the indices listed below are for firmware version 1.0, but they may be
7391
- different for other firmware versions.
7392
- },
7302
+ NOTES => 'These tags are extracted from encrypted data in images from the D810.',
7393
7303
  0x00 => {
7394
7304
  Name => 'ShotInfoVersion',
7395
7305
  Format => 'string[4]',
@@ -7404,39 +7314,64 @@ my %nikonFocalConversions = (
7404
7314
  },
7405
7315
  # 0x0c - number of entries in offset table (= 0x21)
7406
7316
  # 0x10 - int32u[val 0x0c]: offset table
7317
+ 0x10 => {
7318
+ Name => 'SettingsOffset',
7319
+ Format => 'int32u',
7320
+ SubDirectory => {
7321
+ TagTable => 'Image::ExifTool::Nikon::SettingsInfoD810',
7322
+ Start => '$val',
7323
+ },
7324
+ },
7407
7325
  0x24 => {
7408
7326
  Name => 'BracketingOffset',
7409
- DataMember => 'BracketingOffset',
7410
7327
  Format => 'int32u',
7411
- Writable => 0,
7412
- Hidden => 1,
7413
- RawConv => '$$self{BracketingOffset} = $val || 0x10000000; undef',
7328
+ SubDirectory => {
7329
+ TagTable => 'Image::ExifTool::Nikon::BracketingInfoD810',
7330
+ Start => '$val',
7331
+ },
7414
7332
  },
7415
7333
  0x38 => {
7416
7334
  Name => 'ISOAutoOffset',
7417
- DataMember => 'ISOAutoOffset',
7418
7335
  Format => 'int32u',
7419
- Writable => 0,
7420
- Hidden => 1,
7421
- RawConv => '$$self{ISOAutoOffset} = $val || 0x10000000; undef',
7336
+ SubDirectory => {
7337
+ TagTable => 'Image::ExifTool::Nikon::ISOAutoInfoD810',
7338
+ Start => '$val',
7339
+ },
7422
7340
  },
7423
7341
  0x40 => {
7424
7342
  Name => 'CustomSettingsOffset', # (relative offset from start of ShotInfo data)
7425
- DataMember => 'CustomSettingsOffset',
7426
7343
  Format => 'int32u',
7427
- Writable => 0,
7428
- Hidden => 1,
7429
- RawConv => '$$self{CustomSettingsOffset} = $val || 0x10000000; undef',
7344
+ SubDirectory => {
7345
+ TagTable => 'Image::ExifTool::NikonCustom::SettingsD810',
7346
+ Start => '$val',
7347
+ },
7430
7348
  },
7431
7349
  0x84 => {
7432
7350
  Name => 'OrientationOffset',
7433
- DataMember => 'OrientationOffset',
7434
7351
  Format => 'int32u',
7435
- Writable => 0,
7436
- Hidden => 1,
7437
- RawConv => '$$self{OrientationOffset} = $val || 0x10000000; undef',
7352
+ SubDirectory => {
7353
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
7354
+ Start => '$val',
7355
+ }
7438
7356
  },
7439
- 0x01d0 => {
7357
+ # (moves around too much and doesn't fit cleanly in the offset table)
7358
+ #0x38be => {
7359
+ # Name => 'Rotation',
7360
+ # Condition => '$$self{FirmwareVersion} =~ /^1\.0/',
7361
+ # Mask => 0x30,
7362
+ # PrintConv => {
7363
+ # 0 => 'Horizontal',
7364
+ # 1 => 'Rotate 270 CW',
7365
+ # 2 => 'Rotate 90 CW',
7366
+ # 3 => 'Rotate 180',
7367
+ # },
7368
+ #},
7369
+ );
7370
+
7371
+ %Image::ExifTool::Nikon::SettingsInfoD810 = (
7372
+ %binaryDataAttrs,
7373
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7374
+ 0x13c => {
7440
7375
  Name => 'SecondarySlotFunction',
7441
7376
  Mask => 0x03,
7442
7377
  PrintConv => {
@@ -7444,9 +7379,13 @@ my %nikonFocalConversions = (
7444
7379
  2 => 'Backup',
7445
7380
  3 => 'NEF Primary + JPG Secondary',
7446
7381
  },
7447
- Hook => '$varSize = $$self{BracketingOffset} - 0x1747',
7448
7382
  },
7449
- 0x1756 => {
7383
+ );
7384
+
7385
+ %Image::ExifTool::Nikon::BracketingInfoD810 = (
7386
+ %binaryDataAttrs,
7387
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7388
+ 0x0f => {
7450
7389
  Name => 'AEBracketingSteps',
7451
7390
  Mask => 0xff,
7452
7391
  PrintHex => 1,
@@ -7503,7 +7442,7 @@ my %nikonFocalConversions = (
7503
7442
  0xd6 => '5F3',
7504
7443
  },
7505
7444
  },
7506
- 0x1757 => {
7445
+ 0x10 => {
7507
7446
  Name => 'WBBracketingSteps',
7508
7447
  Condition => '$$self{FILE_TYPE} ne "TIFF"', # (covers NEF and TIFF)
7509
7448
  Mask => 0xff,
@@ -7546,7 +7485,7 @@ my %nikonFocalConversions = (
7546
7485
  0x28 => '9F 3',
7547
7486
  },
7548
7487
  },
7549
- 0x175e => {
7488
+ 0x17 => {
7550
7489
  Name => 'NikonMeteringMode',
7551
7490
  Mask => 0x03,
7552
7491
  PrintConv => {
@@ -7555,9 +7494,13 @@ my %nikonFocalConversions = (
7555
7494
  2 => 'Spot',
7556
7495
  3 => 'Highlight'
7557
7496
  },
7558
- Hook => '$varSize = $$self{ISOAutoOffset} - 0x1858',
7559
7497
  },
7560
- 0x185c => {
7498
+ );
7499
+
7500
+ %Image::ExifTool::Nikon::ISOAutoInfoD810 = (
7501
+ %binaryDataAttrs,
7502
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7503
+ 0x04 => {
7561
7504
  Name => 'ISOAutoShutterTime',
7562
7505
  Mask => 0x3f,
7563
7506
  PrintConv => {
@@ -7600,7 +7543,7 @@ my %nikonFocalConversions = (
7600
7543
  36 => 'Auto (Fastest)',
7601
7544
  },
7602
7545
  },
7603
- 0x185d => {
7546
+ 0x05 => {
7604
7547
  Name => 'ISOAutoHiLimit',
7605
7548
  Mask => 0xff,
7606
7549
  PrintHex => 1,
@@ -7647,69 +7590,18 @@ my %nikonFocalConversions = (
7647
7590
  0x6c => 'ISO Hi 4.0',
7648
7591
  0x72 => 'ISO Hi 5.0',
7649
7592
  },
7650
- Hook => '$varSize = $$self{CustomSettingsOffset} - 0x18ab',
7651
7593
  },
7652
- 0x18ab => { # (actual offset adjusted by Hook above)
7653
- Name => 'CustomSettingsD810',
7654
- Format => 'undef[53]',
7655
- SubDirectory => {
7656
- TagTable => 'Image::ExifTool::NikonCustom::SettingsD810',
7657
- },
7658
- Hook => '$varSize = $$self{OrientationOffset} - 0x36f4',
7659
- },
7660
- 0x36f4 => {
7661
- Name => 'RollAngle',
7662
- Format => 'fixed32u',
7663
- Notes => 'converted to degrees of clockwise camera roll',
7664
- ValueConv => '$val <= 180 ? $val : $val - 360',
7665
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7666
- PrintConv => 'sprintf("%.1f", $val)',
7667
- PrintConvInv => '$val',
7668
- },
7669
- 0x36f8 => {
7670
- Name => 'PitchAngle',
7671
- Format => 'fixed32u',
7672
- Notes => 'converted to degrees of upward camera tilt',
7673
- ValueConv => '$val <= 180 ? $val : $val - 360',
7674
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7675
- PrintConv => 'sprintf("%.1f", $val)',
7676
- PrintConvInv => '$val',
7677
- },
7678
- 0x36fc => {
7679
- Name => 'YawAngle',
7680
- Format => 'fixed32u',
7681
- Notes => 'the camera yaw angle when shooting in portrait orientation',
7682
- ValueConv => '$val <= 180 ? $val : $val - 360',
7683
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7684
- PrintConv => 'sprintf("%.1f", $val)',
7685
- PrintConvInv => '$val',
7686
- },
7687
- # note: DecryptLen currently set to OrientationOffset + 12
7688
-
7689
- # (moves around too much and doesn't fit cleanly in the offset table)
7690
- #0x38be => {
7691
- # Name => 'Rotation',
7692
- # Condition => '$$self{FirmwareVersion} =~ /^1\.0/',
7693
- # Mask => 0x30,
7694
- # PrintConv => {
7695
- # 0 => 'Horizontal',
7696
- # 1 => 'Rotate 270 CW',
7697
- # 2 => 'Rotate 90 CW',
7698
- # 3 => 'Rotate 180',
7699
- # },
7700
- #},
7701
7594
  );
7702
7595
 
7703
7596
  # shot information for the D850 firmware 1.00b (encrypted) - ref 28
7704
7597
  %Image::ExifTool::Nikon::ShotInfoD850 = (
7705
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7706
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7598
+ PROCESS_PROC => \&ProcessNikonEncrypted,
7599
+ WRITE_PROC => \&ProcessNikonEncrypted,
7707
7600
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
7708
- VARS => { ID_LABEL => 'Index' },
7709
- DATAMEMBER => [ 0x04, 0x58, 0xa0, 0x0fbf, 0x2efa ],
7710
- IS_SUBDIR => [ 0x1038 ],
7601
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x0c },
7602
+ DATAMEMBER => [ 0x04 ],
7603
+ IS_SUBDIR => [ 0x10, 0x4c, 0x58, 0xa0 ],
7711
7604
  WRITABLE => 1,
7712
- FIRST_ENTRY => 0,
7713
7605
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7714
7606
  NOTES => 'These tags are extracted from encrypted data in images from the D850.',
7715
7607
  0x00 => {
@@ -7724,23 +7616,44 @@ my %nikonFocalConversions = (
7724
7616
  Writable => 0,
7725
7617
  RawConv => '$$self{FirmwareVersion} = $val',
7726
7618
  },
7619
+ 0x10 => {
7620
+ Name => 'MenuSettingsOffset',
7621
+ Format => 'int32u',
7622
+ SubDirectory => {
7623
+ TagTable => 'Image::ExifTool::Nikon::MenuSettingsD850',
7624
+ Start => '$val',
7625
+ },
7626
+ },
7627
+ 0x4c => {
7628
+ Name => 'MoreSettingsOffset',
7629
+ Format => 'int32u',
7630
+ SubDirectory => {
7631
+ TagTable => 'Image::ExifTool::Nikon::MoreSettingsD850',
7632
+ Start => '$val',
7633
+ },
7634
+ },
7727
7635
  0x58 => {
7728
- Name => 'CustomSettingsOffset', # (relative offset from start of ShotInfo data)
7729
- DataMember => 'CustomSettingsOffset',
7636
+ Name => 'CustomSettingsOffset',
7730
7637
  Format => 'int32u',
7731
- Writable => 0,
7732
- Hidden => 1,
7733
- RawConv => '$$self{CustomSettingsOffset} = $val || 0x10000000; undef',
7638
+ SubDirectory => {
7639
+ TagTable => 'Image::ExifTool::NikonCustom::SettingsD850',
7640
+ Start => '$val',
7641
+ },
7734
7642
  },
7735
7643
  0xa0 => {
7736
7644
  Name => 'OrientationOffset',
7737
- DataMember => 'OrientationOffset',
7738
7645
  Format => 'int32u',
7739
- Writable => 0,
7740
- Hidden => 1,
7741
- RawConv => '$$self{OrientationOffset} = $val || 0x10000000; undef',
7646
+ SubDirectory => {
7647
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
7648
+ Start => '$val',
7649
+ },
7742
7650
  },
7743
- 0x0791 => {
7651
+ );
7652
+
7653
+ %Image::ExifTool::Nikon::MenuSettingsD850 = (
7654
+ %binaryDataAttrs,
7655
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7656
+ 0x06dd => {
7744
7657
  Name => 'PhotoShootingMenuBankImageArea',
7745
7658
  Mask => 0x07,
7746
7659
  PrintConv => {
@@ -7751,7 +7664,12 @@ my %nikonFocalConversions = (
7751
7664
  4 => '1:1 (24x24)',
7752
7665
  },
7753
7666
  },
7754
- 0x0fbd => {
7667
+ );
7668
+
7669
+ %Image::ExifTool::Nikon::MoreSettingsD850 = (
7670
+ %binaryDataAttrs,
7671
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
7672
+ 0x24 => {
7755
7673
  Name => 'PhotoShootingMenuBank',
7756
7674
  Condition => '$$self{FILE_TYPE} eq "JPEG"',
7757
7675
  Notes => 'valid for JPEG images only',
@@ -7763,63 +7681,20 @@ my %nikonFocalConversions = (
7763
7681
  3 => 'D',
7764
7682
  },
7765
7683
  },
7766
- 0x0fbf => {
7684
+ 0x25 => {
7767
7685
  Name => 'PrimarySlot',
7768
7686
  Mask => 0x80,
7769
7687
  PrintConv => {
7770
7688
  0 => 'XQD Card',
7771
7689
  1 => 'SD Card',
7772
7690
  },
7773
- Hook => '$varSize = $$self{CustomSettingsOffset} - 0x1038',
7774
- },
7775
- 0x1038 => {
7776
- Name => 'CustomSettingsD850',
7777
- Format => 'undef[90]',
7778
- SubDirectory => {
7779
- TagTable => 'Image::ExifTool::NikonCustom::SettingsD850',
7780
- },
7781
- },
7782
- ### 0x2efb - OrientationInfo start (D850 firmware 1.01a)
7783
- 0x2efa => {
7784
- Name => 'Hook1',
7785
- Hidden => 1,
7786
- RawConv => 'undef',
7787
- # account for variable location of OrientationInfo data
7788
- Hook => '$varSize = $$self{OrientationOffset} - 0x2efb',
7789
- },
7790
- 0x2efb => { #28
7791
- Name => 'RollAngle',
7792
- Format => 'fixed32u',
7793
- Notes => 'converted to degrees of clockwise camera roll',
7794
- ValueConv => '$val <= 180 ? $val : $val - 360',
7795
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7796
- PrintConv => 'sprintf("%.1f", $val)',
7797
- PrintConvInv => '$val',
7798
7691
  },
7799
- 0x2eff => { #28
7800
- Name => 'PitchAngle',
7801
- Format => 'fixed32u',
7802
- Notes => 'converted to degrees of upward camera tilt',
7803
- ValueConv => '$val <= 180 ? $val : $val - 360',
7804
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7805
- PrintConv => 'sprintf("%.1f", $val)',
7806
- PrintConvInv => '$val',
7807
- },
7808
- 0x2f03 => { #28
7809
- Name => 'YawAngle',
7810
- Format => 'fixed32u',
7811
- Notes => 'the camera yaw angle when shooting in portrait orientation',
7812
- ValueConv => '$val <= 180 ? $val : $val - 360',
7813
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
7814
- PrintConv => 'sprintf("%.1f", $val)',
7815
- PrintConvInv => '$val',
7816
- },
7817
- # note: DecryptLen currently set to 0x2f07
7818
7692
  );
7693
+
7819
7694
  # shot information for the D4 firmware 1.00g (ref PH)
7820
7695
  %Image::ExifTool::Nikon::ShotInfoD4 = (
7821
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7822
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7696
+ PROCESS_PROC => \&ProcessNikonEncrypted,
7697
+ WRITE_PROC => \&ProcessNikonEncrypted,
7823
7698
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
7824
7699
  VARS => { ID_LABEL => 'Index' },
7825
7700
  IS_SUBDIR => [ 0x0751 ],
@@ -7845,17 +7720,16 @@ my %nikonFocalConversions = (
7845
7720
  Format => 'undef[56]',
7846
7721
  SubDirectory => { TagTable => 'Image::ExifTool::NikonCustom::SettingsD4' },
7847
7722
  },
7848
- # note: DecryptLen currently set to 0x789
7849
7723
  );
7850
7724
 
7851
7725
  # shot information for the D4S firmware 1.01a (ref 28, encrypted)
7852
7726
  %Image::ExifTool::Nikon::ShotInfoD4S = (
7853
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7854
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
7727
+ PROCESS_PROC => \&ProcessNikonEncrypted,
7728
+ WRITE_PROC => \&ProcessNikonEncrypted,
7855
7729
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
7856
7730
  VARS => { ID_LABEL => 'Index' },
7857
7731
  DATAMEMBER => [ 4 ],
7858
- IS_SUBDIR => [ 0x189d, 0x193d ],
7732
+ IS_SUBDIR => [ 0x189d, 0x193d, 0x350b ],
7859
7733
  WRITABLE => 1,
7860
7734
  FIRST_ENTRY => 0,
7861
7735
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
@@ -8119,31 +7993,13 @@ my %nikonFocalConversions = (
8119
7993
  # },
8120
7994
  # },
8121
7995
  0x350b => {
8122
- Name => 'RollAngle',
8123
- Format => 'fixed32u',
8124
- Notes => 'converted to degrees of clockwise camera roll',
8125
- ValueConv => '$val < 180 ? -$val : 360 - $val',
8126
- ValueConvInv => '$val <= 0 ? -$val : 360 - $val',
8127
- PrintConv => 'sprintf("%.1f", $val)',
8128
- PrintConvInv => '$val',
8129
- },
8130
- 0x350f => {
8131
- Name => 'PitchAngle',
8132
- Format => 'fixed32u',
8133
- Notes => 'converted to degrees of upward camera tilt',
8134
- ValueConv => '$val <= 180 ? $val : $val - 360',
8135
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
8136
- PrintConv => 'sprintf("%.1f", $val)',
8137
- PrintConvInv => '$val',
8138
- },
8139
- 0x3513 => {
8140
- Name => 'YawAngle',
8141
- Format => 'fixed32u',
8142
- Notes => 'the camera yaw angle when shooting in portrait orientation',
8143
- ValueConv => '$val <= 180 ? $val : $val - 360',
8144
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
8145
- PrintConv => 'sprintf("%.1f", $val)',
8146
- PrintConvInv => '$val',
7996
+ Name => 'OrientationInfo',
7997
+ Format => 'undef[12]',
7998
+ SubDirectory => {
7999
+ # Note: pitch angle may be wrong sign for this model?
8000
+ # (pitch sign was changed without verification to use same decoding as other models)
8001
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
8002
+ },
8147
8003
  },
8148
8004
  0x3693 => {
8149
8005
  Name => 'Rotation',
@@ -8155,20 +8011,17 @@ my %nikonFocalConversions = (
8155
8011
  3 => 'Rotate 180',
8156
8012
  },
8157
8013
  },
8158
- # note: DecryptLen currently set to 0x3697
8159
8014
  );
8160
8015
 
8161
8016
  # shot information for the Z7II firmware 1.00 (encrypted) - ref 28
8162
8017
  %Image::ExifTool::Nikon::ShotInfoZ7II = (
8163
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
8164
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
8018
+ PROCESS_PROC => \&ProcessNikonEncrypted,
8019
+ WRITE_PROC => \&ProcessNikonEncrypted,
8165
8020
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
8166
- VARS => { ID_LABEL => 'Index' },
8167
- DATAMEMBER => [ 0x04, 0x30, 0x38, 0x98, 0xa0, 0x75e7, 0x760c,
8168
- 0x7610, 0x7eff, 0xce31, 0xcea5, 0xceb6, 0xceb7 ],
8169
- IS_SUBDIR => [ 0xceb8 ],
8021
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
8022
+ DATAMEMBER => [ 0x04 ],
8023
+ IS_SUBDIR => [ 0x30, 0x38, 0x98, 0xa0 ],
8170
8024
  WRITABLE => 1,
8171
- FIRST_ENTRY => 0,
8172
8025
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8173
8026
  NOTES => 'These tags are extracted from encrypted data in images from the Z7II.',
8174
8027
  0x00 => {
@@ -8197,79 +8050,73 @@ my %nikonFocalConversions = (
8197
8050
  },
8198
8051
  0x24 => {
8199
8052
  Name => 'NumberOffsets', # number of entries in offset table. offsets are from start of ShotInfo data.
8200
- DataMember => 'NumberOffsets',
8201
8053
  Format => 'int32u',
8202
8054
  Writable => 0,
8203
8055
  Hidden => 1,
8204
8056
  },
8205
8057
  0x30 => {
8206
- Name => 'Offset3',
8207
- DataMember => 'Offset3',
8058
+ Name => 'IntervalOffset',
8208
8059
  Format => 'int32u',
8209
- Writable => 0,
8210
- Hidden => 1,
8211
- RawConv => '$$self{Offset3} = $val || 0x10000000; undef', # (ignore if 0)
8060
+ SubDirectory => {
8061
+ TagTable => 'Image::ExifTool::Nikon::IntervalInfoZ7II',
8062
+ Start => '$val',
8063
+ }
8212
8064
  },
8213
8065
  0x38 => {
8214
- Name => 'Offset5',
8215
- DataMember => 'Offset5',
8066
+ Name => 'PortraitOffset',
8216
8067
  Format => 'int32u',
8217
- Writable => 0,
8218
- Hidden => 1,
8219
- RawConv => '$$self{Offset5} = $val || 0x10000000; undef', # (ignore if 0)
8068
+ SubDirectory => {
8069
+ TagTable => 'Image::ExifTool::Nikon::PortraitInfoZ7II',
8070
+ Start => '$val',
8071
+ }
8220
8072
  },
8221
8073
  0x98 => {
8222
8074
  Name => 'OrientationOffset',
8223
- DataMember => 'OrientationOffset',
8224
8075
  Format => 'int32u',
8225
- Writable => 0,
8226
- Hidden => 1,
8227
- RawConv => '$$self{OrientationOffset} = $val || 0x10000000; undef', # (ignore if 0)
8076
+ SubDirectory => {
8077
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
8078
+ Start => '$val',
8079
+ }
8228
8080
  },
8229
8081
  0xa0 => {
8230
- Name => 'Offset31',
8231
- DataMember => 'Offset31',
8082
+ Name => 'MenuOffset',
8232
8083
  Format => 'int32u',
8233
- Writable => 0,
8234
- Hidden => 1,
8235
- RawConv => '$$self{Offset31} = $val || 0x10000000; undef', # (ignore if 0)
8236
- },
8237
- ### 0x75e8 - Offset3 info start (Z7II firmware 1.30)
8238
- 0x75e7 => {
8239
- Name => 'Hook1',
8240
- Hidden => 1,
8241
- RawConv => 'undef',
8242
- # account for variable location of Offset3 data
8243
- Hook => '$varSize = $$self{Offset3} - 0x75e8',
8084
+ SubDirectory => {
8085
+ TagTable => 'Image::ExifTool::Nikon::MenuInfoZ7II',
8086
+ Start => '$val',
8087
+ },
8244
8088
  },
8245
- 0x760c => {
8089
+ );
8090
+
8091
+ %Image::ExifTool::Nikon::IntervalInfoZ7II = (
8092
+ %binaryDataAttrs,
8093
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8094
+ DATAMEMBER => [ 0x24, 0x28 ],
8095
+ 0x24 => {
8246
8096
  Name => 'IntervalShooting',
8247
8097
  RawConv => '$$self{IntervalShooting} = $val',
8248
8098
  Format => 'int16u',
8249
8099
  PrintConv => q{
8250
8100
  return 'Off' if $val == 0 ;
8251
- my $i = sprintf("Interval %.0f of %.0f",$val, $$self{IntervalShootingIntervals}); # something like "Interval 1 of 3"
8252
- my $f = $$self{IntervalShootingShotsPerInterval} > 1 ? sprintf(" Frame %.0f of %.0f",$$self{IntervalFrame}, $$self{IntervalShootingShotsPerInterval}): '' ; # something like "Frame 1 of 3" or blank
8101
+ my $i = sprintf("Interval %.0f of %.0f",$val, $$self{IntervalShootingIntervals}||0); # something like "Interval 1 of 3"
8102
+ my $f = ($$self{IntervalShootingShotsPerInterval}||0) > 1 ? sprintf(" Frame %.0f of %.0f",$$self{IntervalFrame}||0, $$self{IntervalShootingShotsPerInterval}||0): '' ; # something like "Frame 1 of 3" or blank
8253
8103
  return "On: $i$f"
8254
- #$val == 0 ? 'Off' : sprintf("On: Interval %.0f of %.0f Frame %.0f of %.0f",$val, $$self{IntervalShootingIntervals}, $$self{IntervalFrame}, $$self{IntervalShootingShotsPerInterval}),
8104
+ #$val == 0 ? 'Off' : sprintf("On: Interval %.0f of %.0f Frame %.0f of %.0f",$val, $$self{IntervalShootingIntervals}||0, $$self{IntervalFrame}||0, $$self{IntervalShootingShotsPerInterval}||0),
8255
8105
  },
8256
8106
  },
8257
- 0x7610 => {
8107
+ 0x28 => {
8258
8108
  Name => 'IntervalFrame',
8259
8109
  RawConv => '$$self{IntervalFrame} = $val',
8260
8110
  Condition => '$$self{IntervalShooting} > 0',
8261
8111
  Format => 'int16u',
8262
8112
  Hidden => 1,
8263
8113
  },
8264
- ### 0x7f00 - Offset5 info start (Z7II firmware 1.30)
8265
- 0x7eff => {
8266
- Name => 'Hook2',
8267
- Hidden => 1,
8268
- RawConv => 'undef',
8269
- # account for variable location of Offset5 data
8270
- Hook => '$varSize = $$self{Offset5} - 0x7f00',
8271
- },
8272
- 0x7fa0 => { #28
8114
+ );
8115
+
8116
+ %Image::ExifTool::Nikon::PortraitInfoZ7II = (
8117
+ %binaryDataAttrs,
8118
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8119
+ 0xa0 => { #28
8273
8120
  Name => 'PortraitImpressionBalance', # will be 0 for firmware 1.21 and earlier; firmware 1.30 onward: will be set by Photo Shooting Menu entry Portrait Impression Balance
8274
8121
  # offset5+160; 128 is neutral; >128 increases Yellow; <128 increases Magenta; increments of 4 result from 1 full unit adjustment on the camera
8275
8122
  # offset5+161 128 is neutral; >128 increases Brightness; <128 decreases Brightness
@@ -8285,83 +8132,31 @@ my %nikonFocalConversions = (
8285
8132
  return "$color $brightness"
8286
8133
  },
8287
8134
  },
8288
- ### 0xce32 - OrientationInfo start (Z7II firmware 1.00)
8289
- 0xce31 => {
8290
- Name => 'Hook3',
8291
- Hidden => 1,
8292
- RawConv => 'undef',
8293
- # account for variable location of OrientationInfo data
8294
- Hook => '$varSize = $$self{OrientationOffset} - 0xce32',
8295
- },
8135
+ );
8296
8136
 
8297
- 0xce32 => {
8298
- Name => 'RollAngle',
8299
- Format => 'fixed32u',
8300
- Notes => 'converted to degrees of clockwise camera roll',
8301
- ValueConv => '$val <= 180 ? $val : $val - 360',
8302
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
8303
- PrintConv => 'sprintf("%.1f", $val)',
8304
- PrintConvInv => '$val',
8305
- },
8306
- 0xce36 => {
8307
- Name => 'PitchAngle',
8308
- Format => 'fixed32u',
8309
- Notes => 'converted to degrees of upward camera tilt',
8310
- ValueConv => '$val <= 180 ? $val : $val - 360',
8311
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
8312
- PrintConv => 'sprintf("%.1f", $val)',
8313
- PrintConvInv => '$val',
8314
- },
8315
- 0xce3a => {
8316
- Name => 'YawAngle',
8317
- Format => 'fixed32u',
8318
- Notes => 'the camera yaw angle when shooting in portrait orientation',
8319
- ValueConv => '$val <= 180 ? $val : $val - 360',
8320
- ValueConvInv => '$val >= 0 ? $val : $val + 360',
8321
- PrintConv => 'sprintf("%.1f", $val)',
8322
- PrintConvInv => '$val',
8323
- },
8324
- 0xcea5 => {
8325
- Name => 'Hook4',
8326
- Hidden => 1,
8327
- RawConv => 'undef',
8328
- # account for variable location of Offset31 data
8329
- Hook => '$varSize = $$self{Offset31} - 0xcea6',
8330
- },
8331
- ### 0xcea6 - Offset31 info start (Z7II firmware 1.30)
8332
- 0xceb6 => {
8333
- Name => 'MenuSettingsZ7IIOffset',
8334
- # offset to MenuSettingsZ7II is relative to start of Offset31 block
8335
- RawConv => '$$self{MenuSettingsZ7IIOffset} = ($val || 0x10000000) + $$self{Offset31}; undef', # (ignore if 0)
8336
- },
8337
- 0xceb7 => {
8338
- Name => 'Hook5',
8339
- Hidden => 1,
8340
- RawConv => 'undef',
8341
- # account for variable location of Offset5 data
8342
- Hook => '$varSize = $$self{MenuSettingsZ7IIOffset} - 0xceb8',
8343
- },
8344
- 0xceb8 => { # (this is 0xd04e for the Z50)
8345
- Name => 'MenuSettingsZ7II',
8346
- Format => 'undef[860]',
8137
+ %Image::ExifTool::Nikon::MenuInfoZ7II = (
8138
+ %binaryDataAttrs,
8139
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8140
+ IS_SUBDIR => [ 0x10 ],
8141
+ 0x10 => {
8142
+ Name => 'MenuSettingsOffsetZ7II',
8143
+ Format => 'int32u',
8347
8144
  SubDirectory => {
8348
8145
  TagTable => 'Image::ExifTool::Nikon::MenuSettingsZ7II',
8146
+ Start => '$dirStart + $val',
8349
8147
  },
8350
- }
8351
- # note: DecryptLen currently set to 0xd04e + 860 (offset for Z50 is 0xd04e)
8148
+ },
8352
8149
  );
8353
8150
 
8354
8151
  # shot information for the Z9 firmware 1.00 (encrypted) - ref 28
8355
8152
  %Image::ExifTool::Nikon::ShotInfoZ9 = (
8356
- PROCESS_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
8357
- WRITE_PROC => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
8153
+ PROCESS_PROC => \&ProcessNikonEncrypted,
8154
+ WRITE_PROC => \&ProcessNikonEncrypted,
8358
8155
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
8359
- VARS => { ID_LABEL => 'Index' },
8360
- DATAMEMBER => [ 0x04, 0x30, 0x84, 0x8c,0x93, 0xb4, 0xbc, 0xbe,
8361
- 0x4410, 0x4411, 0x80c4, 0x8149, 0x814a ],
8362
- IS_SUBDIR => [ 0x44ec, 0x8225 ],
8156
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
8157
+ DATAMEMBER => [ 0x04 ],
8158
+ IS_SUBDIR => [ 0x30, 0x58, 0x84, 0x8c ],
8363
8159
  WRITABLE => 1,
8364
- FIRST_ENTRY => 0,
8365
8160
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8366
8161
  NOTES => 'These tags are extracted from encrypted data in images from the Z9.',
8367
8162
  0x00 => {
@@ -8390,47 +8185,55 @@ my %nikonFocalConversions = (
8390
8185
  },
8391
8186
  0x24 => {
8392
8187
  Name => 'NumberOffsets', # number of entries in offset table. offsets are from start of ShotInfo data.
8393
- DataMember => 'NumberOffsets',
8394
8188
  Format => 'int32u',
8395
8189
  Writable => 0,
8396
8190
  Hidden => 1,
8397
8191
  },
8192
+ # subdirectories, referenced by offsets (not processed if offset is zero)
8398
8193
  0x30 => {
8399
- Name => 'SequenceOffset', #offset3 - length 2528 (Z9 firmware 1.0)
8400
- DataMember => 'SequenceOffset',
8194
+ Name => 'SequenceOffset',
8401
8195
  Format => 'int32u',
8402
- Writable => 0,
8403
- Hidden => 1,
8404
- RawConv => '$$self{SequenceOffset} = $val || 0x10000000; undef', # (ignore if 0)
8196
+ SubDirectory => {
8197
+ TagTable => 'Image::ExifTool::Nikon::SeqInfoZ9',
8198
+ Start => '$val',
8199
+ },
8200
+ },
8201
+ 0x58 => {
8202
+ Name => 'Offset13', #offset13 - length x'8f80 (Z9 firmware 3.01 NEF), using currently for a few foucs related tags. Might be premature to give the offset a more meaningful name at this point.
8203
+ Condition => '$$self{FirmwareVersion} and $$self{FirmwareVersion} ge "03.01"',
8204
+ Format => 'int32u',
8205
+ SubDirectory => {
8206
+ TagTable => 'Image::ExifTool::Nikon::Offset13InfoZ9',
8207
+ Start => '$val',
8208
+ },
8405
8209
  },
8406
8210
  0x84 => {
8407
- Name => 'OrientationOffset', #offset24 - length 108 (Z9 firmware 1.0)
8408
- DataMember => 'OrientationOffset',
8211
+ Name => 'OrientOffset',
8212
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8409
8213
  Format => 'int32u',
8410
- Writable => 0,
8411
- Hidden => 1,
8412
- RawConv => '$$self{OrientationOffset} = $val || 0x10000000; undef', # (ignore if 0)
8214
+ SubDirectory => {
8215
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
8216
+ Start => '$val',
8217
+ },
8413
8218
  },
8414
8219
  0x8c => {
8415
- Name => 'MenuOffset', #offset26 - length 1895 (Z9 firmware 1.0)
8416
- DataMember => 'MenuOffset6',
8220
+ Name => 'MenuOffset',
8417
8221
  Format => 'int32u',
8418
- Writable => 0,
8419
- Hidden => 1,
8420
- RawConv => '$$self{MenuOffset} = $val || 0x10000000; undef', # (ignore if 0)
8421
- },
8422
- ### 0x0094 - SequenceOffset info start (Z9 firmware 1.00)
8423
- 0x0093 => {
8424
- Name => 'SequenceOffsetHook',
8425
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8426
- Hidden => 1,
8427
- RawConv => 'undef',
8428
- # account for variable location of SequenceOffset data
8429
- Hook => '$varSize = $$self{SequenceOffset} - 0x0094',
8222
+ SubDirectory => {
8223
+ TagTable => 'Image::ExifTool::Nikon::MenuInfoZ9',
8224
+ Start => '$val',
8225
+ },
8430
8226
  },
8431
- 0x00b4 => {
8227
+ );
8228
+
8229
+ # ref 28
8230
+ %Image::ExifTool::Nikon::SeqInfoZ9 = (
8231
+ %binaryDataAttrs,
8232
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8233
+ DATAMEMBER => [ 0x20, 0x28, 0x2a ],
8234
+ 0x0020 => {
8432
8235
  Name => 'FocusShiftShooting',
8433
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8236
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8434
8237
  RawConv => '$$self{FocusShiftShooting} = $val',
8435
8238
  PrintConv => q{
8436
8239
  return 'Off' if $val == 0 ;
@@ -8438,86 +8241,215 @@ my %nikonFocalConversions = (
8438
8241
  return "On: $i"
8439
8242
  },
8440
8243
  },
8441
- 0x00bc => {
8244
+ 0x0028 => {
8442
8245
  Name => 'IntervalShooting',
8443
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8246
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8444
8247
  RawConv => '$$self{IntervalShooting} = $val',
8445
8248
  Format => 'int16u',
8446
8249
  PrintConv => q{
8447
8250
  return 'Off' if $val == 0 ;
8448
- my $i = sprintf("Interval %.0f of %.0f",$val, $$self{IntervalShootingIntervals}); # something like "Interval 1 of 3"
8449
- my $f = $$self{IntervalShootingShotsPerInterval} > 1 ? sprintf(" Frame %.0f of %.0f",$$self{IntervalFrame}, $$self{IntervalShootingShotsPerInterval}): '' ; # something like "Frame 1 of 3" or blank
8251
+ my $i = sprintf("Interval %.0f of %.0f",$val, $$self{IntervalShootingIntervals}||0); # something like "Interval 1 of 3"
8252
+ my $f = ($$self{IntervalShootingShotsPerInterval}||0) > 1 ? sprintf(" Frame %.0f of %.0f",$$self{IntervalFrame}||0, $$self{IntervalShootingShotsPerInterval}||0): '' ; # something like "Frame 1 of 3" or blank
8450
8253
  return "On: $i$f"
8451
- #$val == 0 ? 'Off' : sprintf("On: Interval %.0f of %.0f Frame %.0f of %.0f",$val, $$self{IntervalShootingIntervals}, $$self{IntervalFrame}, $$self{IntervalShootingShotsPerInterval}),
8254
+ #$val == 0 ? 'Off' : sprintf("On: Interval %.0f of %.0f Frame %.0f of %.0f",$val, $$self{IntervalShootingIntervals}||0, $$self{IntervalFrame}||0, $$self{IntervalShootingShotsPerInterval}||0),
8452
8255
  },
8453
8256
  },
8454
- 0x00be => {
8455
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8257
+ 0x002a => {
8456
8258
  Name => 'IntervalFrame',
8457
8259
  RawConv => '$$self{IntervalFrame} = $val',
8458
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8260
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8459
8261
  Format => 'int16u',
8460
8262
  Hidden => 1,
8461
8263
  },
8462
- ### 0x4400 - Offset26 info start (Z9 firmware 3.01 C30/C60/C120 )
8463
- 0x4410 => {
8464
- Name => 'MenuSettingsZ9Offset',
8465
- Condition => '$$self{ShutterMode} eq 96', # C30/C60/C120 jpgs only
8466
- Writable => 0,
8467
- Hidden => 1,
8468
- # offset to MenuSettingsZ9 is relative to start of Offset26 block
8469
- RawConv => '$$self{MenuSettingsZ9Offset} = ($val || 0x10000000) + $$self{MenuOffset}; undef', # (ignore if 0)
8264
+ );
8265
+
8266
+ # ref 28
8267
+ %Image::ExifTool::Nikon::Offset13InfoZ9 = (
8268
+ %binaryDataAttrs,
8269
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8270
+ DATAMEMBER => [ 0x0bea, 0x0beb ],
8271
+ 0x0be8 => {
8272
+ Name => 'AFAreaInitialXPosition', #stored as a representation of the horizontal position of the center of the portion of the focus box positioned top left when in Wide Area (L/S/C1/C2) focus modes (before subject detection potentially refines focus)
8273
+ Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2 ', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8274
+ Format => 'int8s',
8275
+ PrintConv => q{
8276
+ #in FX mode and Single-point, the 29 horizontal focus points are spaced 259 pixels apart starting at pixel 502 and ending at 7754. Spacing is the same for Wide(L/C1/C2) with different start points.
8277
+ #in FX mode and Dynamic(L), the 27 horizontal focus points are spaced 259 pixels apart starting at pixel 761 and ending at 7495
8278
+ #in FX mode and Dynamic(M), the 29 horizontal focus points are spaced 259 pixels apart starting at pixel 502 and ending at 7754
8279
+ #in DX mode and Single-point, the 19 horizontal focus points are spaced 388 pixels apart starting at pixel 636 and ending at 7620. [These correspond to FX positions and match the corresponding values in AFAreaMode tag AFAreaXPosition].
8280
+ #in DX mode and Wide(S), the 17 horizontal focus points are spaced 393 pixels apart starting at pixel 591 and ending at 7272.
8281
+ #in DX mode and Dynamic(L), the 17 horizontal focus points are spaced 388 pixels apart starting at pixel 1024 and ending at 7232
8282
+ #in DX mode and Dynamic(M), the 19 horizontal focus points are spaced 388 pixels apart starting at pixel 636 and ending at 7620
8283
+
8284
+ my $areaMode = $$self{VALUE}{PhotoShootingMenuBankImageArea};
8285
+ my $afAreaMode = $$self{VALUE}{AFAreaMode};
8286
+ my $dynamicAFAreaSize = $$self{VALUE}{DynamicAFAreaSize};
8287
+
8288
+ my $FX = 0;
8289
+ my $DX = 1;
8290
+
8291
+ my $Single = 1;
8292
+ my $Dynamic = 2;
8293
+ my $WideS = 3;
8294
+ my $WideL = 4;
8295
+ my $ThreeD = 5;
8296
+ my $Auto = 6;
8297
+ my $WideC1 = 12;
8298
+
8299
+ my $DynamicS = 0;
8300
+ my $DynamicM = 1;
8301
+ my $DynamicL = 2;
8302
+
8303
+ my $start = 502; #FX - all flavors
8304
+ $start = 636 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic (L/M/S) + 3D + Auto
8305
+ $start = 591 if $areaMode == $DX and $afAreaMode == $WideS ; #DX Wide(S)
8306
+
8307
+ my $increment = 259; #FX - all flavors
8308
+ $increment = 388 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic (L/M/S) + 3D + Auto
8309
+ $increment = 393 if $areaMode == $DX and $afAreaMode == $WideS ; #DX Wide(S)
8310
+
8311
+ my $divisor = 4;
8312
+ $divisor = 6 if $areaMode == $DX ;
8313
+
8314
+ my $offsetVal = 0;
8315
+ $offsetVal = 12 if $areaMode == $FX and $afAreaMode == $Dynamic ; #FX Dynamic (L/M) - force positive values so perl rounding toward zero isn't an issue
8316
+ $offsetVal = 18 if $areaMode == $DX and $afAreaMode == $Dynamic ; #DX Dynamic (L/M)
8317
+
8318
+ my $offsetSum = -1;
8319
+ $offsetSum = -4 if $afAreaMode == $Dynamic ; # Dynamic (L/M)
8320
+
8321
+ my $ncol = $$self{AFAreaInitialWidth};
8322
+ $ncol = int($ncol * 2 / 3) if $areaMode == $DX ; #DX
8323
+
8324
+ #some sample mappings:
8325
+ #FX Wide(S/L/C1/C2) [6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117] to 502, 761, 1020, 1279, 1538, 1797, 2056, 2315, 2574, 2833, 3092, 3351, 3610, 3869, 4128, 4387, 4646, 4905, 5164, 5423, 5682, 5941, 6200, 6459, 6718, 6977, 7236, 7495, 7754]
8326
+ #DX Wide(L/C1/C2) map for Wide(L)/C1/C2 [6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 67, 73, 79, 85, 91, 97, 103, 109, 115] to [636, 1024, 1412, 1800, 2188, 2576, 2964, 3352, 3740, 4128, 4516, 4904, 5292, 5680, 6068, 6456, 6844, 7232, 7620]
8327
+ #DX Wide(S) for Wide(S) [6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 67, 73, 79, 85, 91, 97, 103] to [984, 1377, 1770, 2163, 2556, 2949, 3342, 3735, 4128, 4521, 4914, 5307, 5700, 6093, 6486, 6879, 7272]
8328
+ #FX Dynamic (L) map [-9, -5, -1, 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93] to [761, 1020, 1279, 1538, 1797, 2056, 2315, 2574, 2833, 3092, 3351, 3610, 3869, 4128, 4387, 4646, 4905, 5164, 5423, 5682, 5941, 6200, 6459, 6718, 6977, 7236, 7495]
8329
+
8330
+ return $start + $increment * (int(($val + $offsetVal) / $divisor) + int($ncol / 2) + $offsetSum) ; #do not use simple int() becuase it rounds negative fractions toward zero resulting in duplicate values - instead use the 10xdivisor to force positive values
8331
+ },
8332
+ },
8333
+ 0x0be9 => {
8334
+ Name =>'AFAreaInitialYPosition', #stored as a representation of the vertical position of the center of the portion of the focus box positioned top left when in Wide Area (L/S/C1/C2) focus modes (before subject detection potentially refines focus)
8335
+ Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8336
+ Format => 'int8s',
8337
+ PrintConv => q{
8338
+ #in FX mode and Single-point, the 17 vertical focus points are spaced 291 pixels apart starting at pixel 424 and ending at 5080. Spacing is the same for Wide(L/C1/C2)
8339
+ #in FX mode and Dynamic(L), the 15 vertical focus points are spaced 291 pixels apart starting at pixel 715 and ending at 4789
8340
+ #in FX mode and Dynamic(M), the 17 vertical l focus points are spaced 291 pixels apart starting at pixel 424 and ending at 5080
8341
+ #in DX mode and Single-point, the 11 vertical focus points are spaced 436 pixels apart starting at pixel 572 and ending at 4932. [These correspond to FX positions and match the corresponding values in AFAreaMode tag AFAreaYPosition].
8342
+ #in DX Mode and Wide(S) the 9 vertical focus points are spaced 442 pixels apart starting at pixel 542 and ending at 4520
8343
+ #in DX mode and Dynamic(L), the 9 vertical focus points are spaced 436 pixels apart starting at pixel 1008 and ending at 4496
8344
+
8345
+ my $areaMode = $$self{VALUE}{PhotoShootingMenuBankImageArea};
8346
+ my $afAreaMode = $$self{VALUE}{AFAreaMode};
8347
+ my $dynamicAFAreaSize = $$self{VALUE}{DynamicAFAreaSize};
8348
+
8349
+ my $FX = 0;
8350
+ my $DX = 1;
8351
+
8352
+ my $Single = 1;
8353
+ my $Dynamic = 2;
8354
+ my $WideS = 3;
8355
+ my $WideL = 4;
8356
+ my $ThreeD = 5;
8357
+ my $Auto = 6;
8358
+ my $WideC1 = 12;
8359
+
8360
+ my $DynamicS = 0;
8361
+ my $DynamicM = 1;
8362
+ my $DynamicL = 2;
8363
+
8364
+ my $start = 424; #FX - all flavors
8365
+ $start = 572 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic(L/M/S) + 3D + Auto
8366
+ $start = 542 if $areaMode == $DX and $afAreaMode == 3 ; #DX Wide(S)
8367
+
8368
+ my $increment = 291; #FX - all flavors
8369
+ $increment = 436 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic (L/M/S) +3D + Auto
8370
+ $increment = 442 if $areaMode == $DX and $afAreaMode == 3 ; #DX Wide(S)
8371
+
8372
+ my $divisor = 7;
8373
+ $divisor = 10 if $areaMode == $DX ; #DX
8374
+
8375
+ my $offsetVal = -1;
8376
+ $offsetVal = 39 if $afAreaMode == $Dynamic and ( $dynamicAFAreaSize == $DynamicL ) ; #Dynamic (L) - force positive values so perl rounding toward zero isn't an issue
8377
+ $offsetVal = 40 if $afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicM ; #Dynamic (M)
8378
+ $offsetVal = 40 if $areaMode == $FX and (($afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicS) or $afAreaMode == $ThreeD) ; #FX Dynamic (S) or 3D
8379
+ $offsetVal = 38 if $areaMode == $DX and ($afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicS ) ; #DX Dynamic (S)or 3D
8380
+
8381
+ my $offsetSum = 0;
8382
+ $offsetSum = -6 if $areaMode == $FX and ($afAreaMode == $Dynamic or $afAreaMode == $ThreeD); #FX Dynamic (L/M/S) or 3D
8383
+ $offsetSum = -4 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $ThreeD ); #DX Dynamic (L/M/S) or 3D
8384
+
8385
+ my $nrow = $$self{AFAreaInitialHeight};
8386
+ $nrow = int($nrow * 2 / 3) if $areaMode == $DX; #DX
8387
+
8388
+ #some sample mappings:
8389
+ #FX Wide(S/L/C1/C2) map [7, 13, 20, 27, 33, 40, 47, 53, 60, 67, 74, 80, 87, 94, 100, 107, 114] to [424, 715, 1006, 1297, 1588, 1879, 2170, 2461, 2752, 3043, 3334, 3625, 3916, 4207, 4498, 4789, 5080]
8390
+ #DX Wide(L/C1/C2) map [7, 17, 28, 38, 48, 58, 69, 79, 89, 100, 110] to [572, 1008, 1444, 1880, 2316, 2752, 3188, 3624, 4060, 4496, 4932]
8391
+ #DX Wide(S) map for Wide(S) [7, 17, 28, 38, 48, 58, 69, 79, 89] to [984, 1426, 1868, 2310, 2752, 3194, 3636, 4078, 4520]
8392
+ #FX Dynamic (L) map [-19, -13, -6, 0, 7, 13, 20, 27, 33, 40, 47, 53, 60, 67, 74] to [715, 1006, 1297, 1588, 1879, 2170, 2461, 2752, 3043, 3334, 3625, 3916, 4207, 4498, 4789]
8393
+
8394
+ return $start + $increment * (int(($val + $offsetVal) / $divisor) + int($nrow / 2) + $offsetSum) ;;
8395
+ },
8396
+ },
8397
+ 0x0bea => {
8398
+ Name => 'AFAreaInitialWidth',
8399
+ Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8400
+ ValueConv => '$$self{VALUE}{PhotoShootingMenuBankImageArea} eq 0 ? $val : int($val * 2 / 3)', #DX mode requires scaling down TODO: add support ImageAreas 1:1 and 16:9
8401
+ RawConv => '$$self{AFAreaInitialWidth} = 1 + int ($val / 4)', #convert from [3, 11, 19, 35, 51, 75] to [1, 3, 5, 9 13, 19] to match camera options for C1/C2 focus modes .. input/output of 11/3 is for Wide(S)
8470
8402
  },
8471
- 0x4411 => {
8472
- Name => 'Hook5',
8473
- Condition => '$$self{ShutterMode} eq 96', # C30/C60/C120 jpgs only
8474
- Hidden => 1,
8475
- RawConv => 'undef',
8476
- # account for variable location of menu settings data
8477
- Hook => '$varSize = $$self{MenuSettingsZ9Offset} - 0x44ec',
8403
+ 0x0beb => {
8404
+ Name => 'AFAreaInitialHeight',
8405
+ Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8406
+ ValueConv => '$$self{VALUE}{PhotoShootingMenuBankImageArea} eq 0 ? $val : int($val * 2 / 3)', #DX mode requires scaling down TODO: add support ImageAreas 1:1 and 16:9
8407
+ RawConv => '$$self{AFAreaInitialHeight} = 1 + int ($val / 7) ', #convert from [6, 20, 33, 46, 73] to [1, 3, 5, 7, 11] to match camera options for C1/C2 focus modes .. input/output of 33/5 is for Wide(L)
8478
8408
  },
8479
- 0x44ec => [
8409
+ );
8410
+
8411
+ %Image::ExifTool::Nikon::MenuInfoZ9 = (
8412
+ %binaryDataAttrs,
8413
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8414
+ IS_SUBDIR => [ 0x10 ],
8415
+ # 0x00 - int32u size of this directory
8416
+ 0x10 => [
8480
8417
  {
8481
- Name => 'MenuSettingsZ9',
8482
- Condition => '$$self{ShutterMode} eq 96 and $$self{FirmwareVersion} lt "03.00"', # C30/C60/C120 jpgs only
8483
- Format => 'undef[1646]',
8418
+ Name => 'MenuSettingsOffsetZ9',
8419
+ Condition => '$$self{FirmwareVersion} and $$self{FirmwareVersion} lt "03.00"',
8420
+ Format => 'int32u',
8484
8421
  Notes => 'Firmware versions 2.11 and earlier',
8485
8422
  SubDirectory => {
8486
8423
  TagTable => 'Image::ExifTool::Nikon::MenuSettingsZ9',
8424
+ Start => '$dirStart + $val',
8487
8425
  },
8488
8426
  },
8489
8427
  {
8490
- Name => 'MenuSettingsZ9',
8428
+ Name => 'MenuSettingsOffsetZ9v3',
8491
8429
  Notes => 'Firmware versions 3.0 and later',
8492
- Condition => '$$self{ShutterMode} eq 96', # C30/C60/C120 jpgs only
8493
- Format => 'undef[1948]',
8430
+ Format => 'int32u',
8494
8431
  SubDirectory => {
8495
- TagTable => 'Image::ExifTool::Nikon::MenuSettingsZ9Firmware3',
8432
+ TagTable => 'Image::ExifTool::Nikon::MenuSettingsZ9v3',
8433
+ Start => '$dirStart + $val',
8496
8434
  },
8497
8435
  },
8498
8436
  ],
8499
- ### 0x80c5 - OrientationInfo start (Z9 firmware 3.01)
8500
- 0x80c4 => {
8501
- Name => 'OrientationHook',
8502
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8503
- Hidden => 1,
8504
- RawConv => 'undef',
8505
- # account for variable location of OrientationInfo data
8506
- Hook => '$varSize = $$self{OrientationOffset} - 0x80c5',
8507
- },
8508
- 0x80c5 => {
8437
+ );
8438
+
8439
+ %Image::ExifTool::Nikon::OrientationInfo = (
8440
+ %binaryDataAttrs,
8441
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8442
+ 0 => {
8509
8443
  Name => 'RollAngle',
8510
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8511
- Format => 'fixed32u',
8444
+ Format => 'fixed32u',
8512
8445
  Notes => 'converted to degrees of clockwise camera roll',
8513
8446
  ValueConv => '$val <= 180 ? $val : $val - 360',
8514
8447
  ValueConvInv => '$val >= 0 ? $val : $val + 360',
8515
8448
  PrintConv => 'sprintf("%.1f", $val)',
8516
8449
  PrintConvInv => '$val',
8517
8450
  },
8518
- 0x80c9 => {
8451
+ 4 => {
8519
8452
  Name => 'PitchAngle',
8520
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8521
8453
  Format => 'fixed32u',
8522
8454
  Notes => 'converted to degrees of upward camera tilt',
8523
8455
  ValueConv => '$val <= 180 ? $val : $val - 360',
@@ -8525,9 +8457,8 @@ my %nikonFocalConversions = (
8525
8457
  PrintConv => 'sprintf("%.1f", $val)',
8526
8458
  PrintConvInv => '$val',
8527
8459
  },
8528
- 0x80cd => {
8460
+ 8 => {
8529
8461
  Name => 'YawAngle',
8530
- Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8531
8462
  Format => 'fixed32u',
8532
8463
  Notes => 'the camera yaw angle when shooting in portrait orientation',
8533
8464
  ValueConv => '$val <= 180 ? $val : $val - 360',
@@ -8535,51 +8466,25 @@ my %nikonFocalConversions = (
8535
8466
  PrintConv => 'sprintf("%.1f", $val)',
8536
8467
  PrintConvInv => '$val',
8537
8468
  },
8538
- ### 0x8139 - Offset26 info start (Z9 firmware 3.01)
8539
- 0x8149 => {
8540
- Name => 'MenuSettingsZ9Offset',
8541
- Condition => '$$self{ShutterMode} ne 96', # C30/C60/C120 jpgs handled at 0x4410
8542
- Writable => 0,
8543
- Hidden => 1,
8544
- # offset to MenuSettingsZ9 is relative to start of Offset26 block
8545
- RawConv => '$$self{MenuSettingsZ9Offset} = ($val || 0x10000000) + $$self{MenuOffset}; undef', # (ignore if 0)
8546
- },
8547
- 0x814a => {
8548
- Name => 'Hook5',
8549
- Condition => '$$self{ShutterMode} ne 96', # C30/C60/C120 jpgs handled at 0x4410
8550
- Hidden => 1,
8551
- RawConv => 'undef',
8552
- # account for variable location of menu settings data
8553
- Hook => '$varSize = $$self{MenuSettingsZ9Offset} - 0x8225',
8554
- },
8555
- 0x8225 => [
8556
- {
8557
- Name => 'MenuSettingsZ9',
8558
- Condition => '$$self{ShutterMode} ne 96 and $$self{FirmwareVersion} lt "03.00"', # C30/C60/C120 jpgs handled at 0x4410
8559
- Format => 'undef[1646]',
8560
- Notes => 'Firmware versions 2.11 and earlier',
8561
- SubDirectory => {
8562
- TagTable => 'Image::ExifTool::Nikon::MenuSettingsZ9',
8563
- },
8564
- },
8565
- {
8566
- Name => 'MenuSettingsZ9',
8567
- Notes => 'Firmware versions 3.0 and later',
8568
- Condition => '$$self{ShutterMode} ne 96', # C30/C60/C120 jpgs handled at 0x4410
8569
- Format => 'undef[1948]',
8570
- SubDirectory => {
8571
- TagTable => 'Image::ExifTool::Nikon::MenuSettingsZ9Firmware3',
8572
- },
8573
- },
8574
- ],
8575
- # note: DecryptLen currently set to 0xec4b + 2196
8576
8469
  );
8577
8470
 
8578
8471
  %Image::ExifTool::Nikon::MenuSettingsZ7II = (
8579
8472
  %binaryDataAttrs,
8580
8473
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8581
- DATAMEMBER => [ 176, 180, 328, 352, 858 ],
8474
+ DATAMEMBER => [ 90, 176, 180, 328, 352, 858 ],
8582
8475
  NOTES => 'These tags are used by the Z5, Z6, Z7, Z6II, Z7II, Z50 and Zfc.',
8476
+ #48 SelfTimer' #0=> no 1=> yes works for Z7II firmware 1.40, but not 1.30. Follow-up required.
8477
+ 90 => {
8478
+ Name => 'SingleFrame', #0=> Single Frame 1=> one of the continuous modes
8479
+ Hidden => 1,
8480
+ RawConv => '$$self{SingleFrame} = $val',
8481
+ },
8482
+ 92 => {
8483
+ Name => 'ReleaseMode',
8484
+ #ValueConv => '$$self{SelfTimer} == 1 ? 4 : $$self{SingleFrame} == 0 ? 5 : $val', #map single frame and timer to a unique values for PrintConv. Activate when SelfTimer tag is clarified for cameras other than Z7II fw 1.40
8485
+ ValueConv => '$$self{SingleFrame} == 0 ? 5 : $val', #map single frame to a unique value for PrintConv
8486
+ PrintConv => \%releaseModeZ7,
8487
+ },
8583
8488
  160 => {
8584
8489
  Name => 'IntervalDurationHours',
8585
8490
  Format => 'int32u',
@@ -8800,7 +8705,7 @@ my %nikonFocalConversions = (
8800
8705
  %Image::ExifTool::Nikon::MenuSettingsZ9 = (
8801
8706
  %binaryDataAttrs,
8802
8707
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8803
- DATAMEMBER => [ 140, 188, 192, 232, 424, 534 ],
8708
+ DATAMEMBER => [ 140, 188, 192, 232, 424, 534, 576 ],
8804
8709
  IS_SUBDIR => [ 799 ],
8805
8710
  NOTES => 'These tags are used by the Z9.',
8806
8711
  #90 ISO
@@ -8814,34 +8719,34 @@ my %nikonFocalConversions = (
8814
8719
  Name => 'Intervals',
8815
8720
  Format => 'int32u',
8816
8721
  RawConv => '$$self{IntervalShootingIntervals} = $val',
8817
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8722
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8818
8723
  },
8819
8724
  192 => {
8820
8725
  Name => 'ShotsPerInterval',
8821
8726
  Format => 'int32u',
8822
8727
  RawConv => '$$self{IntervalShootingShotsPerInterval} = $val',
8823
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8728
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8824
8729
  },
8825
8730
  #220 NEFCompression 0=> 'Lossless' 1=> 'High Efficiency*' 4=> 'High Efficientcy'
8826
8731
  232 => {
8827
8732
  Name => 'FocusShiftNumberShots', #1-300
8828
8733
  RawConv => '$$self{FocusShiftNumberShots} = $val',
8829
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8734
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8830
8735
  },
8831
8736
  236 => {
8832
8737
  Name => 'FocusShiftStepWidth', #1(Narrow) to 10 (Wide)
8833
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8738
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8834
8739
  },
8835
8740
  240 => {
8836
8741
  Name => 'FocusShiftInterval',
8837
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8742
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8838
8743
  PrintConv => '$val == 1? "1 Second" : sprintf("%.0f Seconds",$val)',
8839
8744
  },
8840
8745
  244 => {
8841
8746
  Name => 'FocusShiftExposureLock',
8842
8747
  Unknown => 1,
8843
8748
  PrintConv => \%offOn,
8844
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8749
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8845
8750
  },
8846
8751
  274 => { Name => 'PhotoShootingMenuBank', PrintConv => \%banksZ9 },
8847
8752
  276 => { Name => 'ExtendedMenuBanks', PrintConv => \%offOn }, #single tag from both Photo & Video menus
@@ -8940,6 +8845,12 @@ my %nikonFocalConversions = (
8940
8845
  556 => { Name => 'SecondarySlotFunction', PrintConv => \%secondarySlotFunctionZ9 },
8941
8846
  572 => { Name => 'DXCropAlert', PrintConv => \%offOn },
8942
8847
  574 => { Name => 'SubjectDetection', PrintConv => \%subjectDetectionZ9 },
8848
+ 576 => {
8849
+ Name => 'DynamicAFAreaSize',
8850
+ Condition => '$$self{AFAraMode} = 2',
8851
+ RawConv => '$$self{DynamicAFAreaSize} = $val',
8852
+ PrintConv => \%dynamicAfAreaModesZ9,
8853
+ },
8943
8854
  604 => {
8944
8855
  Name => 'MovieImageArea',
8945
8856
  Unknown => 1,
@@ -8996,16 +8907,16 @@ my %nikonFocalConversions = (
8996
8907
  1565 => { Name => 'SetClockFromLocationData', PrintConv => \%offOn, Unknown => 1 },
8997
8908
  1572 => { Name => 'AirplaneMode', PrintConv => \%offOn, Unknown => 1 },
8998
8909
  1573 => { Name => 'EmptySlotRelease', PrintConv => { 0 => 'Disable Release', 1 => 'Enable Release' }, Unknown => 1 },
8999
- 1608 => { Name => 'EnergySavingMode', PrintConv =>\%offOn, Unknown => 1 },
8910
+ 1608 => { Name => 'EnergySavingMode', PrintConv => \%offOn, Unknown => 1 },
9000
8911
  1632 => { Name => 'RecordLocationData', PrintConv => \%offOn, Unknown => 1 },
9001
8912
  1636 => { Name => 'USBPowerDelivery', PrintConv => \%offOn, Unknown => 1 },
9002
8913
  1645 => { Name => 'SensorShield', PrintConv => { 0 => 'Stays Open', 1 => 'Closes' }, Unknown => 1 },
9003
8914
  );
9004
8915
 
9005
- %Image::ExifTool::Nikon::MenuSettingsZ9Firmware3 = ( #starts at Offset26 + 248
8916
+ %Image::ExifTool::Nikon::MenuSettingsZ9v3 = (
9006
8917
  %binaryDataAttrs,
9007
8918
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
9008
- DATAMEMBER => [ 154, 204, 208, 248, 444, 554 ],
8919
+ DATAMEMBER => [ 154, 204, 208, 248, 444, 554, 596 ],
9009
8920
  IS_SUBDIR => [ 847 ],
9010
8921
  NOTES => 'These tags are used by the Z9 firmware 3.00.',
9011
8922
  72 => {
@@ -9022,33 +8933,33 @@ my %nikonFocalConversions = (
9022
8933
  Name => 'Intervals',
9023
8934
  Format => 'int32u',
9024
8935
  RawConv => '$$self{IntervalShootingIntervals} = $val',
9025
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8936
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9026
8937
  },
9027
8938
  208 => {
9028
8939
  Name => 'ShotsPerInterval',
9029
8940
  Format => 'int32u',
9030
8941
  RawConv => '$$self{IntervalShootingShotsPerInterval} = $val',
9031
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8942
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9032
8943
  },
9033
8944
  248 => {
9034
8945
  Name => 'FocusShiftNumberShots', #1-300
9035
8946
  RawConv => '$$self{FocusShiftNumberShots} = $val',
9036
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8947
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9037
8948
  },
9038
8949
  252 => {
9039
8950
  Name => 'FocusShiftStepWidth', #1(Narrow) to 10 (Wide)
9040
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8951
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9041
8952
  },
9042
8953
  256 => {
9043
8954
  Name => 'FocusShiftInterval',
9044
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8955
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9045
8956
  PrintConv => '$val == 1? "1 Second" : sprintf("%.0f Seconds",$val)',
9046
8957
  },
9047
8958
  260 => {
9048
8959
  Name => 'FocusShiftExposureLock',
9049
8960
  Unknown => 1,
9050
8961
  PrintConv => \%offOn,
9051
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
8962
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9052
8963
  },
9053
8964
  290 => { Name => 'PhotoShootingMenuBank', PrintConv => \%banksZ9 },
9054
8965
  292 => { Name => 'ExtendedMenuBanks', PrintConv => \%offOn }, # single tag from both Photo & Video menus
@@ -9134,6 +9045,12 @@ my %nikonFocalConversions = (
9134
9045
  576 => { Name => 'SecondarySlotFunction', PrintConv => \%secondarySlotFunctionZ9 },
9135
9046
  592 => { Name => 'DXCropAlert', PrintConv => \%offOn },
9136
9047
  594 => { Name => 'SubjectDetection', PrintConv => \%subjectDetectionZ9 },
9048
+ 596 => {
9049
+ Name => 'DynamicAFAreaSize',
9050
+ Condition => '$$self{AFAraMode} = 2',
9051
+ RawConv => '$$self{DynamicAFAreaSize} = $val',
9052
+ PrintConv => \%dynamicAfAreaModesZ9,
9053
+ },
9137
9054
  636 => { Name => 'HighFrequencyFlickerReductionShooting', PrintConv => \%offOn, Unknown => 1 }, # new with firmware 3.0
9138
9055
  646 => {
9139
9056
  Name => 'MovieImageArea',
@@ -9192,7 +9109,7 @@ my %nikonFocalConversions = (
9192
9109
  1613 => { Name => 'SetClockFromLocationData', PrintConv => \%offOn, Unknown => 1 },
9193
9110
  1620 => { Name => 'AirplaneMode', PrintConv => \%offOn, Unknown => 1 },
9194
9111
  1621 => { Name => 'EmptySlotRelease', PrintConv => { 0 => 'Disable Release', 1 => 'Enable Release' }, Unknown => 1 },
9195
- 1656 => { Name => 'EnergySavingMode', PrintConv =>\%offOn, Unknown => 1 },
9112
+ 1656 => { Name => 'EnergySavingMode', PrintConv => \%offOn, Unknown => 1 },
9196
9113
  1680 => { Name => 'RecordLocationData', PrintConv => \%offOn, Unknown => 1 },
9197
9114
  1684 => { Name => 'USBPowerDelivery', PrintConv => \%offOn, Unknown => 1 },
9198
9115
  1693 => { Name => 'SensorShield', PrintConv => { 0 => 'Stays Open', 1 => 'Closes' }, Unknown => 1 },
@@ -9200,7 +9117,7 @@ my %nikonFocalConversions = (
9200
9117
  Name => 'FocusShiftAutoReset',
9201
9118
  Unknown => 1,
9202
9119
  PrintConv => \%offOn,
9203
- Condition => '$$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9120
+ Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96 and $$self{FocusShiftShooting} > 0', #not valid for C30/C60/C120
9204
9121
  },
9205
9122
  1810 => { #CSd4-a
9206
9123
  Name => 'PreReleaseBurstLength',
@@ -11258,8 +11175,8 @@ my %nikonFocalConversions = (
11258
11175
  Name => 'LensData0201',
11259
11176
  SubDirectory => {
11260
11177
  TagTable => 'Image::ExifTool::Nikon::LensData01',
11261
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11262
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11178
+ ProcessProc => \&ProcessNikonEncrypted,
11179
+ WriteProc => \&ProcessNikonEncrypted,
11263
11180
  DecryptStart => 4,
11264
11181
  },
11265
11182
  },
@@ -11268,8 +11185,8 @@ my %nikonFocalConversions = (
11268
11185
  Name => 'LensData0204',
11269
11186
  SubDirectory => {
11270
11187
  TagTable => 'Image::ExifTool::Nikon::LensData0204',
11271
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11272
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11188
+ ProcessProc => \&ProcessNikonEncrypted,
11189
+ WriteProc => \&ProcessNikonEncrypted,
11273
11190
  DecryptStart => 4,
11274
11191
  },
11275
11192
  },
@@ -11278,8 +11195,8 @@ my %nikonFocalConversions = (
11278
11195
  Name => 'LensData0400',
11279
11196
  SubDirectory => {
11280
11197
  TagTable => 'Image::ExifTool::Nikon::LensData0400',
11281
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11282
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11198
+ ProcessProc => \&ProcessNikonEncrypted,
11199
+ WriteProc => \&ProcessNikonEncrypted,
11283
11200
  DecryptStart => 4,
11284
11201
  },
11285
11202
  },
@@ -11288,8 +11205,8 @@ my %nikonFocalConversions = (
11288
11205
  Name => 'LensData0402',
11289
11206
  SubDirectory => {
11290
11207
  TagTable => 'Image::ExifTool::Nikon::LensData0402',
11291
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11292
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11208
+ ProcessProc => \&ProcessNikonEncrypted,
11209
+ WriteProc => \&ProcessNikonEncrypted,
11293
11210
  DecryptStart => 4,
11294
11211
  },
11295
11212
  },
@@ -11298,8 +11215,8 @@ my %nikonFocalConversions = (
11298
11215
  Name => 'LensData0403',
11299
11216
  SubDirectory => {
11300
11217
  TagTable => 'Image::ExifTool::Nikon::LensData0403',
11301
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11302
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11218
+ ProcessProc => \&ProcessNikonEncrypted,
11219
+ WriteProc => \&ProcessNikonEncrypted,
11303
11220
  DecryptStart => 4,
11304
11221
  },
11305
11222
  },
@@ -11308,8 +11225,8 @@ my %nikonFocalConversions = (
11308
11225
  Name => 'LensData0800',
11309
11226
  SubDirectory => {
11310
11227
  TagTable => 'Image::ExifTool::Nikon::LensData0800',
11311
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11312
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11228
+ ProcessProc => \&ProcessNikonEncrypted,
11229
+ WriteProc => \&ProcessNikonEncrypted,
11313
11230
  DecryptStart => 4,
11314
11231
  ByteOrder => 'LittleEndian',
11315
11232
  # 0x5a0c - NikonMeteringMode for some Z6 ver1.00 samples (ref PH)
@@ -11319,8 +11236,8 @@ my %nikonFocalConversions = (
11319
11236
  Name => 'LensDataUnknown',
11320
11237
  SubDirectory => {
11321
11238
  TagTable => 'Image::ExifTool::Nikon::LensDataUnknown',
11322
- ProcessProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11323
- WriteProc => \&Image::ExifTool::Nikon::ProcessNikonEncrypted,
11239
+ ProcessProc => \&ProcessNikonEncrypted,
11240
+ WriteProc => \&ProcessNikonEncrypted,
11324
11241
  DecryptStart => 4,
11325
11242
  },
11326
11243
  },
@@ -11512,6 +11429,7 @@ my %nikonFocalConversions = (
11512
11429
  # construct lens ID string as per ref 11
11513
11430
  ValueConv => 'sprintf("%.2X"." %.2X"x7, @raw)',
11514
11431
  PrintConv => \%nikonLensIDs,
11432
+ PrintInt => 1,
11515
11433
  },
11516
11434
  AutoFocus => {
11517
11435
  Require => {
@@ -11835,37 +11753,54 @@ my @xlat = (
11835
11753
  0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f ]
11836
11754
  );
11837
11755
 
11756
+ my ($ci0, $cj0, $ck0, $decryptStart); # decryption parameters
11757
+
11838
11758
  # Decrypt Nikon data block (ref 4)
11839
- # Inputs: 0) reference to data block, 1) serial number key, 2) shutter count key
11840
- # 4) optional start offset (default 0)
11841
- # 5) optional number of bytes to decode (default to the end of the data)
11759
+ # Inputs: 0) reference to data block, 1) optional start offset (default 0)
11760
+ # 2) optional number of bytes to decode (default to the end of the data)
11761
+ # 3) optional serial number key (undef to continue previous decryption)
11762
+ # 4) optional shutter count key
11842
11763
  # Returns: data block with specified data decrypted
11843
- sub Decrypt($$$;$$)
11764
+ # Notes: The first time this is called for a given encrypted data block the serial/count
11765
+ # keys must be defined, and $start must be the offset for initialization of the
11766
+ # decryption parameters (ie. the beginning of the encrypted data, which isn't
11767
+ # necessarily inside the data block if $len is zero). Subsequent calls for
11768
+ # the same data block do not specify the serial/count keys, and may be used
11769
+ # to decrypt data at any start point within the full data block.
11770
+ sub Decrypt($;$$$$)
11844
11771
  {
11845
- my ($dataPt, $serial, $count, $start, $len) = @_;
11846
- my ($i, $dat);
11772
+ my ($dataPt, $start, $len, $serial, $count) = @_;
11773
+ my ($ch, $cj, $ck);
11847
11774
 
11848
11775
  $start or $start = 0;
11849
11776
  my $maxLen = length($$dataPt) - $start;
11850
11777
  $len = $maxLen if not defined $len or $len > $maxLen;
11851
- return $$dataPt if $len <= 0;
11852
- my $key = 0;
11853
- for ($i=0; $i<4; ++$i) {
11854
- $key ^= ($count >> ($i*8)) & 0xff;
11778
+ if (defined $serial and defined $count) {
11779
+ # initialize decryption parameters
11780
+ my $key = 0;
11781
+ $key ^= ($count >> ($_*8)) & 0xff foreach 0..3;
11782
+ $ci0 = $xlat[0][$serial & 0xff];
11783
+ $cj0 = $xlat[1][$key];
11784
+ $ck0 = 0x60;
11785
+ undef $decryptStart;
11855
11786
  }
11856
- my $ci = $xlat[0][$serial & 0xff];
11857
- my $cj = $xlat[1][$key];
11858
- my $ck = 0x60;
11859
- my @data = unpack("x${start}C$len", $$dataPt);
11860
- foreach $dat (@data) {
11861
- $cj = ($cj + $ci * $ck) & 0xff;
11787
+ if (defined $decryptStart) {
11788
+ # initialize decryption parameters for this start position
11789
+ my $n = $start - $decryptStart;
11790
+ $cj = ($cj0 + $ci0 * ($n * $ck0 + ($n * ($n - 1))/2)) & 0xff;
11791
+ $ck = ($ck0 + $n) & 0xff;
11792
+ } else {
11793
+ $decryptStart = $start;
11794
+ ($cj, $ck) = ($cj0, $ck0);
11795
+ }
11796
+ return $$dataPt if $len <= 0;
11797
+ my @data = unpack('C*', substr($$dataPt, $start, $len));
11798
+ foreach $ch (@data) {
11799
+ $cj = ($cj + $ci0 * $ck) & 0xff;
11862
11800
  $ck = ($ck + 1) & 0xff;
11863
- $dat ^= $cj;
11801
+ $ch ^= $cj;
11864
11802
  }
11865
- my $end = $start + $len;
11866
- my $pre = $start ? substr($$dataPt, 0, $start) : '';
11867
- my $post = $end < length($$dataPt) ? substr($$dataPt, $end) : '';
11868
- return $pre . pack('C*',@data) . $post;
11803
+ return substr($$dataPt, 0, $start) . pack('C*', @data) . substr($$dataPt, $start+$len);
11869
11804
  }
11870
11805
 
11871
11806
  #------------------------------------------------------------------------------
@@ -12001,6 +11936,166 @@ sub ProcessNikonMOV($$$)
12001
11936
  return 1;
12002
11937
  }
12003
11938
 
11939
+ #------------------------------------------------------------------------------
11940
+ # Get offset of end-of-data for a tag
11941
+ # Inputs: 0) tag table ref, 1) tag ID, 2) true to not calculate end for a SubDirectory
11942
+ # Returns: offset of tag value end, undef if it can't be determined
11943
+ sub GetTagEnd($$;$)
11944
+ {
11945
+ my ($tagTablePtr, $tagID, $ignoreSubdir) = @_;
11946
+ my $tagInfo = $$tagTablePtr{$tagID};
11947
+ $tagInfo = $$tagInfo[0] if ref $tagInfo eq 'ARRAY';
11948
+ # (can't pre-determine position of offset-based subdirectories)
11949
+ return undef if $ignoreSubdir and $$tagInfo{SubDirectory};
11950
+ my $fmt = $$tagInfo{Format} || $$tagTablePtr{FORMAT} || 'int8u';
11951
+ my $nm = $fmt =~ s/\[(\d+)\]$// ? $1 : 1;
11952
+ my $sz = Image::ExifTool::FormatSize($fmt) or return undef;
11953
+ return int($tagID) + $sz * $nm;
11954
+ }
11955
+
11956
+ #------------------------------------------------------------------------------
11957
+ # Initialize SubDirectory KnownStart/KnownEnd limits of known tags (used in decryption)
11958
+ # Inputs: 0) tagInfo ref containing this SubDirectory, 2) tag table ref for encrypted subdir
11959
+ # Notes: KnownStart/KnownEnd are relative to the SubDirectory Start. If KnownStart/KnownEnd
11960
+ # aren't set then the entire data is decrypted, so all of this effort is just for speed.
11961
+ sub InitEncryptedSubdir($$)
11962
+ {
11963
+ my ($tagInfo, $tagTablePtr) = @_;
11964
+ #
11965
+ # for encrypted NIKON_OFFSETS tables we loop through all SubDirectory tags in this table
11966
+ # and set the KnownEnd for each of these according to the last tag in the child tables
11967
+ #
11968
+ my $vars = $$tagTablePtr{VARS};
11969
+ $vars or $vars = $$tagTablePtr{VARS} = { };
11970
+ if ($$vars{NIKON_OFFSETS} and not $$vars{NIKON_INITIALIZED}) {
11971
+ $$vars{NIKON_INITIALIZED} = 1;
11972
+ my $tagID;
11973
+ foreach $tagID (TagTableKeys($tagTablePtr)) {
11974
+ my $tagInfo = $$tagTablePtr{$tagID};
11975
+ next unless ref $tagInfo eq 'HASH';
11976
+ my $subdir = $$tagInfo{SubDirectory} or next;
11977
+ my $tbl = GetTagTable($$subdir{TagTable});
11978
+ my ($last) = sort { $b <=> $a } TagTableKeys($tbl); # (reverse sort)
11979
+ $$subdir{KnownEnd} = GetTagEnd($tbl, $last, 1);
11980
+ }
11981
+ }
11982
+ #
11983
+ # for other encrypted Nikon tables we set the KnownStart/KnownEnd entries in the
11984
+ # SubDirectory of the parent tag
11985
+ #
11986
+ unless ($$tagInfo{NikonInitialized}) {
11987
+ $$tagInfo{NikonInitialized} = 1;
11988
+ my $subdir = $$tagInfo{SubDirectory};
11989
+ my $start = $$subdir{DecryptStart} || 0;
11990
+ my $off = $$subdir{DirOffset};
11991
+ my @tagIDs = sort { $a <=> $b } TagTableKeys($tagTablePtr);
11992
+ if (defined $off) {
11993
+ $off += $start; # (DirOffset, if specified, is relative to DecryptStart)
11994
+ } else {
11995
+ # ignore tags that come before the start of encryption
11996
+ shift @tagIDs while @tagIDs and $tagIDs[0] < $start;
11997
+ $off = 0;
11998
+ }
11999
+ if (@tagIDs) {
12000
+ my ($first, $last) = @tagIDs[0,-1];
12001
+ my $lastInfo = $$tagTablePtr{$last};
12002
+ $lastInfo = $$lastInfo[0] if ref $lastInfo eq 'ARRAY';
12003
+ $$subdir{KnownStart} = int($first) + $off if $first + $off > $start;
12004
+ $$subdir{KnownEnd} = GetTagEnd($tagTablePtr, $last);
12005
+ if (defined $$subdir{KnownEnd}) {
12006
+ $$subdir{KnownEnd} += $off;
12007
+ } else {
12008
+ warn "Internal error setting KnownEnd for $$tagTablePtr{SHORT_NAME}\n";
12009
+ }
12010
+ } else {
12011
+ $$subdir{KnownStart} = $$subdir{KnownEnd} = $start;
12012
+ }
12013
+ }
12014
+ }
12015
+
12016
+ #------------------------------------------------------------------------------
12017
+ # Prepare to process NIKON_OFFSETS directory and decrypt necessary data
12018
+ # Inputs: 0) ExifTool ref, 1) data ref, 2) tag table ref, 3) decrypt start,
12019
+ # 4) decrypt mode (0=piecewise, 1=continuous to end of last known section, 2=all)
12020
+ # Returns: end of decrypted data (or undef for piecewise decryption)
12021
+ sub PrepareNikonOffsets($$$$$)
12022
+ {
12023
+ my ($et, $dataPt, $tagTablePtr, $start, $decryptMode) = @_;
12024
+ my $offset = $$tagTablePtr{VARS}{NIKON_OFFSETS};
12025
+ my $dataLen = length $$dataPt;
12026
+ return undef if $offset + 4 > $dataLen or $offset < $start;
12027
+ my $serial = $$et{NikonSerialKey};
12028
+ my $count = $$et{NikonCountKey};
12029
+ my $dpos = $offset + 4; # decrypt up to NumberOffsets
12030
+ $$dataPt = Decrypt($dataPt, $start, $dpos - $start, $serial, $count);
12031
+ my $numOffsets = Get32u($dataPt, $offset);
12032
+ my $more = $numOffsets * 4; # more bytes to decrypt entire offsets table
12033
+ return undef if $offset + 4 + $more > $dataLen;
12034
+ $$dataPt = Decrypt($dataPt, $dpos, $more);
12035
+ $dpos += $more;
12036
+ my $unknown = $et->Options('Unknown');
12037
+ my ($i, @offInfo, $end);
12038
+ # extract non-zero offsets and create unknown subdirectories if Unknown > 1
12039
+ for ($i=0; $i<$numOffsets; ++$i) {
12040
+ my $pos = $offset + 4 + 4 * $i;
12041
+ my $off = Get32u($dataPt, $pos) or next;
12042
+ my $tagInfo = $$tagTablePtr{$pos};
12043
+ my $known = 0;
12044
+ if ($tagInfo) {
12045
+ $known = 1 if ref $tagInfo ne 'HASH' or not $$tagInfo{Unknown};
12046
+ } elsif ($unknown > 1) {
12047
+ # create new table for unknown information
12048
+ my $tbl = sprintf('Image::ExifTool::Nikon::UnknownInfo%.2x', $pos);
12049
+ no strict 'refs';
12050
+ unless (%$tbl) {
12051
+ %$tbl = ( %binaryDataAttrs, GROUPS => { 0=>'MakerNotes', 2=>'Unknown' } );
12052
+ GetTagTable($tbl);
12053
+ }
12054
+ # add unknown entry in offset table for this subdirectory
12055
+ $tagInfo = AddTagToTable($tagTablePtr, $pos, {
12056
+ Name => sprintf('UnknownOffset%.2x', $pos),
12057
+ Format => 'int32u',
12058
+ SubDirectory => { TagTable => $tbl },
12059
+ Unknown => 2,
12060
+ });
12061
+ }
12062
+ push @offInfo, [ $pos, $off, $known ]; # save parameters for non-zero offsets
12063
+ }
12064
+ # sort offsets in ascending order, and use the differences to calculate
12065
+ # directory lengths and update the SubDirectory DirLen's accordingly
12066
+ my @sorted = sort { $$a[1] <=> $$b[1] or $$a[0] <=> $$b[0] } @offInfo;
12067
+ push @sorted, [ 0, length($$dataPt), 0 ];
12068
+ for ($i=0; $i<@sorted-1; ++$i) {
12069
+ my $pos = $sorted[$i][0];
12070
+ my $len = $sorted[$i+1][1] - $sorted[$i][1];
12071
+ # set DirLen in SubDirectory entry
12072
+ my $tagInfo = $$tagTablePtr{$pos};
12073
+ my $subdir;
12074
+ $$subdir{DirLen} = $len if ref $tagInfo eq 'HASH' and defined($subdir=$$tagInfo{SubDirectory});
12075
+ if ($decryptMode) {
12076
+ # keep track of end of last known directory
12077
+ $end = $sorted[$i+1][1] if $sorted[$i][2];
12078
+ } elsif ($tagInfo and (ref $tagInfo ne 'HASH' or not $$tagInfo{Unknown})) {
12079
+ # decrypt data piecewise as necessary
12080
+ my $n = $len;
12081
+ if ($subdir and $$subdir{KnownEnd}) {
12082
+ $n = $$subdir{KnownEnd};
12083
+ if ($n > $len) {
12084
+ $et->Warn("Data too short for $$tagInfo{Name}",1);
12085
+ $n = $len;
12086
+ }
12087
+ }
12088
+ $$dataPt = Decrypt($dataPt, $sorted[$i][1], $n);
12089
+ }
12090
+ }
12091
+ if ($decryptMode) {
12092
+ # decrypt the remaining required data
12093
+ $end = length $$dataPt if $decryptMode == 2 or not $end or $end < $dpos;
12094
+ $$dataPt = Decrypt($dataPt, $dpos, $end - $dpos);
12095
+ }
12096
+ return $end;
12097
+ }
12098
+
12004
12099
  #------------------------------------------------------------------------------
12005
12100
  # Read/Write Nikon Encrypted data block
12006
12101
  # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
@@ -12025,15 +12120,17 @@ sub ProcessNikonEncrypted($$$)
12025
12120
  delete $$et{NikonCountKey};
12026
12121
  return 0;
12027
12122
  }
12028
- my $verbose = $$dirInfo{IsWriting} ? 0 : $et->Options('Verbose');
12123
+ my $oldOrder = GetByteOrder();
12124
+ my $isWriting = $$dirInfo{IsWriting};
12125
+ my $verbose = $isWriting ? 0 : $et->Options('Verbose');
12029
12126
  my $tagInfo = $$dirInfo{TagInfo};
12030
12127
  my $dirStart = $$dirInfo{DirStart};
12031
12128
  my $data = substr(${$$dirInfo{DataPt}}, $dirStart, $$dirInfo{DirLen});
12032
12129
 
12033
- my ($start, $len, $more, $offset, $byteOrder, $recrypt, $newSerial, $newCount);
12130
+ my ($start, $len, $offset, $recrypt, $newSerial, $newCount, $didDecrypt);
12034
12131
 
12035
12132
  # must re-encrypt when writing if serial number or shutter count changes
12036
- if ($$dirInfo{IsWriting}) {
12133
+ if ($isWriting) {
12037
12134
  if ($$et{NewNikonSerialKey}) {
12038
12135
  $newSerial = $$et{NewNikonSerialKey};
12039
12136
  $recrypt = 1;
@@ -12044,46 +12141,43 @@ sub ProcessNikonEncrypted($$$)
12044
12141
  }
12045
12142
  }
12046
12143
  if ($tagInfo and $$tagInfo{SubDirectory}) {
12047
- $start = $$tagInfo{SubDirectory}{DecryptStart};
12048
- # may decrypt only part of the information to save time
12049
- if ($verbose < 3 and $et->Options('Unknown') < 2 and not $recrypt) {
12050
- $len = $$tagInfo{SubDirectory}{DecryptLen};
12051
- $more = $$tagInfo{SubDirectory}{DecryptMore};
12144
+ # initialize SubDirectory entries used in encryption (KnownStart, KnownEnd)
12145
+ InitEncryptedSubdir($tagInfo, $tagTablePtr);
12146
+ my $subdir = $$tagInfo{SubDirectory};
12147
+ $start = $$subdir{DecryptStart} || 0;
12148
+ # DirOffset, if specified, is the offset to the start of the
12149
+ # directory relative to start of encrypted data
12150
+ $offset = defined $$subdir{DirOffset} ? $$subdir{DirOffset} + $start : 0;
12151
+ # must set byte ordering before calling PrepareNikonOffsets()
12152
+ SetByteOrder($$subdir{ByteOrder}) if $$subdir{ByteOrder};
12153
+ # prepare for processing NIKON_OFFSETS directory if necessary
12154
+ my $unknown = $verbose > 2 || $et->Options('Unknown') > 1;
12155
+ # decrypt mode: 0=piecewise, 1=continuous to end of last known section, 2=all
12156
+ my $dMode = $isWriting ? ($recrypt ? 2 : 1) : ($unknown ? 2 : 0);
12157
+ if ($$tagTablePtr{VARS}{NIKON_OFFSETS}) {
12158
+ $len = PrepareNikonOffsets($et, \$data, $tagTablePtr, $start, $dMode);
12159
+ $didDecrypt = 1;
12160
+ } elsif ($dMode < 2) {
12161
+ if ($dMode == 0 and $$subdir{KnownStart}) {
12162
+ # initialize decryption parameters for address DecryptStart address
12163
+ Decrypt(\$data, $start, 0, $serial, $count);
12164
+ # reset serial/count keys so we don't re-initialize below
12165
+ undef $serial;
12166
+ undef $count;
12167
+ # change decryption start to skip unnecessary data
12168
+ $start = $$subdir{KnownStart};
12169
+ }
12170
+ $len = $$subdir{KnownEnd} - $start if $$subdir{KnownEnd};
12052
12171
  }
12053
- $offset = $$tagInfo{SubDirectory}{DirOffset};
12054
- $byteOrder = $$tagInfo{SubDirectory}{ByteOrder};
12055
- }
12056
- $start or $start = 0;
12057
- if (defined $offset) {
12058
- # offset, if specified, is relative to start of encrypted data
12059
- $offset += $start;
12060
12172
  } else {
12061
- $offset = 0;
12173
+ $start = $offset = 0;
12062
12174
  }
12063
12175
  my $maxLen = length($data) - $start;
12064
- # decrypt all the data unless DecryptLen is given
12065
- unless ($len and $len < $maxLen) {
12066
- $len = $maxLen;
12067
- undef $more; # (can't decrypt more than this)
12068
- }
12176
+ # decrypt all the data unless the length was specified
12177
+ $len = $maxLen unless $len and $len < $maxLen;
12069
12178
 
12070
- $data = Decrypt(\$data, $serial, $count, $start, $len);
12179
+ $data = Decrypt(\$data, $start, $len, $serial, $count) unless $didDecrypt;
12071
12180
 
12072
- # set appropriate byte ordering before evaluating DecryptMore
12073
- my $oldOrder = GetByteOrder();
12074
- SetByteOrder($byteOrder) if $byteOrder;
12075
-
12076
- if ($more) {
12077
- #### eval DecryptMore ($data)
12078
- my $moreLen = eval $more;
12079
- $moreLen = $maxLen if $moreLen > $maxLen;
12080
- # re-decrypt with new length
12081
- if ($len < $moreLen) {
12082
- $len = $moreLen;
12083
- $data = substr(${$$dirInfo{DataPt}}, $dirStart, $$dirInfo{DirLen});
12084
- $data = Decrypt(\$data, $serial, $count, $start, $len);
12085
- }
12086
- }
12087
12181
  if ($verbose > 2) {
12088
12182
  $et->VerboseDir("Decrypted $$tagInfo{Name}");
12089
12183
  $et->VerboseDump(\$data,
@@ -12102,7 +12196,7 @@ sub ProcessNikonEncrypted($$$)
12102
12196
  Base => $$dirInfo{Base},
12103
12197
  );
12104
12198
  my $rtnVal;
12105
- if ($$dirInfo{IsWriting}) {
12199
+ if ($isWriting) {
12106
12200
  my $changed = $$et{CHANGED};
12107
12201
  $rtnVal = $et->WriteBinaryData(\%subdirInfo, $tagTablePtr);
12108
12202
  # must re-encrypt if serial number or shutter count changes
@@ -12117,7 +12211,8 @@ sub ProcessNikonEncrypted($$$)
12117
12211
  # add back any un-encrypted data at start
12118
12212
  $rtnVal = substr($data, 0, $offset) . $rtnVal if $offset;
12119
12213
  # re-encrypt data (symmetrical algorithm)
12120
- $rtnVal = Decrypt(\$rtnVal, $serial, $count, $start, $len);
12214
+ $rtnVal = Decrypt(\$rtnVal, $start, $len, $serial, $count);
12215
+ $et->VPrint(2, $$et{INDENT}, " [recrypted $$tagInfo{Name}]");
12121
12216
  }
12122
12217
  } else {
12123
12218
  $rtnVal = $et->ProcessBinaryData(\%subdirInfo, $tagTablePtr);