exiftool_vendored 12.57.0 → 12.59.0

Sign up to get free protection for your applications and to get access to all the features.
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;