exiftool_vendored 12.57.0 → 12.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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;