exiftool_vendored 12.57.0 → 12.58.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +14 -0
  3. data/bin/META.json +1 -1
  4. data/bin/META.yml +1 -1
  5. data/bin/README +2 -2
  6. data/bin/config_files/rotate_regions.config +1 -1
  7. data/bin/exiftool +25 -21
  8. data/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  9. data/bin/lib/Image/ExifTool/APE.pm +2 -2
  10. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +13 -14
  11. data/bin/lib/Image/ExifTool/Canon.pm +26 -6
  12. data/bin/lib/Image/ExifTool/DJI.pm +28 -2
  13. data/bin/lib/Image/ExifTool/Exif.pm +24 -5
  14. data/bin/lib/Image/ExifTool/FlashPix.pm +2 -2
  15. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -0
  16. data/bin/lib/Image/ExifTool/JPEG.pm +14 -2
  17. data/bin/lib/Image/ExifTool/LNK.pm +5 -4
  18. data/bin/lib/Image/ExifTool/MPEG.pm +2 -2
  19. data/bin/lib/Image/ExifTool/MakerNotes.pm +2 -2
  20. data/bin/lib/Image/ExifTool/Minolta.pm +6 -7
  21. data/bin/lib/Image/ExifTool/Nikon.pm +385 -110
  22. data/bin/lib/Image/ExifTool/Pentax.pm +8 -5
  23. data/bin/lib/Image/ExifTool/Photoshop.pm +3 -3
  24. data/bin/lib/Image/ExifTool/QuickTime.pm +5 -5
  25. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1 -1
  26. data/bin/lib/Image/ExifTool/README +8 -0
  27. data/bin/lib/Image/ExifTool/RIFF.pm +3 -3
  28. data/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
  29. data/bin/lib/Image/ExifTool/Sigma.pm +4 -4
  30. data/bin/lib/Image/ExifTool/Sony.pm +23 -1
  31. data/bin/lib/Image/ExifTool/TagLookup.pm +4457 -4441
  32. data/bin/lib/Image/ExifTool/TagNames.pod +76 -12
  33. data/bin/lib/Image/ExifTool/Validate.pm +5 -5
  34. data/bin/lib/Image/ExifTool/WriteExif.pl +42 -0
  35. data/bin/lib/Image/ExifTool/Writer.pl +3 -1
  36. data/bin/lib/Image/ExifTool/XMP.pm +2 -2
  37. data/bin/lib/Image/ExifTool.pm +57 -12
  38. data/bin/perl-Image-ExifTool.spec +1 -1
  39. data/lib/exiftool_vendored/version.rb +1 -1
  40. 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.20';
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',
@@ -5312,7 +5307,7 @@ my %nikonFocalConversions = (
5312
5307
  Name => 'LensMountType',
5313
5308
  RawConv => '$$self{LensMountType} = $val', # 0=> DSLR lens via FTZ style adapter; 1=> Native Z lens;
5314
5309
  Format => 'int8u',
5315
- Unknown => 1,
5310
+ #Unknown => 1,
5316
5311
  PrintConv => {
5317
5312
  0 => 'F-mount Lens',
5318
5313
  1 => 'Z-mount Lens',
@@ -5375,7 +5370,7 @@ my %nikonFocalConversions = (
5375
5370
  Name => 'LensPositionAbsolute', # <=0 at infinity. Typical value at CFD might be 58000. Only valid for Z-mount lenses.
5376
5371
  Condition => '$$self{NewLensData} and $$self{LensMountType} and $$self{LensMountType} == 1',
5377
5372
  Format => 'int32s',
5378
- Unknown => 1,
5373
+ #Unknown => 1,
5379
5374
  },
5380
5375
  );
5381
5376
 
@@ -5498,8 +5493,6 @@ my %nikonFocalConversions = (
5498
5493
  Format => 'int32u',
5499
5494
  Priority => 0,
5500
5495
  },
5501
- # note: DecryptLen currently set to 0x251
5502
-
5503
5496
  # 0x55c - int16u[2400] TiffMeteringImage2: 60x40 image (ShotInfoVersion 0800, ref JR)
5504
5497
  # 0x181c - int16u[1200] TiffMeteringImage?: 60x20 image for some NEF's (ShotInfoVersion 0800, ref JR)
5505
5498
  # 0x217c - int16u[2400] TiffMeteringImage3: 60x40 image (ShotInfoVersion 0800, ref JR)
@@ -5542,7 +5535,6 @@ my %nikonFocalConversions = (
5542
5535
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD40',
5543
5536
  },
5544
5537
  },
5545
- # note: DecryptLen currently set to 748
5546
5538
  );
5547
5539
 
5548
5540
  # shot information for D80 (encrypted) - ref JD
@@ -5622,7 +5614,6 @@ my %nikonFocalConversions = (
5622
5614
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD80',
5623
5615
  },
5624
5616
  },
5625
- # note: DecryptLen currently set to 765
5626
5617
  );
5627
5618
 
5628
5619
  # shot information for D90 (encrypted) - ref PH
@@ -5668,7 +5659,6 @@ my %nikonFocalConversions = (
5668
5659
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD90',
5669
5660
  },
5670
5661
  },
5671
- # note: DecryptLen currently set to 0x398
5672
5662
  );
5673
5663
 
5674
5664
  # shot information for the D3 firmware 0.37 and 1.00 (encrypted) - ref PH
@@ -5732,7 +5722,6 @@ my %nikonFocalConversions = (
5732
5722
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5733
5723
  },
5734
5724
  },
5735
- # note: DecryptLen currently set to 0x318
5736
5725
  );
5737
5726
 
5738
5727
  # shot information for the D3 firmware 1.10, 2.00 and 2.01 (encrypted) - ref PH
@@ -5827,7 +5816,6 @@ my %nikonFocalConversions = (
5827
5816
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5828
5817
  },
5829
5818
  },
5830
- # note: DecryptLen currently set to 0x321
5831
5819
  );
5832
5820
 
5833
5821
  # shot information for the D3X firmware 1.00 (encrypted) - ref PH
@@ -5873,7 +5861,6 @@ my %nikonFocalConversions = (
5873
5861
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5874
5862
  },
5875
5863
  },
5876
- # note: DecryptLen currently set to 0x323
5877
5864
  );
5878
5865
 
5879
5866
  # shot information for the D3S firmware 0.16 and 1.00 (encrypted) - ref PH
@@ -5928,7 +5915,6 @@ my %nikonFocalConversions = (
5928
5915
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
5929
5916
  },
5930
5917
  },
5931
- # note: DecryptLen currently set to 0x2e9
5932
5918
  );
5933
5919
 
5934
5920
  # shot information for the D300 firmware 1.00 (encrypted) - ref JD
@@ -6021,7 +6007,6 @@ my %nikonFocalConversions = (
6021
6007
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6022
6008
  },
6023
6009
  },
6024
- # note: DecryptLen currently set to 813
6025
6010
  );
6026
6011
 
6027
6012
  # shot information for the D300 firmware 1.10 (encrypted) - ref PH
@@ -6172,7 +6157,6 @@ my %nikonFocalConversions = (
6172
6157
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6173
6158
  },
6174
6159
  },
6175
- # note: DecryptLen currently set to 825
6176
6160
  );
6177
6161
 
6178
6162
  # shot information for the D300S firmware 1.00 (encrypted) - ref PH
@@ -6218,7 +6202,6 @@ my %nikonFocalConversions = (
6218
6202
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD3',
6219
6203
  },
6220
6204
  },
6221
- # note: DecryptLen currently set to 827
6222
6205
  );
6223
6206
 
6224
6207
  # shot information for the D700 firmware 1.02f (encrypted) - ref 29
@@ -6264,7 +6247,39 @@ my %nikonFocalConversions = (
6264
6247
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD700',
6265
6248
  },
6266
6249
  },
6267
- # note: DecryptLen currently set to 852
6250
+ );
6251
+
6252
+ # shot information for the D780 - ref #28
6253
+ %Image::ExifTool::Nikon::ShotInfoD780 = (
6254
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6255
+ WRITE_PROC => \&ProcessNikonEncrypted,
6256
+ CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6257
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
6258
+ DATAMEMBER => [ 0x04 ],
6259
+ IS_SUBDIR => [ 0x9c ],
6260
+ WRITABLE => 1,
6261
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6262
+ NOTES => 'These tags are extracted from encrypted data in images from the D780.',
6263
+ 0x00 => {
6264
+ Name => 'ShotInfoVersion',
6265
+ Format => 'string[4]',
6266
+ Writable => 0,
6267
+ },
6268
+ 0x04 => {
6269
+ Name => 'FirmwareVersion',
6270
+ DataMember => 'FirmwareVersion',
6271
+ Format => 'string[5]',
6272
+ Writable => 0,
6273
+ RawConv => '$$self{FirmwareVersion} = $val',
6274
+ },
6275
+ 0x9c => {
6276
+ Name => 'OrientOffset',
6277
+ Format => 'int32u',
6278
+ SubDirectory => {
6279
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
6280
+ Start => '$val',
6281
+ },
6282
+ },
6268
6283
  );
6269
6284
 
6270
6285
  # shot information for the D5000 firmware 1.00 (encrypted) - ref PH
@@ -6310,7 +6325,6 @@ my %nikonFocalConversions = (
6310
6325
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5000',
6311
6326
  },
6312
6327
  },
6313
- # note: DecryptLen currently set to 0x39a
6314
6328
  );
6315
6329
 
6316
6330
  # shot information for the D5100 firmware 1.00f (encrypted) - ref PH
@@ -6345,7 +6359,6 @@ my %nikonFocalConversions = (
6345
6359
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5100',
6346
6360
  },
6347
6361
  },
6348
- # note: DecryptLen currently set to 0x430
6349
6362
  );
6350
6363
 
6351
6364
  # shot information for the D5200 firmware 1.00 (encrypted) - ref PH
@@ -6383,7 +6396,6 @@ my %nikonFocalConversions = (
6383
6396
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD5200',
6384
6397
  },
6385
6398
  },
6386
- # note: DecryptLen currently set to 0xd00
6387
6399
  );
6388
6400
 
6389
6401
  # shot information for the D7000 firmware 1.01d (encrypted) - ref 29
@@ -6431,6 +6443,39 @@ my %nikonFocalConversions = (
6431
6443
  },
6432
6444
  );
6433
6445
 
6446
+ # shot information for the D7500 - ref #28
6447
+ %Image::ExifTool::Nikon::ShotInfoD7500 = (
6448
+ PROCESS_PROC => \&ProcessNikonEncrypted,
6449
+ WRITE_PROC => \&ProcessNikonEncrypted,
6450
+ CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
6451
+ VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x0c },
6452
+ DATAMEMBER => [ 0x04 ],
6453
+ IS_SUBDIR => [ 0xa0 ],
6454
+ WRITABLE => 1,
6455
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
6456
+ NOTES => 'These tags are extracted from encrypted data in images from the D7500.',
6457
+ 0x00 => {
6458
+ Name => 'ShotInfoVersion',
6459
+ Format => 'string[4]',
6460
+ Writable => 0,
6461
+ },
6462
+ 0x04 => {
6463
+ Name => 'FirmwareVersion',
6464
+ DataMember => 'FirmwareVersion',
6465
+ Format => 'string[5]',
6466
+ Writable => 0,
6467
+ RawConv => '$$self{FirmwareVersion} = $val',
6468
+ },
6469
+ 0xa0 => {
6470
+ Name => 'OrientOffset',
6471
+ Format => 'int32u',
6472
+ SubDirectory => {
6473
+ TagTable => 'Image::ExifTool::Nikon::OrientationInfo',
6474
+ Start => '$val',
6475
+ },
6476
+ },
6477
+ );
6478
+
6434
6479
  # shot information for the D800 firmware 1.01a (encrypted) - ref PH
6435
6480
  %Image::ExifTool::Nikon::ShotInfoD800 = (
6436
6481
  PROCESS_PROC => \&ProcessNikonEncrypted,
@@ -6549,7 +6594,6 @@ my %nikonFocalConversions = (
6549
6594
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD800',
6550
6595
  },
6551
6596
  },
6552
- # note: DecryptLen currently set to 0x720
6553
6597
  );
6554
6598
 
6555
6599
  # shot information for the D5 firmware 1.10a and D500 firmware 1.01 (encrypted) - ref 28
@@ -7009,7 +7053,6 @@ my %nikonFocalConversions = (
7009
7053
  3 => 'Highlight'
7010
7054
  },
7011
7055
  },
7012
- # note: DecryptLen currently set to OtherOffset + 0x2ea5 - 0x2c90
7013
7056
  );
7014
7057
 
7015
7058
  # shot information for the D6 firmware 1.00 (encrypted) - ref 28
@@ -7244,7 +7287,6 @@ my %nikonFocalConversions = (
7244
7287
  TagTable => 'Image::ExifTool::NikonCustom::SettingsD610',
7245
7288
  },
7246
7289
  },
7247
- # note: DecryptLen currently set to 0x7ff
7248
7290
  );
7249
7291
 
7250
7292
  # shot information for the D810 firmware 1.00(PH)/1.01 (encrypted) - ref 28
@@ -7678,7 +7720,6 @@ my %nikonFocalConversions = (
7678
7720
  Format => 'undef[56]',
7679
7721
  SubDirectory => { TagTable => 'Image::ExifTool::NikonCustom::SettingsD4' },
7680
7722
  },
7681
- # note: DecryptLen currently set to 0x789
7682
7723
  );
7683
7724
 
7684
7725
  # shot information for the D4S firmware 1.01a (ref 28, encrypted)
@@ -7970,7 +8011,6 @@ my %nikonFocalConversions = (
7970
8011
  3 => 'Rotate 180',
7971
8012
  },
7972
8013
  },
7973
- # note: DecryptLen currently set to 0x3697
7974
8014
  );
7975
8015
 
7976
8016
  # shot information for the Z7II firmware 1.00 (encrypted) - ref 28
@@ -8115,7 +8155,7 @@ my %nikonFocalConversions = (
8115
8155
  CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
8116
8156
  VARS => { ID_LABEL => 'Index', NIKON_OFFSETS => 0x24 },
8117
8157
  DATAMEMBER => [ 0x04 ],
8118
- IS_SUBDIR => [ 0x30, 0x84, 0x8c ],
8158
+ IS_SUBDIR => [ 0x30, 0x58, 0x84, 0x8c ],
8119
8159
  WRITABLE => 1,
8120
8160
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8121
8161
  NOTES => 'These tags are extracted from encrypted data in images from the Z9.',
@@ -8158,6 +8198,15 @@ my %nikonFocalConversions = (
8158
8198
  Start => '$val',
8159
8199
  },
8160
8200
  },
8201
+ 0x58 => {
8202
+ Name => 'Offset13', #offset13 - length x'8f80 (Z9 firmware 3.01 NEF), using currently for a few foucs related tags. Might be premature to give the offset a more meaningful name at this point.
8203
+ Condition => '$$self{FirmwareVersion} and $$self{FirmwareVersion} ge "03.01"',
8204
+ Format => 'int32u',
8205
+ SubDirectory => {
8206
+ TagTable => 'Image::ExifTool::Nikon::Offset13InfoZ9',
8207
+ Start => '$val',
8208
+ },
8209
+ },
8161
8210
  0x84 => {
8162
8211
  Name => 'OrientOffset',
8163
8212
  Condition => '$$self{ShutterMode} and $$self{ShutterMode} ne 96', #not valid for C30/C60/C120
@@ -8177,6 +8226,7 @@ my %nikonFocalConversions = (
8177
8226
  },
8178
8227
  );
8179
8228
 
8229
+ # ref 28
8180
8230
  %Image::ExifTool::Nikon::SeqInfoZ9 = (
8181
8231
  %binaryDataAttrs,
8182
8232
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
@@ -8213,6 +8263,151 @@ my %nikonFocalConversions = (
8213
8263
  },
8214
8264
  );
8215
8265
 
8266
+ # ref 28
8267
+ %Image::ExifTool::Nikon::Offset13InfoZ9 = (
8268
+ %binaryDataAttrs,
8269
+ GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8270
+ DATAMEMBER => [ 0x0bea, 0x0beb ],
8271
+ 0x0be8 => {
8272
+ Name => 'AFAreaInitialXPosition', #stored as a representation of the horizontal position of the center of the portion of the focus box positioned top left when in Wide Area (L/S/C1/C2) focus modes (before subject detection potentially refines focus)
8273
+ Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2 ', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8274
+ Format => 'int8s',
8275
+ PrintConv => q{
8276
+ #in FX mode and Single-point, the 29 horizontal focus points are spaced 259 pixels apart starting at pixel 502 and ending at 7754. Spacing is the same for Wide(L/C1/C2) with different start points.
8277
+ #in FX mode and Dynamic(L), the 27 horizontal focus points are spaced 259 pixels apart starting at pixel 761 and ending at 7495
8278
+ #in FX mode and Dynamic(M), the 29 horizontal focus points are spaced 259 pixels apart starting at pixel 502 and ending at 7754
8279
+ #in DX mode and Single-point, the 19 horizontal focus points are spaced 388 pixels apart starting at pixel 636 and ending at 7620. [These correspond to FX positions and match the corresponding values in AFAreaMode tag AFAreaXPosition].
8280
+ #in DX mode and Wide(S), the 17 horizontal focus points are spaced 393 pixels apart starting at pixel 591 and ending at 7272.
8281
+ #in DX mode and Dynamic(L), the 17 horizontal focus points are spaced 388 pixels apart starting at pixel 1024 and ending at 7232
8282
+ #in DX mode and Dynamic(M), the 19 horizontal focus points are spaced 388 pixels apart starting at pixel 636 and ending at 7620
8283
+
8284
+ my $areaMode = $$self{VALUE}{PhotoShootingMenuBankImageArea};
8285
+ my $afAreaMode = $$self{VALUE}{AFAreaMode};
8286
+ my $dynamicAFAreaSize = $$self{VALUE}{DynamicAFAreaSize};
8287
+
8288
+ my $FX = 0;
8289
+ my $DX = 1;
8290
+
8291
+ my $Single = 1;
8292
+ my $Dynamic = 2;
8293
+ my $WideS = 3;
8294
+ my $WideL = 4;
8295
+ my $ThreeD = 5;
8296
+ my $Auto = 6;
8297
+ my $WideC1 = 12;
8298
+
8299
+ my $DynamicS = 0;
8300
+ my $DynamicM = 1;
8301
+ my $DynamicL = 2;
8302
+
8303
+ my $start = 502; #FX - all flavors
8304
+ $start = 636 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic (L/M/S) + 3D + Auto
8305
+ $start = 591 if $areaMode == $DX and $afAreaMode == $WideS ; #DX Wide(S)
8306
+
8307
+ my $increment = 259; #FX - all flavors
8308
+ $increment = 388 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic (L/M/S) + 3D + Auto
8309
+ $increment = 393 if $areaMode == $DX and $afAreaMode == $WideS ; #DX Wide(S)
8310
+
8311
+ my $divisor = 4;
8312
+ $divisor = 6 if $areaMode == $DX ;
8313
+
8314
+ my $offsetVal = 0;
8315
+ $offsetVal = 12 if $areaMode == $FX and $afAreaMode == $Dynamic ; #FX Dynamic (L/M) - force positive values so perl rounding toward zero isn't an issue
8316
+ $offsetVal = 18 if $areaMode == $DX and $afAreaMode == $Dynamic ; #DX Dynamic (L/M)
8317
+
8318
+ my $offsetSum = -1;
8319
+ $offsetSum = -4 if $afAreaMode == $Dynamic ; # Dynamic (L/M)
8320
+
8321
+ my $ncol = $$self{AFAreaInitialWidth};
8322
+ $ncol = int($ncol * 2 / 3) if $areaMode == $DX ; #DX
8323
+
8324
+ #some sample mappings:
8325
+ #FX Wide(S/L/C1/C2) [6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117] to 502, 761, 1020, 1279, 1538, 1797, 2056, 2315, 2574, 2833, 3092, 3351, 3610, 3869, 4128, 4387, 4646, 4905, 5164, 5423, 5682, 5941, 6200, 6459, 6718, 6977, 7236, 7495, 7754]
8326
+ #DX Wide(L/C1/C2) map for Wide(L)/C1/C2 [6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 67, 73, 79, 85, 91, 97, 103, 109, 115] to [636, 1024, 1412, 1800, 2188, 2576, 2964, 3352, 3740, 4128, 4516, 4904, 5292, 5680, 6068, 6456, 6844, 7232, 7620]
8327
+ #DX Wide(S) for Wide(S) [6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 67, 73, 79, 85, 91, 97, 103] to [984, 1377, 1770, 2163, 2556, 2949, 3342, 3735, 4128, 4521, 4914, 5307, 5700, 6093, 6486, 6879, 7272]
8328
+ #FX Dynamic (L) map [-9, -5, -1, 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93] to [761, 1020, 1279, 1538, 1797, 2056, 2315, 2574, 2833, 3092, 3351, 3610, 3869, 4128, 4387, 4646, 4905, 5164, 5423, 5682, 5941, 6200, 6459, 6718, 6977, 7236, 7495]
8329
+
8330
+ return $start + $increment * (int(($val + $offsetVal) / $divisor) + int($ncol / 2) + $offsetSum) ; #do not use simple int() becuase it rounds negative fractions toward zero resulting in duplicate values - instead use the 10xdivisor to force positive values
8331
+ },
8332
+ },
8333
+ 0x0be9 => {
8334
+ Name =>'AFAreaInitialYPosition', #stored as a representation of the vertical position of the center of the portion of the focus box positioned top left when in Wide Area (L/S/C1/C2) focus modes (before subject detection potentially refines focus)
8335
+ Condition => '$$self{ShutterMode} ne 96 and $$self{AFAreaMode} < 2', #not valid for C30/C60/C120 or for Area Modes 1:1 and 16:19
8336
+ Format => 'int8s',
8337
+ PrintConv => q{
8338
+ #in FX mode and Single-point, the 17 vertical focus points are spaced 291 pixels apart starting at pixel 424 and ending at 5080. Spacing is the same for Wide(L/C1/C2)
8339
+ #in FX mode and Dynamic(L), the 15 vertical focus points are spaced 291 pixels apart starting at pixel 715 and ending at 4789
8340
+ #in FX mode and Dynamic(M), the 17 vertical l focus points are spaced 291 pixels apart starting at pixel 424 and ending at 5080
8341
+ #in DX mode and Single-point, the 11 vertical focus points are spaced 436 pixels apart starting at pixel 572 and ending at 4932. [These correspond to FX positions and match the corresponding values in AFAreaMode tag AFAreaYPosition].
8342
+ #in DX Mode and Wide(S) the 9 vertical focus points are spaced 442 pixels apart starting at pixel 542 and ending at 4520
8343
+ #in DX mode and Dynamic(L), the 9 vertical focus points are spaced 436 pixels apart starting at pixel 1008 and ending at 4496
8344
+
8345
+ my $areaMode = $$self{VALUE}{PhotoShootingMenuBankImageArea};
8346
+ my $afAreaMode = $$self{VALUE}{AFAreaMode};
8347
+ my $dynamicAFAreaSize = $$self{VALUE}{DynamicAFAreaSize};
8348
+
8349
+ my $FX = 0;
8350
+ my $DX = 1;
8351
+
8352
+ my $Single = 1;
8353
+ my $Dynamic = 2;
8354
+ my $WideS = 3;
8355
+ my $WideL = 4;
8356
+ my $ThreeD = 5;
8357
+ my $Auto = 6;
8358
+ my $WideC1 = 12;
8359
+
8360
+ my $DynamicS = 0;
8361
+ my $DynamicM = 1;
8362
+ my $DynamicL = 2;
8363
+
8364
+ my $start = 424; #FX - all flavors
8365
+ $start = 572 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic(L/M/S) + 3D + Auto
8366
+ $start = 542 if $areaMode == $DX and $afAreaMode == 3 ; #DX Wide(S)
8367
+
8368
+ my $increment = 291; #FX - all flavors
8369
+ $increment = 436 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $WideL or $afAreaMode == $ThreeD or $afAreaMode == $Auto or $afAreaMode >= $WideC1); #DX Wide(L/C1/C2) + Dynamic (L/M/S) +3D + Auto
8370
+ $increment = 442 if $areaMode == $DX and $afAreaMode == 3 ; #DX Wide(S)
8371
+
8372
+ my $divisor = 7;
8373
+ $divisor = 10 if $areaMode == $DX ; #DX
8374
+
8375
+ my $offsetVal = -1;
8376
+ $offsetVal = 39 if $afAreaMode == $Dynamic and ( $dynamicAFAreaSize == $DynamicL ) ; #Dynamic (L) - force positive values so perl rounding toward zero isn't an issue
8377
+ $offsetVal = 40 if $afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicM ; #Dynamic (M)
8378
+ $offsetVal = 40 if $areaMode == $FX and (($afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicS) or $afAreaMode == $ThreeD) ; #FX Dynamic (S) or 3D
8379
+ $offsetVal = 38 if $areaMode == $DX and ($afAreaMode == $Dynamic and $dynamicAFAreaSize == $DynamicS ) ; #DX Dynamic (S)or 3D
8380
+
8381
+ my $offsetSum = 0;
8382
+ $offsetSum = -6 if $areaMode == $FX and ($afAreaMode == $Dynamic or $afAreaMode == $ThreeD); #FX Dynamic (L/M/S) or 3D
8383
+ $offsetSum = -4 if $areaMode == $DX and ($afAreaMode == $Dynamic or $afAreaMode == $ThreeD ); #DX Dynamic (L/M/S) or 3D
8384
+
8385
+ my $nrow = $$self{AFAreaInitialHeight};
8386
+ $nrow = int($nrow * 2 / 3) if $areaMode == $DX; #DX
8387
+
8388
+ #some sample mappings:
8389
+ #FX Wide(S/L/C1/C2) map [7, 13, 20, 27, 33, 40, 47, 53, 60, 67, 74, 80, 87, 94, 100, 107, 114] to [424, 715, 1006, 1297, 1588, 1879, 2170, 2461, 2752, 3043, 3334, 3625, 3916, 4207, 4498, 4789, 5080]
8390
+ #DX Wide(L/C1/C2) map [7, 17, 28, 38, 48, 58, 69, 79, 89, 100, 110] to [572, 1008, 1444, 1880, 2316, 2752, 3188, 3624, 4060, 4496, 4932]
8391
+ #DX Wide(S) map for Wide(S) [7, 17, 28, 38, 48, 58, 69, 79, 89] to [984, 1426, 1868, 2310, 2752, 3194, 3636, 4078, 4520]
8392
+ #FX Dynamic (L) map [-19, -13, -6, 0, 7, 13, 20, 27, 33, 40, 47, 53, 60, 67, 74] to [715, 1006, 1297, 1588, 1879, 2170, 2461, 2752, 3043, 3334, 3625, 3916, 4207, 4498, 4789]
8393
+
8394
+ return $start + $increment * (int(($val + $offsetVal) / $divisor) + int($nrow / 2) + $offsetSum) ;;
8395
+ },
8396
+ },
8397
+ 0x0bea => {
8398
+ Name => 'AFAreaInitialWidth',
8399
+ Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8400
+ ValueConv => '$$self{VALUE}{PhotoShootingMenuBankImageArea} eq 0 ? $val : int($val * 2 / 3)', #DX mode requires scaling down TODO: add support ImageAreas 1:1 and 16:9
8401
+ RawConv => '$$self{AFAreaInitialWidth} = 1 + int ($val / 4)', #convert from [3, 11, 19, 35, 51, 75] to [1, 3, 5, 9 13, 19] to match camera options for C1/C2 focus modes .. input/output of 11/3 is for Wide(S)
8402
+ },
8403
+ 0x0beb => {
8404
+ Name => 'AFAreaInitialHeight',
8405
+ Condition => '$$self{ShutterMode} ne 96', #not valid for C30/C60/C120
8406
+ ValueConv => '$$self{VALUE}{PhotoShootingMenuBankImageArea} eq 0 ? $val : int($val * 2 / 3)', #DX mode requires scaling down TODO: add support ImageAreas 1:1 and 16:9
8407
+ RawConv => '$$self{AFAreaInitialHeight} = 1 + int ($val / 7) ', #convert from [6, 20, 33, 46, 73] to [1, 3, 5, 7, 11] to match camera options for C1/C2 focus modes .. input/output of 33/5 is for Wide(L)
8408
+ },
8409
+ );
8410
+
8216
8411
  %Image::ExifTool::Nikon::MenuInfoZ9 = (
8217
8412
  %binaryDataAttrs,
8218
8413
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
@@ -8510,7 +8705,7 @@ my %nikonFocalConversions = (
8510
8705
  %Image::ExifTool::Nikon::MenuSettingsZ9 = (
8511
8706
  %binaryDataAttrs,
8512
8707
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8513
- DATAMEMBER => [ 140, 188, 192, 232, 424, 534 ],
8708
+ DATAMEMBER => [ 140, 188, 192, 232, 424, 534, 576 ],
8514
8709
  IS_SUBDIR => [ 799 ],
8515
8710
  NOTES => 'These tags are used by the Z9.',
8516
8711
  #90 ISO
@@ -8650,6 +8845,12 @@ my %nikonFocalConversions = (
8650
8845
  556 => { Name => 'SecondarySlotFunction', PrintConv => \%secondarySlotFunctionZ9 },
8651
8846
  572 => { Name => 'DXCropAlert', PrintConv => \%offOn },
8652
8847
  574 => { Name => 'SubjectDetection', PrintConv => \%subjectDetectionZ9 },
8848
+ 576 => {
8849
+ Name => 'DynamicAFAreaSize',
8850
+ Condition => '$$self{AFAraMode} = 2',
8851
+ RawConv => '$$self{DynamicAFAreaSize} = $val',
8852
+ PrintConv => \%dynamicAfAreaModesZ9,
8853
+ },
8653
8854
  604 => {
8654
8855
  Name => 'MovieImageArea',
8655
8856
  Unknown => 1,
@@ -8715,7 +8916,7 @@ my %nikonFocalConversions = (
8715
8916
  %Image::ExifTool::Nikon::MenuSettingsZ9v3 = (
8716
8917
  %binaryDataAttrs,
8717
8918
  GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
8718
- DATAMEMBER => [ 154, 204, 208, 248, 444, 554 ],
8919
+ DATAMEMBER => [ 154, 204, 208, 248, 444, 554, 596 ],
8719
8920
  IS_SUBDIR => [ 847 ],
8720
8921
  NOTES => 'These tags are used by the Z9 firmware 3.00.',
8721
8922
  72 => {
@@ -8844,6 +9045,12 @@ my %nikonFocalConversions = (
8844
9045
  576 => { Name => 'SecondarySlotFunction', PrintConv => \%secondarySlotFunctionZ9 },
8845
9046
  592 => { Name => 'DXCropAlert', PrintConv => \%offOn },
8846
9047
  594 => { Name => 'SubjectDetection', PrintConv => \%subjectDetectionZ9 },
9048
+ 596 => {
9049
+ Name => 'DynamicAFAreaSize',
9050
+ Condition => '$$self{AFAraMode} = 2',
9051
+ RawConv => '$$self{DynamicAFAreaSize} = $val',
9052
+ PrintConv => \%dynamicAfAreaModesZ9,
9053
+ },
8847
9054
  636 => { Name => 'HighFrequencyFlickerReductionShooting', PrintConv => \%offOn, Unknown => 1 }, # new with firmware 3.0
8848
9055
  646 => {
8849
9056
  Name => 'MovieImageArea',
@@ -11222,6 +11429,7 @@ my %nikonFocalConversions = (
11222
11429
  # construct lens ID string as per ref 11
11223
11430
  ValueConv => 'sprintf("%.2X"." %.2X"x7, @raw)',
11224
11431
  PrintConv => \%nikonLensIDs,
11432
+ PrintInt => 1,
11225
11433
  },
11226
11434
  AutoFocus => {
11227
11435
  Require => {
@@ -11728,51 +11936,113 @@ sub ProcessNikonMOV($$$)
11728
11936
  return 1;
11729
11937
  }
11730
11938
 
11939
+ #------------------------------------------------------------------------------
11940
+ # Get offset of end-of-data for a tag
11941
+ # Inputs: 0) tag table ref, 1) tag ID, 2) true to not calculate end for a SubDirectory
11942
+ # Returns: offset of tag value end, undef if it can't be determined
11943
+ sub GetTagEnd($$;$)
11944
+ {
11945
+ my ($tagTablePtr, $tagID, $ignoreSubdir) = @_;
11946
+ my $tagInfo = $$tagTablePtr{$tagID};
11947
+ $tagInfo = $$tagInfo[0] if ref $tagInfo eq 'ARRAY';
11948
+ # (can't pre-determine position of offset-based subdirectories)
11949
+ return undef if $ignoreSubdir and $$tagInfo{SubDirectory};
11950
+ my $fmt = $$tagInfo{Format} || $$tagTablePtr{FORMAT} || 'int8u';
11951
+ my $nm = $fmt =~ s/\[(\d+)\]$// ? $1 : 1;
11952
+ my $sz = Image::ExifTool::FormatSize($fmt) or return undef;
11953
+ return int($tagID) + $sz * $nm;
11954
+ }
11955
+
11956
+ #------------------------------------------------------------------------------
11957
+ # Initialize SubDirectory KnownStart/KnownEnd limits of known tags (used in decryption)
11958
+ # Inputs: 0) tagInfo ref containing this SubDirectory, 2) tag table ref for encrypted subdir
11959
+ # Notes: KnownStart/KnownEnd are relative to the SubDirectory Start. If KnownStart/KnownEnd
11960
+ # aren't set then the entire data is decrypted, so all of this effort is just for speed.
11961
+ sub InitEncryptedSubdir($$)
11962
+ {
11963
+ my ($tagInfo, $tagTablePtr) = @_;
11964
+ #
11965
+ # for encrypted NIKON_OFFSETS tables we loop through all SubDirectory tags in this table
11966
+ # and set the KnownEnd for each of these according to the last tag in the child tables
11967
+ #
11968
+ my $vars = $$tagTablePtr{VARS};
11969
+ $vars or $vars = $$tagTablePtr{VARS} = { };
11970
+ if ($$vars{NIKON_OFFSETS} and not $$vars{NIKON_INITIALIZED}) {
11971
+ $$vars{NIKON_INITIALIZED} = 1;
11972
+ my $tagID;
11973
+ foreach $tagID (TagTableKeys($tagTablePtr)) {
11974
+ my $tagInfo = $$tagTablePtr{$tagID};
11975
+ next unless ref $tagInfo eq 'HASH';
11976
+ my $subdir = $$tagInfo{SubDirectory} or next;
11977
+ my $tbl = GetTagTable($$subdir{TagTable});
11978
+ my ($last) = sort { $b <=> $a } TagTableKeys($tbl); # (reverse sort)
11979
+ $$subdir{KnownEnd} = GetTagEnd($tbl, $last, 1);
11980
+ }
11981
+ }
11982
+ #
11983
+ # for other encrypted Nikon tables we set the KnownStart/KnownEnd entries in the
11984
+ # SubDirectory of the parent tag
11985
+ #
11986
+ unless ($$tagInfo{NikonInitialized}) {
11987
+ $$tagInfo{NikonInitialized} = 1;
11988
+ my $subdir = $$tagInfo{SubDirectory};
11989
+ my $start = $$subdir{DecryptStart} || 0;
11990
+ my $off = $$subdir{DirOffset};
11991
+ my @tagIDs = sort { $a <=> $b } TagTableKeys($tagTablePtr);
11992
+ if (defined $off) {
11993
+ $off += $start; # (DirOffset, if specified, is relative to DecryptStart)
11994
+ } else {
11995
+ # ignore tags that come before the start of encryption
11996
+ shift @tagIDs while @tagIDs and $tagIDs[0] < $start;
11997
+ $off = 0;
11998
+ }
11999
+ if (@tagIDs) {
12000
+ my ($first, $last) = @tagIDs[0,-1];
12001
+ my $lastInfo = $$tagTablePtr{$last};
12002
+ $lastInfo = $$lastInfo[0] if ref $lastInfo eq 'ARRAY';
12003
+ $$subdir{KnownStart} = int($first) + $off if $first + $off > $start;
12004
+ $$subdir{KnownEnd} = GetTagEnd($tagTablePtr, $last);
12005
+ if (defined $$subdir{KnownEnd}) {
12006
+ $$subdir{KnownEnd} += $off;
12007
+ } else {
12008
+ warn "Internal error setting KnownEnd for $$tagTablePtr{SHORT_NAME}\n";
12009
+ }
12010
+ } else {
12011
+ $$subdir{KnownStart} = $$subdir{KnownEnd} = $start;
12012
+ }
12013
+ }
12014
+ }
12015
+
11731
12016
  #------------------------------------------------------------------------------
11732
12017
  # Prepare to process NIKON_OFFSETS directory and decrypt necessary data
11733
12018
  # 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)
12019
+ # 4) decrypt mode (0=piecewise, 1=continuous to end of last known section, 2=all)
11736
12020
  # Returns: end of decrypted data (or undef for piecewise decryption)
11737
- sub PrepareNikonOffsets($$$$$$$)
12021
+ sub PrepareNikonOffsets($$$$$)
11738
12022
  {
11739
- my ($et, $dataPt, $tagTablePtr, $start, $serial, $count, $decryptMode) = @_;
12023
+ my ($et, $dataPt, $tagTablePtr, $start, $decryptMode) = @_;
11740
12024
  my $offset = $$tagTablePtr{VARS}{NIKON_OFFSETS};
11741
- my $unknown = $et->Options('Unknown');
11742
12025
  my $dataLen = length $$dataPt;
11743
12026
  return undef if $offset + 4 > $dataLen or $offset < $start;
11744
- my $dpos = $offset + 4; # decrypt the first 4 bytes
12027
+ my $serial = $$et{NikonSerialKey};
12028
+ my $count = $$et{NikonCountKey};
12029
+ my $dpos = $offset + 4; # decrypt up to NumberOffsets
11745
12030
  $$dataPt = Decrypt($dataPt, $start, $dpos - $start, $serial, $count);
11746
12031
  my $numOffsets = Get32u($dataPt, $offset);
11747
- my $more = $numOffsets * 4;
12032
+ my $more = $numOffsets * 4; # more bytes to decrypt entire offsets table
11748
12033
  return undef if $offset + 4 + $more > $dataLen;
11749
12034
  $$dataPt = Decrypt($dataPt, $dpos, $more);
11750
12035
  $dpos += $more;
11751
- my $doneAlready = $$tagTablePtr{VARS}{NIKON_OFFSETS_DONE};
11752
- $$tagTablePtr{VARS}{NIKON_OFFSETS_DONE} = 1;
11753
- my ($i, @offInfo);
12036
+ my $unknown = $et->Options('Unknown');
12037
+ my ($i, @offInfo, $end);
12038
+ # extract non-zero offsets and create unknown subdirectories if Unknown > 1
11754
12039
  for ($i=0; $i<$numOffsets; ++$i) {
11755
12040
  my $pos = $offset + 4 + 4 * $i;
11756
12041
  my $off = Get32u($dataPt, $pos) or next;
11757
12042
  my $tagInfo = $$tagTablePtr{$pos};
12043
+ my $known = 0;
11758
12044
  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
- }
12045
+ $known = 1 if ref $tagInfo ne 'HASH' or not $$tagInfo{Unknown};
11776
12046
  } elsif ($unknown > 1) {
11777
12047
  # create new table for unknown information
11778
12048
  my $tbl = sprintf('Image::ExifTool::Nikon::UnknownInfo%.2x', $pos);
@@ -11789,12 +12059,8 @@ sub PrepareNikonOffsets($$$$$$$)
11789
12059
  Unknown => 2,
11790
12060
  });
11791
12061
  }
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
- }
12062
+ push @offInfo, [ $pos, $off, $known ]; # save parameters for non-zero offsets
11796
12063
  }
11797
- my $end;
11798
12064
  # sort offsets in ascending order, and use the differences to calculate
11799
12065
  # directory lengths and update the SubDirectory DirLen's accordingly
11800
12066
  my @sorted = sort { $$a[1] <=> $$b[1] or $$a[0] <=> $$b[0] } @offInfo;
@@ -11805,17 +12071,15 @@ sub PrepareNikonOffsets($$$$$$$)
11805
12071
  # set DirLen in SubDirectory entry
11806
12072
  my $tagInfo = $$tagTablePtr{$pos};
11807
12073
  my $subdir;
11808
- if (ref $tagInfo eq 'HASH' and defined($subdir=$$tagInfo{SubDirectory})) {
11809
- $$tagInfo{SubDirectory}{DirLen} = $len;
11810
- }
12074
+ $$subdir{DirLen} = $len if ref $tagInfo eq 'HASH' and defined($subdir=$$tagInfo{SubDirectory});
11811
12075
  if ($decryptMode) {
11812
12076
  # keep track of end of last known directory
11813
12077
  $end = $sorted[$i+1][1] if $sorted[$i][2];
11814
12078
  } elsif ($tagInfo and (ref $tagInfo ne 'HASH' or not $$tagInfo{Unknown})) {
11815
12079
  # decrypt data piecewise as necessary
11816
12080
  my $n = $len;
11817
- if ($subdir and $$subdir{KnownLen}) {
11818
- $n = $$subdir{KnownLen};
12081
+ if ($subdir and $$subdir{KnownEnd}) {
12082
+ $n = $$subdir{KnownEnd};
11819
12083
  if ($n > $len) {
11820
12084
  $et->Warn("Data too short for $$tagInfo{Name}",1);
11821
12085
  $n = $len;
@@ -11863,7 +12127,7 @@ sub ProcessNikonEncrypted($$$)
11863
12127
  my $dirStart = $$dirInfo{DirStart};
11864
12128
  my $data = substr(${$$dirInfo{DataPt}}, $dirStart, $$dirInfo{DirLen});
11865
12129
 
11866
- my ($start, $len, $offset, $byteOrder, $recrypt, $newSerial, $newCount, $didDecrypt);
12130
+ my ($start, $len, $offset, $recrypt, $newSerial, $newCount, $didDecrypt);
11867
12131
 
11868
12132
  # must re-encrypt when writing if serial number or shutter count changes
11869
12133
  if ($isWriting) {
@@ -11877,28 +12141,39 @@ sub ProcessNikonEncrypted($$$)
11877
12141
  }
11878
12142
  }
11879
12143
  if ($tagInfo and $$tagInfo{SubDirectory}) {
12144
+ # initialize SubDirectory entries used in encryption (KnownStart, KnownEnd)
12145
+ InitEncryptedSubdir($tagInfo, $tagTablePtr);
11880
12146
  my $subdir = $$tagInfo{SubDirectory};
11881
12147
  $start = $$subdir{DecryptStart} || 0;
11882
- # DirOffset, if specified, is relative to start of encrypted data
12148
+ # DirOffset, if specified, is the offset to the start of the
12149
+ # directory relative to start of encrypted data
11883
12150
  $offset = defined $$subdir{DirOffset} ? $$subdir{DirOffset} + $start : 0;
11884
- $byteOrder = $$subdir{ByteOrder};
11885
- SetByteOrder($byteOrder) if $byteOrder;
12151
+ # must set byte ordering before calling PrepareNikonOffsets()
12152
+ SetByteOrder($$subdir{ByteOrder}) if $$subdir{ByteOrder};
11886
12153
  # 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);
12154
+ my $unknown = $verbose > 2 || $et->Options('Unknown') > 1;
12155
+ # decrypt mode: 0=piecewise, 1=continuous to end of last known section, 2=all
12156
+ my $dMode = $isWriting ? ($recrypt ? 2 : 1) : ($unknown ? 2 : 0);
12157
+ if ($$tagTablePtr{VARS}{NIKON_OFFSETS}) {
12158
+ $len = PrepareNikonOffsets($et, \$data, $tagTablePtr, $start, $dMode);
11892
12159
  $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};
12160
+ } elsif ($dMode < 2) {
12161
+ if ($dMode == 0 and $$subdir{KnownStart}) {
12162
+ # initialize decryption parameters for address DecryptStart address
12163
+ Decrypt(\$data, $start, 0, $serial, $count);
12164
+ # reset serial/count keys so we don't re-initialize below
12165
+ undef $serial;
12166
+ undef $count;
12167
+ # change decryption start to skip unnecessary data
12168
+ $start = $$subdir{KnownStart};
12169
+ }
12170
+ $len = $$subdir{KnownEnd} - $start if $$subdir{KnownEnd};
11896
12171
  }
11897
12172
  } else {
11898
12173
  $start = $offset = 0;
11899
12174
  }
11900
12175
  my $maxLen = length($data) - $start;
11901
- # decrypt all the data unless DecryptLen is given
12176
+ # decrypt all the data unless the length was specified
11902
12177
  $len = $maxLen unless $len and $len < $maxLen;
11903
12178
 
11904
12179
  $data = Decrypt(\$data, $start, $len, $serial, $count) unless $didDecrypt;