exiftool_vendored 12.57.0 → 12.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +39 -0
  3. data/bin/MANIFEST +3 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +2 -2
  7. data/bin/config_files/example.config +1 -0
  8. data/bin/config_files/rotate_regions.config +1 -1
  9. data/bin/exiftool +76 -57
  10. data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  11. data/bin/lib/Image/ExifTool/APE.pm +2 -2
  12. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +13 -14
  13. data/bin/lib/Image/ExifTool/Canon.pm +26 -6
  14. data/bin/lib/Image/ExifTool/DJI.pm +28 -2
  15. data/bin/lib/Image/ExifTool/Exif.pm +24 -5
  16. data/bin/lib/Image/ExifTool/FlashPix.pm +28 -10
  17. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
  18. data/bin/lib/Image/ExifTool/JPEG.pm +14 -2
  19. data/bin/lib/Image/ExifTool/LIF.pm +10 -2
  20. data/bin/lib/Image/ExifTool/LNK.pm +5 -4
  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/MinoltaRaw.pm +9 -1
  25. data/bin/lib/Image/ExifTool/Nikon.pm +390 -114
  26. data/bin/lib/Image/ExifTool/Olympus.pm +87 -7
  27. data/bin/lib/Image/ExifTool/PNG.pm +15 -2
  28. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +27 -1
  29. data/bin/lib/Image/ExifTool/Pentax.pm +8 -5
  30. data/bin/lib/Image/ExifTool/PhaseOne.pm +14 -1
  31. data/bin/lib/Image/ExifTool/Photoshop.pm +3 -3
  32. data/bin/lib/Image/ExifTool/QuickTime.pm +16 -11
  33. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +38 -6
  34. data/bin/lib/Image/ExifTool/README +8 -0
  35. data/bin/lib/Image/ExifTool/RIFF.pm +41 -13
  36. data/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
  37. data/bin/lib/Image/ExifTool/Sigma.pm +4 -4
  38. data/bin/lib/Image/ExifTool/Sony.pm +23 -1
  39. data/bin/lib/Image/ExifTool/TagLookup.pm +4464 -4441
  40. data/bin/lib/Image/ExifTool/TagNames.pod +117 -36
  41. data/bin/lib/Image/ExifTool/Validate.pm +5 -5
  42. data/bin/lib/Image/ExifTool/WriteExif.pl +49 -0
  43. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  44. data/bin/lib/Image/ExifTool/Writer.pl +74 -14
  45. data/bin/lib/Image/ExifTool/XMP.pm +19 -4
  46. data/bin/lib/Image/ExifTool/XMP2.pl +2 -1
  47. data/bin/lib/Image/ExifTool.pm +131 -17
  48. data/bin/lib/Image/ExifTool.pod +40 -5
  49. data/bin/perl-Image-ExifTool.spec +1 -1
  50. data/lib/exiftool_vendored/version.rb +1 -1
  51. metadata +2 -2
@@ -64,7 +64,7 @@ use Image::ExifTool::Exif;
64
64
  use Image::ExifTool::GPS;
65
65
  use Image::ExifTool::XMP;
66
66
 
67
- $VERSION = '4.19';
67
+ $VERSION = '4.21';
68
68
 
69
69
  sub LensIDConv($$$);
70
70
  sub ProcessNikonAVI($$$);
@@ -84,9 +84,8 @@ sub GetAFPointGrid($$;$);
84
84
  The Nikon LensID is constructed as a Composite tag from the raw hex values
85
85
  of 8 other tags: LensIDNumber, LensFStops, MinFocalLength, MaxFocalLength,
86
86
  MaxApertureAtMinFocal, MaxApertureAtMaxFocal, MCUVersion and LensType, in
87
- that order. Multiple lenses with the same LensID are differentiated by
88
- decimal values in the list below. The user-defined "Lenses" list may be
89
- 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
90
89
  L<sample config file|../config.html> for details).
91
90
  },
92
91
  OTHER => \&LensIDConv,
@@ -881,6 +880,12 @@ my %bracketProgramZ9 = (
881
880
  9 => '9F',
882
881
  );
883
882
 
883
+ my %dynamicAfAreaModesZ9 = (
884
+ 0 => 'Small',
885
+ 1 => 'Medium',
886
+ 2 => 'Large',
887
+ );
888
+
884
889
  my %flashControlModeZ7 = (
885
890
  0 => 'TTL',
886
891
  1 => 'Auto External Flash',
@@ -2067,7 +2072,6 @@ my %base64coord = (
2067
2072
  SubDirectory => {
2068
2073
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD40',
2069
2074
  DecryptStart => 4,
2070
- DecryptLen => 748,
2071
2075
  ByteOrder => 'BigEndian',
2072
2076
  },
2073
2077
  },
@@ -2077,7 +2081,6 @@ my %base64coord = (
2077
2081
  SubDirectory => {
2078
2082
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD80',
2079
2083
  DecryptStart => 4,
2080
- DecryptLen => 765,
2081
2084
  # (Capture NX can change the makernote byte order, but this stays big-endian)
2082
2085
  ByteOrder => 'BigEndian',
2083
2086
  },
@@ -2088,7 +2091,6 @@ my %base64coord = (
2088
2091
  SubDirectory => {
2089
2092
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD90',
2090
2093
  DecryptStart => 4,
2091
- DecryptLen => 0x398,
2092
2094
  ByteOrder => 'BigEndian',
2093
2095
  },
2094
2096
  },
@@ -2098,7 +2100,6 @@ my %base64coord = (
2098
2100
  SubDirectory => {
2099
2101
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3a',
2100
2102
  DecryptStart => 4,
2101
- DecryptLen => 0x318,
2102
2103
  ByteOrder => 'BigEndian',
2103
2104
  },
2104
2105
  },
@@ -2108,7 +2109,6 @@ my %base64coord = (
2108
2109
  SubDirectory => {
2109
2110
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3b',
2110
2111
  DecryptStart => 4,
2111
- DecryptLen => 0x321,
2112
2112
  ByteOrder => 'BigEndian',
2113
2113
  },
2114
2114
  },
@@ -2118,7 +2118,6 @@ my %base64coord = (
2118
2118
  SubDirectory => {
2119
2119
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3X',
2120
2120
  DecryptStart => 4,
2121
- DecryptLen => 0x323,
2122
2121
  ByteOrder => 'BigEndian',
2123
2122
  },
2124
2123
  },
@@ -2128,7 +2127,6 @@ my %base64coord = (
2128
2127
  SubDirectory => {
2129
2128
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD3S',
2130
2129
  DecryptStart => 4,
2131
- DecryptLen => 0x2e9,
2132
2130
  ByteOrder => 'BigEndian',
2133
2131
  },
2134
2132
  },
@@ -2139,7 +2137,6 @@ my %base64coord = (
2139
2137
  SubDirectory => {
2140
2138
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD300a',
2141
2139
  DecryptStart => 4,
2142
- DecryptLen => 813,
2143
2140
  ByteOrder => 'BigEndian',
2144
2141
  },
2145
2142
  },
@@ -2150,7 +2147,6 @@ my %base64coord = (
2150
2147
  SubDirectory => {
2151
2148
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD300b',
2152
2149
  DecryptStart => 4,
2153
- DecryptLen => 825,
2154
2150
  ByteOrder => 'BigEndian',
2155
2151
  },
2156
2152
  },
@@ -2161,7 +2157,6 @@ my %base64coord = (
2161
2157
  SubDirectory => {
2162
2158
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD300S',
2163
2159
  DecryptStart => 4,
2164
- DecryptLen => 827,
2165
2160
  ByteOrder => 'BigEndian',
2166
2161
  },
2167
2162
  },
@@ -2172,17 +2167,33 @@ my %base64coord = (
2172
2167
  SubDirectory => {
2173
2168
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD700',
2174
2169
  DecryptStart => 4,
2175
- DecryptLen => 0x358,
2176
2170
  ByteOrder => 'BigEndian',
2177
2171
  },
2178
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
+ },
2179
2191
  { #PH (D800 firmware 1.01a)
2180
2192
  Condition => '$$valPt =~ /^0222/',
2181
2193
  Name => 'ShotInfoD800',
2182
2194
  SubDirectory => {
2183
2195
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD800',
2184
2196
  DecryptStart => 4,
2185
- DecryptLen => 0x720,
2186
2197
  ByteOrder => 'BigEndian',
2187
2198
  },
2188
2199
  },
@@ -2213,7 +2224,6 @@ my %base64coord = (
2213
2224
  SubDirectory => {
2214
2225
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD5000',
2215
2226
  DecryptStart => 4,
2216
- DecryptLen => 0x39a,
2217
2227
  ByteOrder => 'BigEndian',
2218
2228
  },
2219
2229
  },
@@ -2223,7 +2233,6 @@ my %base64coord = (
2223
2233
  SubDirectory => {
2224
2234
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD5100',
2225
2235
  DecryptStart => 4,
2226
- DecryptLen => 0x430,
2227
2236
  ByteOrder => 'BigEndian',
2228
2237
  },
2229
2238
  },
@@ -2233,7 +2242,6 @@ my %base64coord = (
2233
2242
  SubDirectory => {
2234
2243
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD5200',
2235
2244
  DecryptStart => 4,
2236
- DecryptLen => 0xd00,
2237
2245
  ByteOrder => 'BigEndian',
2238
2246
  },
2239
2247
  },
@@ -2243,7 +2251,6 @@ my %base64coord = (
2243
2251
  SubDirectory => {
2244
2252
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD7000',
2245
2253
  DecryptStart => 4,
2246
- DecryptLen => 0x448,
2247
2254
  ByteOrder => 'BigEndian',
2248
2255
  },
2249
2256
  },
@@ -2253,7 +2260,6 @@ my %base64coord = (
2253
2260
  SubDirectory => {
2254
2261
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD4',
2255
2262
  DecryptStart => 4,
2256
- DecryptLen => 0x789,
2257
2263
  ByteOrder => 'BigEndian',
2258
2264
  },
2259
2265
  },
@@ -2263,7 +2269,6 @@ my %base64coord = (
2263
2269
  SubDirectory => {
2264
2270
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD4S',
2265
2271
  DecryptStart => 4,
2266
- DecryptLen => 0x3697,
2267
2272
  ByteOrder => 'LittleEndian',
2268
2273
  },
2269
2274
  },
@@ -2291,7 +2296,6 @@ my %base64coord = (
2291
2296
  SubDirectory => {
2292
2297
  TagTable => 'Image::ExifTool::Nikon::ShotInfoD610',
2293
2298
  DecryptStart => 4,
2294
- DecryptLen => 0x7ff,
2295
2299
  ByteOrder => 'BigEndian',
2296
2300
  },
2297
2301
  },
@@ -2322,7 +2326,6 @@ my %base64coord = (
2322
2326
  ProcessProc => \&ProcessNikonEncrypted,
2323
2327
  WriteProc => \&ProcessNikonEncrypted,
2324
2328
  DecryptStart => 4,
2325
- DecryptLen => 0x251,
2326
2329
  ByteOrder => 'BigEndian',
2327
2330
  },
2328
2331
  },
@@ -2389,8 +2392,7 @@ my %base64coord = (
2389
2392
  ProcessProc => \&ProcessNikonEncrypted,
2390
2393
  WriteProc => \&ProcessNikonEncrypted,
2391
2394
  DecryptStart => 4,
2392
- DecryptLen => 22, # 284 bytes encrypted, but don't need to decrypt it all
2393
- DirOffset => 14,
2395
+ DirOffset => 14, # (start of directory relative to DecryptStart)
2394
2396
  },
2395
2397
  },
2396
2398
  { # (D3/D3X/D300/D700=0209,D300S=0212,D3S=0214)
@@ -2401,7 +2403,6 @@ my %base64coord = (
2401
2403
  ProcessProc => \&ProcessNikonEncrypted,
2402
2404
  WriteProc => \&ProcessNikonEncrypted,
2403
2405
  DecryptStart => 284,
2404
- DecryptLen => 18, # 324 bytes encrypted, but don't need to decrypt it all
2405
2406
  DirOffset => 10,
2406
2407
  },
2407
2408
  },
@@ -2413,7 +2414,6 @@ my %base64coord = (
2413
2414
  ProcessProc => \&ProcessNikonEncrypted,
2414
2415
  WriteProc => \&ProcessNikonEncrypted,
2415
2416
  DecryptStart => 284,
2416
- DecryptLen => 14, # don't need to decrypt it all
2417
2417
  DirOffset => 6,
2418
2418
  },
2419
2419
  },
@@ -2425,7 +2425,6 @@ my %base64coord = (
2425
2425
  ProcessProc => \&ProcessNikonEncrypted,
2426
2426
  WriteProc => \&ProcessNikonEncrypted,
2427
2427
  DecryptStart => 284,
2428
- DecryptLen => 24, # don't need to decrypt it all
2429
2428
  DirOffset => 16,
2430
2429
  },
2431
2430
  },
@@ -2437,7 +2436,6 @@ my %base64coord = (
2437
2436
  ProcessProc => \&ProcessNikonEncrypted,
2438
2437
  WriteProc => \&ProcessNikonEncrypted,
2439
2438
  DecryptStart => 284,
2440
- DecryptLen => 18, # don't need to decrypt it all
2441
2439
  DirOffset => 10,
2442
2440
  },
2443
2441
  },
@@ -2449,7 +2447,6 @@ my %base64coord = (
2449
2447
  ProcessProc => \&ProcessNikonEncrypted,
2450
2448
  WriteProc => \&ProcessNikonEncrypted,
2451
2449
  DecryptStart => 284,
2452
- DecryptLen => 12, # don't need to decrypt it all
2453
2450
  DirOffset => 4,
2454
2451
  },
2455
2452
  },
@@ -2461,7 +2458,6 @@ my %base64coord = (
2461
2458
  ProcessProc => \&ProcessNikonEncrypted,
2462
2459
  WriteProc => \&ProcessNikonEncrypted, # (necessary to recrypt this if serial number changed)
2463
2460
  DecryptStart => 284,
2464
- DecryptLen => 10, # (arbitrary)
2465
2461
  },
2466
2462
  },
2467
2463
  { # (1J1/1J2/1V1=0400, 1V2=0401, 1J3/1S1=0402, 1AW1=0403, Z6/Z7=0800)
@@ -2472,7 +2468,6 @@ my %base64coord = (
2472
2468
  ProcessProc => \&ProcessNikonEncrypted,
2473
2469
  WriteProc => \&ProcessNikonEncrypted, # (necessary to recrypt this if serial number changed)
2474
2470
  DecryptStart => 4,
2475
- DecryptLen => 10, # (arbitrary)
2476
2471
  },
2477
2472
  },
2478
2473
  {
@@ -5267,7 +5262,7 @@ my %nikonFocalConversions = (
5267
5262
  Name => 'NewLensData',
5268
5263
  Format => 'undef[17]',
5269
5264
  RawConv => '$$self{NewLensData} = 1 unless $val =~ /^.\0+$/s; undef',
5270
- Hidden => 1,
5265
+ #Hidden => 1,
5271
5266
  },
5272
5267
  0x30 => { #PH
5273
5268
  Name => 'LensID',
@@ -5303,6 +5298,7 @@ my %nikonFocalConversions = (
5303
5298
  35 => 'Nikkor Z 28-75mm f/2.8', #IB
5304
5299
  36 => 'Nikkor Z 400mm f/4.5 VR S', #IB
5305
5300
  37 => 'Nikkor Z 600mm f/4 TC VR S', #28
5301
+ 38 => 'Nikkor Z 85mm f/1.2 S', #28
5306
5302
  39 => 'Nikkor Z 17-28mm f/2.8', #IB
5307
5303
  32768 => 'Nikkor Z 400mm f/2.8 TC VR S TC-1.4x', #28
5308
5304
  32769 => 'Nikkor Z 600mm f/4 TC VR S TC-1.4x', #28
@@ -5312,7 +5308,7 @@ my %nikonFocalConversions = (
5312
5308
  Name => 'LensMountType',
5313
5309
  RawConv => '$$self{LensMountType} = $val', # 0=> DSLR lens via FTZ style adapter; 1=> Native Z lens;
5314
5310
  Format => 'int8u',
5315
- Unknown => 1,
5311
+ #Unknown => 1,
5316
5312
  PrintConv => {
5317
5313
  0 => 'F-mount Lens',
5318
5314
  1 => 'Z-mount Lens',
@@ -5375,7 +5371,7 @@ my %nikonFocalConversions = (
5375
5371
  Name => 'LensPositionAbsolute', # <=0 at infinity. Typical value at CFD might be 58000. Only valid for Z-mount lenses.
5376
5372
  Condition => '$$self{NewLensData} and $$self{LensMountType} and $$self{LensMountType} == 1',
5377
5373
  Format => 'int32s',
5378
- Unknown => 1,
5374
+ #Unknown => 1,
5379
5375
  },
5380
5376
  );
5381
5377
 
@@ -5498,8 +5494,6 @@ my %nikonFocalConversions = (
5498
5494
  Format => 'int32u',
5499
5495
  Priority => 0,
5500
5496
  },
5501
- # note: DecryptLen currently set to 0x251
5502
-
5503
5497
  # 0x55c - int16u[2400] TiffMeteringImage2: 60x40 image (ShotInfoVersion 0800, ref JR)
5504
5498
  # 0x181c - int16u[1200] TiffMeteringImage?: 60x20 image for some NEF's (ShotInfoVersion 0800, ref JR)
5505
5499
  # 0x217c - int16u[2400] TiffMeteringImage3: 60x40 image (ShotInfoVersion 0800, ref JR)
@@ -5542,7 +5536,6 @@ my %nikonFocalConversions = (
5542
5536
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD40',
5543
5537
  },
5544
5538
  },
5545
- # note: DecryptLen currently set to 748
5546
5539
  );
5547
5540
 
5548
5541
  # shot information for D80 (encrypted) - ref JD
@@ -5622,7 +5615,6 @@ my %nikonFocalConversions = (
5622
5615
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD80',
5623
5616
  },
5624
5617
  },
5625
- # note: DecryptLen currently set to 765
5626
5618
  );
5627
5619
 
5628
5620
  # shot information for D90 (encrypted) - ref PH
@@ -5668,7 +5660,6 @@ my %nikonFocalConversions = (
5668
5660
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD90',
5669
5661
  },
5670
5662
  },
5671
- # note: DecryptLen currently set to 0x398
5672
5663
  );
5673
5664
 
5674
5665
  # shot information for the D3 firmware 0.37 and 1.00 (encrypted) - ref PH
@@ -5732,7 +5723,6 @@ my %nikonFocalConversions = (
5732
5723
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5733
5724
  },
5734
5725
  },
5735
- # note: DecryptLen currently set to 0x318
5736
5726
  );
5737
5727
 
5738
5728
  # shot information for the D3 firmware 1.10, 2.00 and 2.01 (encrypted) - ref PH
@@ -5827,7 +5817,6 @@ my %nikonFocalConversions = (
5827
5817
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5828
5818
  },
5829
5819
  },
5830
- # note: DecryptLen currently set to 0x321
5831
5820
  );
5832
5821
 
5833
5822
  # shot information for the D3X firmware 1.00 (encrypted) - ref PH
@@ -5873,7 +5862,6 @@ my %nikonFocalConversions = (
5873
5862
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5874
5863
  },
5875
5864
  },
5876
- # note: DecryptLen currently set to 0x323
5877
5865
  );
5878
5866
 
5879
5867
  # shot information for the D3S firmware 0.16 and 1.00 (encrypted) - ref PH
@@ -5928,7 +5916,6 @@ my %nikonFocalConversions = (
5928
5916
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5929
5917
  },
5930
5918
  },
5931
- # note: DecryptLen currently set to 0x2e9
5932
5919
  );
5933
5920
 
5934
5921
  # shot information for the D300 firmware 1.00 (encrypted) - ref JD
@@ -6021,7 +6008,6 @@ my %nikonFocalConversions = (
6021
6008
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6022
6009
  },
6023
6010
  },
6024
- # note: DecryptLen currently set to 813
6025
6011
  );
6026
6012
 
6027
6013
  # shot information for the D300 firmware 1.10 (encrypted) - ref PH
@@ -6172,7 +6158,6 @@ my %nikonFocalConversions = (
6172
6158
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6173
6159
  },
6174
6160
  },
6175
- # note: DecryptLen currently set to 825
6176
6161
  );
6177
6162
 
6178
6163
  # shot information for the D300S firmware 1.00 (encrypted) - ref PH
@@ -6218,7 +6203,6 @@ my %nikonFocalConversions = (
6218
6203
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6219
6204
  },
6220
6205
  },
6221
- # note: DecryptLen currently set to 827
6222
6206
  );
6223
6207
 
6224
6208
  # shot information for the D700 firmware 1.02f (encrypted) - ref 29
@@ -6264,7 +6248,39 @@ my %nikonFocalConversions = (
6264
6248
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD700',
6265
6249
  },
6266
6250
  },
6267
- # note: DecryptLen currently set to 852
6251
+ );
6252
+
6253
+ # shot information for the D780 - ref #28
6254
+ %Image::ExifTool::Nikon::ShotInfoD780 = (
6255
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6256
+ WRITE_PROC => \&ProcessNikonEncrypted,
6257
+ CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6258
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
6259
+ DATAMEMBER => [ 0x04 ],
6260
+ IS_SUBDIR => [ 0x9c ],
6261
+ WRITABLE => 1,
6262
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6263
+ NOTES => 'These tags are extracted from encrypted data in images from the D780.',
6264
+ 0x00 => {
6265
+ Name => 'ShotInfoVersion',
6266
+ Format => 'string[4]',
6267
+ Writable => 0,
6268
+ },
6269
+ 0x04 => {
6270
+ Name => 'FirmwareVersion',
6271
+ DataMember => 'FirmwareVersion',
6272
+ Format => 'string[5]',
6273
+ Writable => 0,
6274
+ RawConv => '$$self{FirmwareVersion} = $val',
6275
+ },
6276
+ 0x9c => {
6277
+ Name => 'OrientOffset',
6278
+ Format => 'int32u',
6279
+ SubDirectory => {
6280
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
6281
+ Start => '$val',
6282
+ },
6283
+ },
6268
6284
  );
6269
6285
 
6270
6286
  # shot information for the D5000 firmware 1.00 (encrypted) - ref PH
@@ -6310,7 +6326,6 @@ my %nikonFocalConversions = (
6310
6326
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5000',
6311
6327
  },
6312
6328
  },
6313
- # note: DecryptLen currently set to 0x39a
6314
6329
  );
6315
6330
 
6316
6331
  # shot information for the D5100 firmware 1.00f (encrypted) - ref PH
@@ -6345,7 +6360,6 @@ my %nikonFocalConversions = (
6345
6360
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5100',
6346
6361
  },
6347
6362
  },
6348
- # note: DecryptLen currently set to 0x430
6349
6363
  );
6350
6364
 
6351
6365
  # shot information for the D5200 firmware 1.00 (encrypted) - ref PH
@@ -6383,7 +6397,6 @@ my %nikonFocalConversions = (
6383
6397
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5200',
6384
6398
  },
6385
6399
  },
6386
- # note: DecryptLen currently set to 0xd00
6387
6400
  );
6388
6401
 
6389
6402
  # shot information for the D7000 firmware 1.01d (encrypted) - ref 29
@@ -6431,6 +6444,39 @@ my %nikonFocalConversions = (
6431
6444
  },
6432
6445
  );
6433
6446
 
6447
+ # shot information for the D7500 - ref #28
6448
+ %Image::ExifTool::Nikon::ShotInfoD7500 = (
6449
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6450
+ WRITE_PROC => \&ProcessNikonEncrypted,
6451
+ CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6452
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x0c },
6453
+ DATAMEMBER => [ 0x04 ],
6454
+ IS_SUBDIR => [ 0xa0 ],
6455
+ WRITABLE => 1,
6456
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6457
+ NOTES => 'These tags are extracted from encrypted data in images from the D7500.',
6458
+ 0x00 => {
6459
+ Name => 'ShotInfoVersion',
6460
+ Format => 'string[4]',
6461
+ Writable => 0,
6462
+ },
6463
+ 0x04 => {
6464
+ Name => 'FirmwareVersion',
6465
+ DataMember => 'FirmwareVersion',
6466
+ Format => 'string[5]',
6467
+ Writable => 0,
6468
+ RawConv => '$$self{FirmwareVersion} = $val',
6469
+ },
6470
+ 0xa0 => {
6471
+ Name => 'OrientOffset',
6472
+ Format => 'int32u',
6473
+ SubDirectory => {
6474
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
6475
+ Start => '$val',
6476
+ },
6477
+ },
6478
+ );
6479
+
6434
6480
  # shot information for the D800 firmware 1.01a (encrypted) - ref PH
6435
6481
  %Image::ExifTool::Nikon::ShotInfoD800 = (
6436
6482
  PROCESS_PROC => \&ProcessNikonEncrypted,
@@ -6549,7 +6595,6 @@ my %nikonFocalConversions = (
6549
6595
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD800',
6550
6596
  },
6551
6597
  },
6552
- # note: DecryptLen currently set to 0x720
6553
6598
  );
6554
6599
 
6555
6600
  # shot information for the D5 firmware 1.10a and D500 firmware 1.01 (encrypted) - ref 28
@@ -7009,7 +7054,6 @@ my %nikonFocalConversions = (
7009
7054
  3 => 'Highlight'
7010
7055
  },
7011
7056
  },
7012
- # note: DecryptLen currently set to OtherOffset + 0x2ea5 - 0x2c90
7013
7057
  );
7014
7058
 
7015
7059
  # shot information for the D6 firmware 1.00 (encrypted) - ref 28
@@ -7244,7 +7288,6 @@ my %nikonFocalConversions = (
7244
7288
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD610',
7245
7289
  },
7246
7290
  },
7247
- # note: DecryptLen currently set to 0x7ff
7248
7291
  );
7249
7292
 
7250
7293
  # shot information for the D810 firmware 1.00(PH)/1.01 (encrypted) - ref 28
@@ -7678,7 +7721,6 @@ my %nikonFocalConversions = (
7678
7721
  Format => 'undef[56]',
7679
7722
  SubDirectory => { TagTable => 'Image::ExifTool::NikonCustom::SettingsD4' },
7680
7723
  },
7681
- # note: DecryptLen currently set to 0x789
7682
7724
  );
7683
7725
 
7684
7726
  # shot information for the D4S firmware 1.01a (ref 28, encrypted)
@@ -7970,7 +8012,6 @@ my %nikonFocalConversions = (
7970
8012
  3 => 'Rotate 180',
7971
8013
  },
7972
8014
  },
7973
- # note: DecryptLen currently set to 0x3697
7974
8015
  );
7975
8016
 
7976
8017
  # shot information for the Z7II firmware 1.00 (encrypted) - ref 28
@@ -8115,7 +8156,7 @@ my %nikonFocalConversions = (
8115
8156
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
8116
8157
  VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
8117
8158
  DATAMEMBER => [ 0x04 ],
8118
- IS_SUBDIR => [ 0x30, 0x84, 0x8c ],
8159
+ IS_SUBDIR => [ 0x30, 0x58, 0x84, 0x8c ],
8119
8160
  WRITABLE => 1,
8120
8161
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8121
8162
  NOTES => 'These tags are extracted from encrypted data in images from the Z9.',
@@ -8158,6 +8199,15 @@ my %nikonFocalConversions = (
8158
8199
  Start => '$val',
8159
8200
  },
8160
8201
  },
8202
+ 0x58 => {
8203
+ 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.
8204
+ Condition => '$$self{FirmwareVersion} and $$self{FirmwareVersion} ge "03.01"',
8205
+ Format => 'int32u',
8206
+ SubDirectory => {
8207
+ TagTable => 'Image::ExifTool::Nikon::Offset13InfoZ9',
8208
+ Start => '$val',
8209
+ },
8210
+ },
8161
8211
  0x84 => {
8162
8212
  Name => 'OrientOffset',
8163
8213
  Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96', #not valid for C30/C60/C120
@@ -8177,6 +8227,7 @@ my %nikonFocalConversions = (
8177
8227
  },
8178
8228
  );
8179
8229
 
8230
+ # ref 28
8180
8231
  %Image::ExifTool::Nikon::SeqInfoZ9 = (
8181
8232
  %binaryDataAttrs,
8182
8233
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
@@ -8213,6 +8264,151 @@ my %nikonFocalConversions = (
8213
8264
  },
8214
8265
  );
8215
8266
 
8267
+ # ref 28
8268
+ %Image::ExifTool::Nikon::Offset13InfoZ9 = (
8269
+ %binaryDataAttrs,
8270
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8271
+ DATAMEMBER => [ 0x0bea, 0x0beb ],
8272
+ 0x0be8 => {
8273
+ 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)
8274
+ Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2 ', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8275
+ Format => 'int8s',
8276
+ PrintConv => q{
8277
+ #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.
8278
+ #in FX mode and Dynamic(L), the 27 horizontal focus points are spaced 259 pixels apart starting at pixel 761 and ending at 7495
8279
+ #in FX mode and Dynamic(M), the 29 horizontal focus points are spaced 259 pixels apart starting at pixel 502 and ending at 7754
8280
+ #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].
8281
+ #in DX mode and Wide(S), the 17 horizontal focus points are spaced 393 pixels apart starting at pixel 591 and ending at 7272.
8282
+ #in DX mode and Dynamic(L), the 17 horizontal focus points are spaced 388 pixels apart starting at pixel 1024 and ending at 7232
8283
+ #in DX mode and Dynamic(M), the 19 horizontal focus points are spaced 388 pixels apart starting at pixel 636 and ending at 7620
8284
+
8285
+ my $areaMode = $$self{VALUE}{PhotoShootingMenuBankImageArea};
8286
+ my $afAreaMode = $$self{VALUE}{AFAreaMode};
8287
+ my $dynamicAFAreaSize = $$self{VALUE}{DynamicAFAreaSize};
8288
+
8289
+ my $FX = 0;
8290
+ my $DX = 1;
8291
+
8292
+ my $Single = 1;
8293
+ my $Dynamic = 2;
8294
+ my $WideS = 3;
8295
+ my $WideL = 4;
8296
+ my $ThreeD = 5;
8297
+ my $Auto = 6;
8298
+ my $WideC1 = 12;
8299
+
8300
+ my $DynamicS = 0;
8301
+ my $DynamicM = 1;
8302
+ my $DynamicL = 2;
8303
+
8304
+ my $start = 502; #FX - all flavors
8305
+ $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
8306
+ $start = 591 if $areaMode == $DX and $afAreaMode == $WideS ; #DX Wide(S)
8307
+
8308
+ my $increment = 259; #FX - all flavors
8309
+ $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
8310
+ $increment = 393 if $areaMode == $DX and $afAreaMode == $WideS ; #DX Wide(S)
8311
+
8312
+ my $divisor = 4;
8313
+ $divisor = 6 if $areaMode == $DX ;
8314
+
8315
+ my $offsetVal = 0;
8316
+ $offsetVal = 12 if $areaMode == $FX and $afAreaMode == $Dynamic ; #FX Dynamic (L/M) - force positive values so perl rounding toward zero isn't an issue
8317
+ $offsetVal = 18 if $areaMode == $DX and $afAreaMode == $Dynamic ; #DX Dynamic (L/M)
8318
+
8319
+ my $offsetSum = -1;
8320
+ $offsetSum = -4 if $afAreaMode == $Dynamic ; # Dynamic (L/M)
8321
+
8322
+ my $ncol = $$self{AFAreaInitialWidth};
8323
+ $ncol = int($ncol * 2 / 3) if $areaMode == $DX ; #DX
8324
+
8325
+ #some sample mappings:
8326
+ #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]
8327
+ #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]
8328
+ #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]
8329
+ #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]
8330
+
8331
+ 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
8332
+ },
8333
+ },
8334
+ 0x0be9 => {
8335
+ 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)
8336
+ Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8337
+ Format => 'int8s',
8338
+ PrintConv => q{
8339
+ #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)
8340
+ #in FX mode and Dynamic(L), the 15 vertical focus points are spaced 291 pixels apart starting at pixel 715 and ending at 4789
8341
+ #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
8342
+ #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].
8343
+ #in DX Mode and Wide(S) the 9 vertical focus points are spaced 442 pixels apart starting at pixel 542 and ending at 4520
8344
+ #in DX mode and Dynamic(L), the 9 vertical focus points are spaced 436 pixels apart starting at pixel 1008 and ending at 4496
8345
+
8346
+ my $areaMode = $$self{VALUE}{PhotoShootingMenuBankImageArea};
8347
+ my $afAreaMode = $$self{VALUE}{AFAreaMode};
8348
+ my $dynamicAFAreaSize = $$self{VALUE}{DynamicAFAreaSize};
8349
+
8350
+ my $FX = 0;
8351
+ my $DX = 1;
8352
+
8353
+ my $Single = 1;
8354
+ my $Dynamic = 2;
8355
+ my $WideS = 3;
8356
+ my $WideL = 4;
8357
+ my $ThreeD = 5;
8358
+ my $Auto = 6;
8359
+ my $WideC1 = 12;
8360
+
8361
+ my $DynamicS = 0;
8362
+ my $DynamicM = 1;
8363
+ my $DynamicL = 2;
8364
+
8365
+ my $start = 424; #FX - all flavors
8366
+ $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
8367
+ $start = 542 if $areaMode == $DX and $afAreaMode == 3 ; #DX Wide(S)
8368
+
8369
+ my $increment = 291; #FX - all flavors
8370
+ $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
8371
+ $increment = 442 if $areaMode == $DX and $afAreaMode == 3 ; #DX Wide(S)
8372
+
8373
+ my $divisor = 7;
8374
+ $divisor = 10 if $areaMode == $DX ; #DX
8375
+
8376
+ my $offsetVal = -1;
8377
+ $offsetVal = 39 if $afAreaMode == $Dynamic and ( $dynamicAFAreaSize == $DynamicL ) ; #Dynamic (L) - force positive values so perl rounding toward zero isn't an issue
8378
+ $offsetVal = 40 if $afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicM ; #Dynamic (M)
8379
+ $offsetVal = 40 if $areaMode == $FX and (($afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicS) or $afAreaMode == $ThreeD) ; #FX Dynamic (S) or 3D
8380
+ $offsetVal = 38 if $areaMode == $DX and ($afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicS ) ; #DX Dynamic (S)or 3D
8381
+
8382
+ my $offsetSum = 0;
8383
+ $offsetSum = -6 if $areaMode == $FX and ($afAreaMode == $Dynamic or $afAreaMode == $ThreeD); #FX Dynamic (L/M/S) or 3D
8384
+ $offsetSum = -4 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $ThreeD ); #DX Dynamic (L/M/S) or 3D
8385
+
8386
+ my $nrow = $$self{AFAreaInitialHeight};
8387
+ $nrow = int($nrow * 2 / 3) if $areaMode == $DX; #DX
8388
+
8389
+ #some sample mappings:
8390
+ #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]
8391
+ #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]
8392
+ #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]
8393
+ #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]
8394
+
8395
+ return $start + $increment * (int(($val + $offsetVal) / $divisor) + int($nrow / 2) + $offsetSum) ;;
8396
+ },
8397
+ },
8398
+ 0x0bea => {
8399
+ Name => 'AFAreaInitialWidth',
8400
+ Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8401
+ 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
8402
+ 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)
8403
+ },
8404
+ 0x0beb => {
8405
+ Name => 'AFAreaInitialHeight',
8406
+ Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8407
+ 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
8408
+ 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)
8409
+ },
8410
+ );
8411
+
8216
8412
  %Image::ExifTool::Nikon::MenuInfoZ9 = (
8217
8413
  %binaryDataAttrs,
8218
8414
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
@@ -8510,7 +8706,7 @@ my %nikonFocalConversions = (
8510
8706
  %Image::ExifTool::Nikon::MenuSettingsZ9 = (
8511
8707
  %binaryDataAttrs,
8512
8708
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8513
- DATAMEMBER => [ 140, 188, 192, 232, 424, 534 ],
8709
+ DATAMEMBER => [ 140, 188, 192, 232, 424, 534, 576 ],
8514
8710
  IS_SUBDIR => [ 799 ],
8515
8711
  NOTES => 'These tags are used by the Z9.',
8516
8712
  #90 ISO
@@ -8650,6 +8846,12 @@ my %nikonFocalConversions = (
8650
8846
  556 => { Name => 'SecondarySlotFunction', PrintConv => \%secondarySlotFunctionZ9 },
8651
8847
  572 => { Name => 'DXCropAlert', PrintConv => \%offOn },
8652
8848
  574 => { Name => 'SubjectDetection', PrintConv => \%subjectDetectionZ9 },
8849
+ 576 => {
8850
+ Name => 'DynamicAFAreaSize',
8851
+ Condition => '$$self{AFAraMode} = 2',
8852
+ RawConv => '$$self{DynamicAFAreaSize} = $val',
8853
+ PrintConv => \%dynamicAfAreaModesZ9,
8854
+ },
8653
8855
  604 => {
8654
8856
  Name => 'MovieImageArea',
8655
8857
  Unknown => 1,
@@ -8715,7 +8917,7 @@ my %nikonFocalConversions = (
8715
8917
  %Image::ExifTool::Nikon::MenuSettingsZ9v3 = (
8716
8918
  %binaryDataAttrs,
8717
8919
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8718
- DATAMEMBER => [ 154, 204, 208, 248, 444, 554 ],
8920
+ DATAMEMBER => [ 154, 204, 208, 248, 444, 554, 596 ],
8719
8921
  IS_SUBDIR => [ 847 ],
8720
8922
  NOTES => 'These tags are used by the Z9 firmware 3.00.',
8721
8923
  72 => {
@@ -8844,6 +9046,12 @@ my %nikonFocalConversions = (
8844
9046
  576 => { Name => 'SecondarySlotFunction', PrintConv => \%secondarySlotFunctionZ9 },
8845
9047
  592 => { Name => 'DXCropAlert', PrintConv => \%offOn },
8846
9048
  594 => { Name => 'SubjectDetection', PrintConv => \%subjectDetectionZ9 },
9049
+ 596 => {
9050
+ Name => 'DynamicAFAreaSize',
9051
+ Condition => '$$self{AFAraMode} = 2',
9052
+ RawConv => '$$self{DynamicAFAreaSize} = $val',
9053
+ PrintConv => \%dynamicAfAreaModesZ9,
9054
+ },
8847
9055
  636 => { Name => 'HighFrequencyFlickerReductionShooting', PrintConv => \%offOn, Unknown => 1 }, # new with firmware 3.0
8848
9056
  646 => {
8849
9057
  Name => 'MovieImageArea',
@@ -11222,6 +11430,7 @@ my %nikonFocalConversions = (
11222
11430
  # construct lens ID string as per ref 11
11223
11431
  ValueConv => 'sprintf("%.2X"." %.2X"x7, @raw)',
11224
11432
  PrintConv => \%nikonLensIDs,
11433
+ PrintInt => 1,
11225
11434
  },
11226
11435
  AutoFocus => {
11227
11436
  Require => {
@@ -11628,19 +11837,19 @@ sub ProcessNikonApp($;$)
11628
11837
  my $trailerLen = unpack('N', $buff);
11629
11838
  $trailerLen > $fileEnd and $et->Warn('Bad NikonApp trailer size'), return 0;
11630
11839
  if ($dirInfo) {
11631
- $$dirInfo{DirLen} = $trailerLen if $dirInfo;
11840
+ $$dirInfo{DirLen} = $trailerLen;
11632
11841
  $$dirInfo{DataPos} = $fileEnd - $trailerLen;
11633
11842
  if ($$dirInfo{OutFile}) {
11634
11843
  if ($$et{DEL_GROUP}{NikonApp}) {
11844
+ $et->VPrint(0, " Deleting NikonApp trailer ($trailerLen bytes)\n");
11635
11845
  ++$$et{CHANGED};
11636
- # just copy the trailer when writing
11846
+ # just copy the trailer when writing (read directly into output buffer)
11637
11847
  } elsif ($trailerLen > $fileEnd or not $raf->Seek($$dirInfo{DataPos}, 0) or
11638
11848
  $raf->Read(${$$dirInfo{OutFile}}, $trailerLen) != $trailerLen)
11639
11849
  {
11640
11850
  return 0;
11641
- } else {
11642
- return 1;
11643
11851
  }
11852
+ return 1;
11644
11853
  }
11645
11854
  $et->DumpTrailer($dirInfo) if $verbose or $$et{HTML_DUMP};
11646
11855
  }
@@ -11728,51 +11937,113 @@ sub ProcessNikonMOV($$$)
11728
11937
  return 1;
11729
11938
  }
11730
11939
 
11940
+ #------------------------------------------------------------------------------
11941
+ # Get offset of end-of-data for a tag
11942
+ # Inputs: 0) tag table ref, 1) tag ID, 2) true to not calculate end for a SubDirectory
11943
+ # Returns: offset of tag value end, undef if it can't be determined
11944
+ sub GetTagEnd($$;$)
11945
+ {
11946
+ my ($tagTablePtr, $tagID, $ignoreSubdir) = @_;
11947
+ my $tagInfo = $$tagTablePtr{$tagID};
11948
+ $tagInfo = $$tagInfo[0] if ref $tagInfo eq 'ARRAY';
11949
+ # (can't pre-determine position of offset-based subdirectories)
11950
+ return undef if $ignoreSubdir and $$tagInfo{SubDirectory};
11951
+ my $fmt = $$tagInfo{Format} || $$tagTablePtr{FORMAT} || 'int8u';
11952
+ my $nm = $fmt =~ s/\[(\d+)\]$// ? $1 : 1;
11953
+ my $sz = Image::ExifTool::FormatSize($fmt) or return undef;
11954
+ return int($tagID) + $sz * $nm;
11955
+ }
11956
+
11957
+ #------------------------------------------------------------------------------
11958
+ # Initialize SubDirectory KnownStart/KnownEnd limits of known tags (used in decryption)
11959
+ # Inputs: 0) tagInfo ref containing this SubDirectory, 2) tag table ref for encrypted subdir
11960
+ # Notes: KnownStart/KnownEnd are relative to the SubDirectory Start. If KnownStart/KnownEnd
11961
+ # aren't set then the entire data is decrypted, so all of this effort is just for speed.
11962
+ sub InitEncryptedSubdir($$)
11963
+ {
11964
+ my ($tagInfo, $tagTablePtr) = @_;
11965
+ #
11966
+ # for encrypted NIKON_OFFSETS tables we loop through all SubDirectory tags in this table
11967
+ # and set the KnownEnd for each of these according to the last tag in the child tables
11968
+ #
11969
+ my $vars = $$tagTablePtr{VARS};
11970
+ $vars or $vars = $$tagTablePtr{VARS} = { };
11971
+ if ($$vars{NIKON_OFFSETS} and not $$vars{NIKON_INITIALIZED}) {
11972
+ $$vars{NIKON_INITIALIZED} = 1;
11973
+ my $tagID;
11974
+ foreach $tagID (TagTableKeys($tagTablePtr)) {
11975
+ my $tagInfo = $$tagTablePtr{$tagID};
11976
+ next unless ref $tagInfo eq 'HASH';
11977
+ my $subdir = $$tagInfo{SubDirectory} or next;
11978
+ my $tbl = GetTagTable($$subdir{TagTable});
11979
+ my ($last) = sort { $b <=> $a } TagTableKeys($tbl); # (reverse sort)
11980
+ $$subdir{KnownEnd} = GetTagEnd($tbl, $last, 1);
11981
+ }
11982
+ }
11983
+ #
11984
+ # for other encrypted Nikon tables we set the KnownStart/KnownEnd entries in the
11985
+ # SubDirectory of the parent tag
11986
+ #
11987
+ unless ($$tagInfo{NikonInitialized}) {
11988
+ $$tagInfo{NikonInitialized} = 1;
11989
+ my $subdir = $$tagInfo{SubDirectory};
11990
+ my $start = $$subdir{DecryptStart} || 0;
11991
+ my $off = $$subdir{DirOffset};
11992
+ my @tagIDs = sort { $a <=> $b } TagTableKeys($tagTablePtr);
11993
+ if (defined $off) {
11994
+ $off += $start; # (DirOffset, if specified, is relative to DecryptStart)
11995
+ } else {
11996
+ # ignore tags that come before the start of encryption
11997
+ shift @tagIDs while @tagIDs and $tagIDs[0] < $start;
11998
+ $off = 0;
11999
+ }
12000
+ if (@tagIDs) {
12001
+ my ($first, $last) = @tagIDs[0,-1];
12002
+ my $lastInfo = $$tagTablePtr{$last};
12003
+ $lastInfo = $$lastInfo[0] if ref $lastInfo eq 'ARRAY';
12004
+ $$subdir{KnownStart} = int($first) + $off if $first + $off > $start;
12005
+ $$subdir{KnownEnd} = GetTagEnd($tagTablePtr, $last);
12006
+ if (defined $$subdir{KnownEnd}) {
12007
+ $$subdir{KnownEnd} += $off;
12008
+ } else {
12009
+ warn "Internal error setting KnownEnd for $$tagTablePtr{SHORT_NAME}\n";
12010
+ }
12011
+ } else {
12012
+ $$subdir{KnownStart} = $$subdir{KnownEnd} = $start;
12013
+ }
12014
+ }
12015
+ }
12016
+
11731
12017
  #------------------------------------------------------------------------------
11732
12018
  # Prepare to process NIKON_OFFSETS directory and decrypt necessary data
11733
12019
  # Inputs: 0) ExifTool ref, 1) data ref, 2) tag table ref, 3) decrypt start,
11734
- # 4) serial key, 5) count key, 6) decrypt mode (0=piecewise,
11735
- # 1=continuous to end of last known section, 2=all)
12020
+ # 4) decrypt mode (0=piecewise, 1=continuous to end of last known section, 2=all)
11736
12021
  # Returns: end of decrypted data (or undef for piecewise decryption)
11737
- sub PrepareNikonOffsets($$$$$$$)
12022
+ sub PrepareNikonOffsets($$$$$)
11738
12023
  {
11739
- my ($et, $dataPt, $tagTablePtr, $start, $serial, $count, $decryptMode) = @_;
12024
+ my ($et, $dataPt, $tagTablePtr, $start, $decryptMode) = @_;
11740
12025
  my $offset = $$tagTablePtr{VARS}{NIKON_OFFSETS};
11741
- my $unknown = $et->Options('Unknown');
11742
12026
  my $dataLen = length $$dataPt;
11743
12027
  return undef if $offset + 4 > $dataLen or $offset < $start;
11744
- my $dpos = $offset + 4; # decrypt the first 4 bytes
12028
+ my $serial = $$et{NikonSerialKey};
12029
+ my $count = $$et{NikonCountKey};
12030
+ my $dpos = $offset + 4; # decrypt up to NumberOffsets
11745
12031
  $$dataPt = Decrypt($dataPt, $start, $dpos - $start, $serial, $count);
11746
12032
  my $numOffsets = Get32u($dataPt, $offset);
11747
- my $more = $numOffsets * 4;
12033
+ my $more = $numOffsets * 4; # more bytes to decrypt entire offsets table
11748
12034
  return undef if $offset + 4 + $more > $dataLen;
11749
12035
  $$dataPt = Decrypt($dataPt, $dpos, $more);
11750
12036
  $dpos += $more;
11751
- my $doneAlready = $$tagTablePtr{VARS}{NIKON_OFFSETS_DONE};
11752
- $$tagTablePtr{VARS}{NIKON_OFFSETS_DONE} = 1;
11753
- my ($i, @offInfo);
12037
+ my $unknown = $et->Options('Unknown');
12038
+ my ($i, @offInfo, $end);
12039
+ # extract non-zero offsets and create unknown subdirectories if Unknown > 1
11754
12040
  for ($i=0; $i<$numOffsets; ++$i) {
11755
12041
  my $pos = $offset + 4 + 4 * $i;
11756
12042
  my $off = Get32u($dataPt, $pos) or next;
11757
12043
  my $tagInfo = $$tagTablePtr{$pos};
12044
+ my $known = 0;
11758
12045
  if ($tagInfo) {
11759
- if (not $doneAlready and ref $tagInfo eq 'HASH' and
11760
- not $$tagInfo{Unknown} and $$tagInfo{SubDirectory})
11761
- {
11762
- # determine length of subdirectory up to end of last known tag
11763
- my $subdir = $$tagInfo{SubDirectory};
11764
- my $tbl = GetTagTable($$subdir{TagTable});
11765
- my ($last) = sort { $b <=> $a } TagTableKeys($tbl);
11766
- my $lastInfo = $$tbl{$last};
11767
- $lastInfo = $$lastInfo[0] if ref $lastInfo eq 'ARRAY';
11768
- # (can't pre-determine known length of offset-based subdirectories)
11769
- unless ($$lastInfo{SubDirectory}) {
11770
- my $fmt = $$lastInfo{Format} || $$tbl{FORMAT} || 'int8u';
11771
- my $nm = $fmt =~ s/\[(\d+)\]$// ? $1 : 1;
11772
- my $sz = Image::ExifTool::FormatSize($fmt);
11773
- $$subdir{KnownLen} = int($last) + $sz * $nm if $sz;
11774
- }
11775
- }
12046
+ $known = 1 if ref $tagInfo ne 'HASH' or not $$tagInfo{Unknown};
11776
12047
  } elsif ($unknown > 1) {
11777
12048
  # create new table for unknown information
11778
12049
  my $tbl = sprintf('Image::ExifTool::Nikon::UnknownInfo%.2x', $pos);
@@ -11789,12 +12060,8 @@ sub PrepareNikonOffsets($$$$$$$)
11789
12060
  Unknown => 2,
11790
12061
  });
11791
12062
  }
11792
- if ($off) {
11793
- my $known = ($tagInfo and (ref $tagInfo ne 'HASH' or not $$tagInfo{Unknown})) ? 1 : 0;
11794
- push @offInfo, [ $pos, $off, $known ];
11795
- }
12063
+ push @offInfo, [ $pos, $off, $known ]; # save parameters for non-zero offsets
11796
12064
  }
11797
- my $end;
11798
12065
  # sort offsets in ascending order, and use the differences to calculate
11799
12066
  # directory lengths and update the SubDirectory DirLen's accordingly
11800
12067
  my @sorted = sort { $$a[1] <=> $$b[1] or $$a[0] <=> $$b[0] } @offInfo;
@@ -11805,17 +12072,15 @@ sub PrepareNikonOffsets($$$$$$$)
11805
12072
  # set DirLen in SubDirectory entry
11806
12073
  my $tagInfo = $$tagTablePtr{$pos};
11807
12074
  my $subdir;
11808
- if (ref $tagInfo eq 'HASH' and defined($subdir=$$tagInfo{SubDirectory})) {
11809
- $$tagInfo{SubDirectory}{DirLen} = $len;
11810
- }
12075
+ $$subdir{DirLen} = $len if ref $tagInfo eq 'HASH' and defined($subdir=$$tagInfo{SubDirectory});
11811
12076
  if ($decryptMode) {
11812
12077
  # keep track of end of last known directory
11813
12078
  $end = $sorted[$i+1][1] if $sorted[$i][2];
11814
12079
  } elsif ($tagInfo and (ref $tagInfo ne 'HASH' or not $$tagInfo{Unknown})) {
11815
12080
  # decrypt data piecewise as necessary
11816
12081
  my $n = $len;
11817
- if ($subdir and $$subdir{KnownLen}) {
11818
- $n = $$subdir{KnownLen};
12082
+ if ($subdir and $$subdir{KnownEnd}) {
12083
+ $n = $$subdir{KnownEnd};
11819
12084
  if ($n > $len) {
11820
12085
  $et->Warn("Data too short for $$tagInfo{Name}",1);
11821
12086
  $n = $len;
@@ -11863,7 +12128,7 @@ sub ProcessNikonEncrypted($$$)
11863
12128
  my $dirStart = $$dirInfo{DirStart};
11864
12129
  my $data = substr(${$$dirInfo{DataPt}}, $dirStart, $$dirInfo{DirLen});
11865
12130
 
11866
- my ($start, $len, $offset, $byteOrder, $recrypt, $newSerial, $newCount, $didDecrypt);
12131
+ my ($start, $len, $offset, $recrypt, $newSerial, $newCount, $didDecrypt);
11867
12132
 
11868
12133
  # must re-encrypt when writing if serial number or shutter count changes
11869
12134
  if ($isWriting) {
@@ -11877,28 +12142,39 @@ sub ProcessNikonEncrypted($$$)
11877
12142
  }
11878
12143
  }
11879
12144
  if ($tagInfo and $$tagInfo{SubDirectory}) {
12145
+ # initialize SubDirectory entries used in encryption (KnownStart, KnownEnd)
12146
+ InitEncryptedSubdir($tagInfo, $tagTablePtr);
11880
12147
  my $subdir = $$tagInfo{SubDirectory};
11881
12148
  $start = $$subdir{DecryptStart} || 0;
11882
- # DirOffset, if specified, is relative to start of encrypted data
12149
+ # DirOffset, if specified, is the offset to the start of the
12150
+ # directory relative to start of encrypted data
11883
12151
  $offset = defined $$subdir{DirOffset} ? $$subdir{DirOffset} + $start : 0;
11884
- $byteOrder = $$subdir{ByteOrder};
11885
- SetByteOrder($byteOrder) if $byteOrder;
12152
+ # must set byte ordering before calling PrepareNikonOffsets()
12153
+ SetByteOrder($$subdir{ByteOrder}) if $$subdir{ByteOrder};
11886
12154
  # prepare for processing NIKON_OFFSETS directory if necessary
11887
- if ($$tagTablePtr{VARS} and $$tagTablePtr{VARS}{NIKON_OFFSETS}) {
11888
- my $unknown = $et->Options('Verbose') > 2 || $et->Options('Unknown') > 1;
11889
- # decrypt mode: 0=piecewise, 1=continuous to end of last known section, 2=all
11890
- my $dMode = $isWriting ? ($recrypt ? 2 : 1) : ($unknown ? 2 : 0);
11891
- $len = PrepareNikonOffsets($et, \$data, $tagTablePtr, $start, $serial, $count, $dMode);
12155
+ my $unknown = $verbose > 2 || $et->Options('Unknown') > 1;
12156
+ # decrypt mode: 0=piecewise, 1=continuous to end of last known section, 2=all
12157
+ my $dMode = $isWriting ? ($recrypt ? 2 : 1) : ($unknown ? 2 : 0);
12158
+ if ($$tagTablePtr{VARS}{NIKON_OFFSETS}) {
12159
+ $len = PrepareNikonOffsets($et, \$data, $tagTablePtr, $start, $dMode);
11892
12160
  $didDecrypt = 1;
11893
- # may decrypt only part of the information to save time
11894
- } elsif ($verbose < 3 and $et->Options('Unknown') < 2 and not $recrypt) {
11895
- $len = $$subdir{DecryptLen};
12161
+ } elsif ($dMode < 2) {
12162
+ if ($dMode == 0 and $$subdir{KnownStart}) {
12163
+ # initialize decryption parameters for address DecryptStart address
12164
+ Decrypt(\$data, $start, 0, $serial, $count);
12165
+ # reset serial/count keys so we don't re-initialize below
12166
+ undef $serial;
12167
+ undef $count;
12168
+ # change decryption start to skip unnecessary data
12169
+ $start = $$subdir{KnownStart};
12170
+ }
12171
+ $len = $$subdir{KnownEnd} - $start if $$subdir{KnownEnd};
11896
12172
  }
11897
12173
  } else {
11898
12174
  $start = $offset = 0;
11899
12175
  }
11900
12176
  my $maxLen = length($data) - $start;
11901
- # decrypt all the data unless DecryptLen is given
12177
+ # decrypt all the data unless the length was specified
11902
12178
  $len = $maxLen unless $len and $len < $maxLen;
11903
12179
 
11904
12180
  $data = Decrypt(\$data, $start, $len, $serial, $count) unless $didDecrypt;