exiftool-vendored.pl 12.55.0 → 12.60.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 (66) hide show
  1. package/bin/Changes +97 -4
  2. package/bin/MANIFEST +9 -0
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +19 -19
  6. package/bin/arg_files/xmp2exif.args +4 -1
  7. package/bin/config_files/example.config +1 -0
  8. package/bin/config_files/rotate_regions.config +1 -1
  9. package/bin/exiftool +197 -122
  10. package/bin/fmt_files/kml.fmt +3 -0
  11. package/bin/fmt_files/kml_track.fmt +3 -0
  12. package/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  13. package/bin/lib/Image/ExifTool/APE.pm +2 -2
  14. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +25 -19
  15. package/bin/lib/Image/ExifTool/Canon.pm +33 -7
  16. package/bin/lib/Image/ExifTool/CanonRaw.pm +5 -1
  17. package/bin/lib/Image/ExifTool/DJI.pm +28 -2
  18. package/bin/lib/Image/ExifTool/Exif.pm +107 -20
  19. package/bin/lib/Image/ExifTool/FlashPix.pm +92 -9
  20. package/bin/lib/Image/ExifTool/FujiFilm.pm +9 -4
  21. package/bin/lib/Image/ExifTool/GPS.pm +7 -2
  22. package/bin/lib/Image/ExifTool/Geotag.pm +30 -7
  23. package/bin/lib/Image/ExifTool/InfiRay.pm +227 -0
  24. package/bin/lib/Image/ExifTool/JPEG.pm +53 -7
  25. package/bin/lib/Image/ExifTool/Jpeg2000.pm +5 -5
  26. package/bin/lib/Image/ExifTool/LIF.pm +10 -2
  27. package/bin/lib/Image/ExifTool/LNK.pm +5 -4
  28. package/bin/lib/Image/ExifTool/MIE.pm +3 -3
  29. package/bin/lib/Image/ExifTool/MPEG.pm +2 -2
  30. package/bin/lib/Image/ExifTool/MakerNotes.pm +3 -2
  31. package/bin/lib/Image/ExifTool/Minolta.pm +6 -7
  32. package/bin/lib/Image/ExifTool/MinoltaRaw.pm +2 -1
  33. package/bin/lib/Image/ExifTool/Nikon.pm +1199 -1325
  34. package/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  35. package/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  36. package/bin/lib/Image/ExifTool/Olympus.pm +88 -6
  37. package/bin/lib/Image/ExifTool/OpenEXR.pm +32 -15
  38. package/bin/lib/Image/ExifTool/PNG.pm +89 -3
  39. package/bin/lib/Image/ExifTool/PanasonicRaw.pm +27 -1
  40. package/bin/lib/Image/ExifTool/Pentax.pm +8 -5
  41. package/bin/lib/Image/ExifTool/PhaseOne.pm +14 -1
  42. package/bin/lib/Image/ExifTool/Photoshop.pm +38 -7
  43. package/bin/lib/Image/ExifTool/QuickTime.pm +44 -13
  44. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +63 -20
  45. package/bin/lib/Image/ExifTool/README +19 -2
  46. package/bin/lib/Image/ExifTool/RIFF.pm +34 -13
  47. package/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
  48. package/bin/lib/Image/ExifTool/Real.pm +2 -2
  49. package/bin/lib/Image/ExifTool/Ricoh.pm +2 -1
  50. package/bin/lib/Image/ExifTool/Sigma.pm +5 -4
  51. package/bin/lib/Image/ExifTool/SigmaRaw.pm +9 -3
  52. package/bin/lib/Image/ExifTool/Sony.pm +28 -1
  53. package/bin/lib/Image/ExifTool/TagLookup.pm +4691 -4624
  54. package/bin/lib/Image/ExifTool/TagNames.pod +511 -117
  55. package/bin/lib/Image/ExifTool/VCard.pm +19 -5
  56. package/bin/lib/Image/ExifTool/Validate.pm +5 -5
  57. package/bin/lib/Image/ExifTool/WriteExif.pl +42 -0
  58. package/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  59. package/bin/lib/Image/ExifTool/Writer.pl +150 -36
  60. package/bin/lib/Image/ExifTool/XMP.pm +19 -4
  61. package/bin/lib/Image/ExifTool/XMP2.pl +2 -1
  62. package/bin/lib/Image/ExifTool.pm +248 -54
  63. package/bin/lib/Image/ExifTool.pod +94 -58
  64. package/bin/perl-Image-ExifTool.spec +18 -18
  65. package/bin/pp_build_exe.args +7 -6
  66. package/package.json +3 -3
@@ -29,7 +29,7 @@ use vars qw($VERSION);
29
29
  use Image::ExifTool qw(:Public);
30
30
  use Image::ExifTool::GPS;
31
31
 
32
- $VERSION = '1.70';
32
+ $VERSION = '1.71';
33
33
 
34
34
  sub JITTER() { return 2 } # maximum time jitter
35
35
 
@@ -92,7 +92,7 @@ my %isOrient = ( dir => 1, pitch => 1, roll => 1 ); # test for orientation key
92
92
  # tags which may exist separately in some formats (eg. CSV)
93
93
  my %sepTags = ( dir => 1, pitch => 1, roll => 1, track => 1, speed => 1 );
94
94
 
95
- # conversion factors for GPSSpeed
95
+ # conversion factors for GPSSpeed (standard EXIF units only)
96
96
  my %speedConv = (
97
97
  'K' => 1.852, # km/h per knot
98
98
  'M' => 1.150779448, # mph per knot
@@ -102,7 +102,14 @@ my %speedConv = (
102
102
  'mph' => 'M',
103
103
  );
104
104
 
105
- my $secPerDay = 24 * 3600; # a useful constant
105
+ # all recognized speed conversion factors (non-EXIF included)
106
+ my %otherConv = (
107
+ 'km/h' => 1.852,
108
+ 'mph' => 1.150779448,
109
+ 'm/s' => 0.514444,
110
+ );
111
+
112
+ my $secPerDay = 24 * 3600; # a useful constant
106
113
 
107
114
  #------------------------------------------------------------------------------
108
115
  # Load GPS track log file
@@ -140,6 +147,7 @@ sub LoadTrackLog($$;$)
140
147
  my ($raf, $from, $time, $isDate, $noDate, $noDateChanged, $lastDate, $dateFlarm);
141
148
  my ($nmeaStart, $fixSecs, @fixTimes, $lastFix, %nmea, @csvHeadings, $sortFixes);
142
149
  my ($canCut, $cutPDOP, $cutHDOP, $cutSats, $e0, $e1, @tmp, $trackFile, $trackTime);
150
+ my $scaleSpeed;
143
151
 
144
152
  unless (eval { require Time::Local }) {
145
153
  return 'Geotag feature requires Time::Local installed';
@@ -246,7 +254,9 @@ sub LoadTrackLog($$;$)
246
254
  $format = 'CSV';
247
255
  # convert recognized headings to our parameter names
248
256
  foreach (@csvHeadings) {
257
+ my $head = $_;
249
258
  my $param;
259
+ my $xtra = '';
250
260
  s/^GPS ?//; # remove leading "GPS" to simplify regex patterns
251
261
  if (/^Time ?\(seconds\)$/i) { # DJI
252
262
  # DJI CSV log files have a column "Time(seconds)" which is seconds since
@@ -274,7 +284,16 @@ sub LoadTrackLog($$;$)
274
284
  /ref$/i and $param .= 'ref';
275
285
  } elsif (/^(Pos)?Alt/i) {
276
286
  $param = 'alt';
277
- } elsif (/^(Angle)?(Heading|Track)/i) {
287
+ } elsif (/^Speed/i) {
288
+ $param = 'speed';
289
+ # (recognize units in brackets)
290
+ if (m{\((mph|km/h|m/s)\)}) {
291
+ $scaleSpeed = $otherConv{$1};
292
+ $xtra = " in $1";
293
+ } else {
294
+ $xtra = ' in knots';
295
+ }
296
+ } elsif (/^(Angle)?(Heading|Track|Bearing)/i) {
278
297
  $param = 'track';
279
298
  } elsif (/^(Angle)?Pitch/i or /^Camera ?Elevation ?Angle/i) {
280
299
  $param = 'pitch';
@@ -284,10 +303,10 @@ sub LoadTrackLog($$;$)
284
303
  $param = 'dir';
285
304
  }
286
305
  if ($param) {
287
- $et->VPrint(2, "CSV column '${_}' is $param\n");
306
+ $et->VPrint(2, "CSV column '${head}' is $param$xtra\n");
288
307
  $_ = $param;
289
308
  } else {
290
- $et->VPrint(2, "CSV column '${_}' ignored\n");
309
+ $et->VPrint(2, "CSV column '${head}' ignored\n");
291
310
  $_ = ''; # ignore this column
292
311
  }
293
312
  }
@@ -479,9 +498,11 @@ DoneFix: $isDate = 1;
479
498
  my ($param, $date, $secs, %neg);
480
499
  foreach $param (@csvHeadings) {
481
500
  my $val = shift @vals;
482
- last unless defined $val;
501
+ last unless defined $val and length($val);
483
502
  next unless $param;
484
503
  if ($param eq 'datetime') {
504
+ # (fix formats like "24.07.2016 13:47:30")
505
+ $val =~ s/^(\d{2})[^\d](\d{2})[^\d](\d{4}) /$3:$2:$1 /;
485
506
  local $SIG{'__WARN__'} = sub { };
486
507
  my $dateTime = $et->InverseDateTime($val);
487
508
  if ($dateTime) {
@@ -510,6 +531,7 @@ DoneFix: $isDate = 1;
510
531
  $date = $trackTime;
511
532
  $secs = $val;
512
533
  } else {
534
+ $val /= $scaleSpeed if $scaleSpeed and $param eq 'speed';
513
535
  $$fix{$param} = $val;
514
536
  $$has{$param} = 1 if $sepTags{$param};
515
537
  }
@@ -1204,6 +1226,7 @@ Category: foreach $category (qw{pos track alt orient atemp}) {
1204
1226
  @r = $et->SetNewValue(GPSTrackRef => (defined $$tFix{track} ? 'T' : undef), %opts);
1205
1227
  my ($spd, $ref);
1206
1228
  if (defined($spd = $$tFix{speed})) {
1229
+ # convert to specified units if necessary
1207
1230
  $ref = $$et{OPTIONS}{GeoSpeedRef};
1208
1231
  if ($ref and defined $speedConv{$ref}) {
1209
1232
  $ref = $speedConv{$ref} if $speedConv{$speedConv{$ref}};
@@ -0,0 +1,227 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: InfiRay.pm
3
+ #
4
+ # Description: InfiRay IJPEG thermal image metadata
5
+ #
6
+ # Revisions: 2023-02-08 - M. Del Sol Created
7
+ #
8
+ # References: 1) https://github.com/exiftool/exiftool/pull/184
9
+ #
10
+ # Notes: Information in this document has been mostly gathered by
11
+ # disassembling the P2 Pro Android app, version 1.0.8.230111.
12
+ #------------------------------------------------------------------------------
13
+
14
+ package Image::ExifTool::InfiRay;
15
+
16
+ use strict;
17
+ use vars qw($VERSION);
18
+
19
+ $VERSION = '1.00';
20
+
21
+ my %convFloat2 = ( PrintConv => 'sprintf("%.2f", $val)' );
22
+ my %convPercent = ( PrintConv => 'sprintf("%.1f %%", $val * 100)' );
23
+ my %convMeters = ( PrintConv => 'sprintf("%.2f m", $val)' );
24
+ my %convCelsius = ( PrintConv => 'sprintf("%.2f C", $val)' );
25
+
26
+ # InfiRay IJPEG version header, found in JPEGs APP2
27
+ %Image::ExifTool::InfiRay::Version = (
28
+ GROUPS => { 0 => 'APP2', 2 => 'Image' },
29
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
30
+ VARS => { NO_LOOKUP => 1 }, # omit tags from lookup
31
+ NOTES => q{
32
+ This table lists tags found in the InfiRay APP2 IJPEG version header, found
33
+ in JPEGs taken with the P2 Pro camera app.
34
+ },
35
+ 0x00 => { Name => 'IJPEGVersion', Format => 'int8u[4]' },
36
+ # 0x04 => { Name => 'IJPEGSignature', Format => 'string[6]' }, # "IJPEG\0"
37
+ 0x0c => { Name => 'IJPEGOrgType', Format => 'int8u' },
38
+ 0x0d => { Name => 'IJPEGDispType', Format => 'int8u' },
39
+ 0x0e => { Name => 'IJPEGRotate', Format => 'int8u' },
40
+ 0x0f => { Name => 'IJPEGMirrorFlip', Format => 'int8u' },
41
+ 0x10 => { Name => 'ImageColorSwitchable', Format => 'int8u' },
42
+ 0x11 => { Name => 'ThermalColorPalette', Format => 'int16u' },
43
+ 0x20 => { Name => 'IRDataSize', Format => 'int64u' },
44
+ 0x28 => { Name => 'IRDataFormat', Format => 'int16u' },
45
+ 0x2a => { Name => 'IRImageWidth', Format => 'int16u' },
46
+ 0x2c => { Name => 'IRImageHeight', Format => 'int16u' },
47
+ 0x2e => { Name => 'IRImageBpp', Format => 'int8u' },
48
+ 0x30 => { Name => 'TempDataSize', Format => 'int64u' },
49
+ 0x38 => { Name => 'TempDataFormat', Format => 'int16u' },
50
+ 0x3a => { Name => 'TempImageWidth', Format => 'int16u' },
51
+ 0x3c => { Name => 'TempImageHeight', Format => 'int16u' },
52
+ 0x3e => { Name => 'TempImageBpp', Format => 'int8u' },
53
+ 0x40 => { Name => 'VisibleDataSize', Format => 'int64u' },
54
+ 0x48 => { Name => 'VisibleDataFormat', Format => 'int16u' },
55
+ 0x4a => { Name => 'VisibleImageWidth', Format => 'int16u' },
56
+ 0x4c => { Name => 'VisibleImageHeight', Format => 'int16u' },
57
+ 0x4e => { Name => 'VisibleImageBpp', Format => 'int8u' },
58
+ );
59
+
60
+ # InfiRay IJPEG factory temperature, found in IJPEG's APP4 section
61
+ %Image::ExifTool::InfiRay::Factory = (
62
+ GROUPS => { 0 => 'APP4', 2 => 'Image' },
63
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
64
+ VARS => { NO_LOOKUP => 1 }, # omit tags from lookup
65
+ NOTES => q{
66
+ This table lists tags found in the InfiRay APP4 IJPEG camera factory
67
+ defaults and calibration data.
68
+ },
69
+ 0x00 => { Name => 'IJPEGTempVersion', Format => 'int8u[4]' },
70
+ 0x04 => { Name => 'FactDefEmissivity', Format => 'int8s' },
71
+ 0x05 => { Name => 'FactDefTau', Format => 'int8s' },
72
+ 0x06 => { Name => 'FactDefTa', Format => 'int16s' },
73
+ 0x08 => { Name => 'FactDefTu', Format => 'int16s' },
74
+ 0x0a => { Name => 'FactDefDist', Format => 'int16s' },
75
+ 0x0c => { Name => 'FactDefA0', Format => 'int32s' },
76
+ 0x10 => { Name => 'FactDefB0', Format => 'int32s' },
77
+ 0x14 => { Name => 'FactDefA1', Format => 'int32s' },
78
+ 0x18 => { Name => 'FactDefB1', Format => 'int32s' },
79
+ 0x1c => { Name => 'FactDefP0', Format => 'int32s' },
80
+ 0x20 => { Name => 'FactDefP1', Format => 'int32s' },
81
+ 0x24 => { Name => 'FactDefP2', Format => 'int32s' },
82
+ 0x44 => { Name => 'FactRelSensorTemp', Format => 'int16s' },
83
+ 0x46 => { Name => 'FactRelShutterTemp', Format => 'int16s' },
84
+ 0x48 => { Name => 'FactRelLensTemp', Format => 'int16s' },
85
+ 0x64 => { Name => 'FactStatusGain', Format => 'int8s' },
86
+ 0x65 => { Name => 'FactStatusEnvOK', Format => 'int8s' },
87
+ 0x66 => { Name => 'FactStatusDistOK', Format => 'int8s' },
88
+ 0x67 => { Name => 'FactStatusTempMap', Format => 'int8s' },
89
+ # Missing: ndist_table_len, ndist_table, nuc_t_table_len, nuc_t_table
90
+ );
91
+
92
+ # InfiRay IJPEG picture temperature information, found in IJPEG's APP5 section
93
+ %Image::ExifTool::InfiRay::Picture = (
94
+ GROUPS => { 0 => 'APP5', 2 => 'Image' },
95
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
96
+ VARS => { NO_LOOKUP => 1 }, # omit tags from lookup
97
+ NOTES => q{
98
+ This table lists tags found in the InfiRay APP5 IJPEG picture temperature
99
+ information.
100
+ },
101
+ 0x00 => { Name => 'EnvironmentTemp', Format => 'float', %convCelsius },
102
+ 0x04 => { Name => 'Distance', Format => 'float', %convMeters },
103
+ 0x08 => { Name => 'Emissivity', Format => 'float', %convFloat2 },
104
+ 0x0c => { Name => 'Humidity', Format => 'float', %convPercent },
105
+ 0x10 => { Name => 'ReferenceTemp', Format => 'float', %convCelsius },
106
+ 0x20 => { Name => 'TempUnit', Format => 'int8u' },
107
+ 0x21 => { Name => 'ShowCenterTemp', Format => 'int8u' },
108
+ 0x22 => { Name => 'ShowMaxTemp', Format => 'int8u' },
109
+ 0x23 => { Name => 'ShowMinTemp', Format => 'int8u' },
110
+ 0x24 => { Name => 'TempMeasureCount', Format => 'int16u' },
111
+ # TODO: process extra measurements list
112
+ );
113
+
114
+ # InfiRay IJPEG visual-infrared mixing mode, found in IJPEG's APP6 section
115
+ %Image::ExifTool::InfiRay::MixMode = (
116
+ GROUPS => { 0 => 'APP6', 2 => 'Image' },
117
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
118
+ VARS => { NO_LOOKUP => 1 }, # omit tags from lookup
119
+ NOTES => q{
120
+ This table lists tags found in the InfiRay APP6 IJPEG visual-infrared mixing
121
+ mode section.
122
+ },
123
+ 0x00 => { Name => 'MixMode', Format => 'int8u' },
124
+ 0x01 => { Name => 'FusionIntensity', Format => 'float', %convPercent },
125
+ 0x05 => { Name => 'OffsetAdjustment', Format => 'float' },
126
+ 0x09 => { Name => 'CorrectionAsix', Format => 'float[30]' },
127
+ );
128
+
129
+ # InfiRay IJPEG camera operation mode, found in IJPEG's APP7 section
130
+ #
131
+ # I do not know in what units these times are, or what do they represent.
132
+ %Image::ExifTool::InfiRay::OpMode = (
133
+ GROUPS => { 0 => 'APP7', 2 => 'Image' },
134
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
135
+ VARS => { NO_LOOKUP => 1 }, # omit tags from lookup
136
+ NOTES => q{
137
+ This table lists tags found in the InfiRay APP7 IJPEG camera operation mode
138
+ section.
139
+ },
140
+ 0x00 => { Name => 'WorkingMode', Format => 'int8u' },
141
+ 0x01 => { Name => 'IntegralTime', Format => 'int32u' },
142
+ 0x05 => { Name => 'IntegratTimeHdr', Format => 'int32u' },
143
+ 0x09 => { Name => 'GainStable', Format => 'int8u' },
144
+ 0x0a => { Name => 'TempControlEnable', Format => 'int8u' },
145
+ 0x0b => { Name => 'DeviceTemp', Format => 'float', %convCelsius },
146
+ );
147
+
148
+ # InfiRay IJPEG isothermal information, found in IJPEG's APP8 section
149
+ #
150
+ # I have genuinely no clue what is the meaning of any of this information, or
151
+ # what is it used for.
152
+ %Image::ExifTool::InfiRay::Isothermal = (
153
+ GROUPS => { 0 => 'APP8', 2 => 'Image' },
154
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
155
+ VARS => { NO_LOOKUP => 1 }, # omit tags from lookup
156
+ NOTES => q{
157
+ This table lists tags found in the InfiRay APP8 IJPEG picture isothermal
158
+ information.
159
+ },
160
+ 0x00 => { Name => 'IsothermalMax', Format => 'float' },
161
+ 0x04 => { Name => 'IsothermalMin', Format => 'float' },
162
+ 0x08 => { Name => 'ChromaBarMax', Format => 'float' },
163
+ 0x0c => { Name => 'ChromaBarMin', Format => 'float' },
164
+ );
165
+
166
+ # InfiRay IJPEG sensor information, found in IJPEG's APP9 section
167
+ %Image::ExifTool::InfiRay::Sensor = (
168
+ GROUPS => { 0 => 'APP9', 2 => 'Image' },
169
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
170
+ VARS => { NO_LOOKUP => 1 }, # omit tags from lookup
171
+ NOTES => q{
172
+ This table lists tags found in the InfiRay APP9 IJPEG sensor information
173
+ chunk.
174
+ },
175
+ 0x000 => { Name => 'IRSensorManufacturer', Format => 'string[12]' },
176
+ 0x040 => { Name => 'IRSensorName', Format => 'string[12]' },
177
+ 0x080 => { Name => 'IRSensorPartNumber', Format => 'string[32]' },
178
+ 0x0c0 => { Name => 'IRSensorSerialNumber', Format => 'string[32]' },
179
+ 0x100 => { Name => 'IRSensorFirmware', Format => 'string[12]' },
180
+ 0x140 => { Name => 'IRSensorAperture', Format => 'float', %convFloat2 },
181
+ 0x144 => { Name => 'IRFocalLength', Format => 'float', %convFloat2 },
182
+ 0x180 => { Name => 'VisibleSensorManufacturer', Format => 'string[12]' },
183
+ 0x1c0 => { Name => 'VisibleSensorName', Format => 'string[12]' },
184
+ 0x200 => { Name => 'VisibleSensorPartNumber', Format => 'string[32]' },
185
+ 0x240 => { Name => 'VisibleSensorSerialNumber', Format => 'string[32]' },
186
+ 0x280 => { Name => 'VisibleSensorFirmware', Format => 'string[12]' },
187
+ 0x2c0 => { Name => 'VisibleSensorAperture', Format => 'float' },
188
+ 0x2c4 => { Name => 'VisibleFocalLength', Format => 'float' },
189
+ );
190
+
191
+ __END__
192
+
193
+ =head1 NAME
194
+
195
+ Image::ExifTool::InfiRay - InfiRay IJPEG thermal image metadata
196
+
197
+ =head1 SYNOPSIS
198
+
199
+ This module is loaded automatically by Image::ExifTool when required.
200
+
201
+ =head1 DESCRIPTION
202
+
203
+ This module contains definitions required by Image::ExifTool to interpret
204
+ metadata and thermal-related information of pictures saved by the InfiRay
205
+ IJPEG SDK, used in cameras such as the P2 Pro.
206
+
207
+ =head1 AUTHOR
208
+
209
+ Copyright 2003-2023, Marcos Del Sol Vives (marcos at orca.pet)
210
+
211
+ This library is free software; you can redistribute it and/or modify it
212
+ under the same terms as Perl itself.
213
+
214
+ =head1 REFERENCES
215
+
216
+ =over 4
217
+
218
+ =item L<https://github.com/exiftool/exiftool/pull/184>
219
+
220
+ =back
221
+
222
+ =head1 SEE ALSO
223
+
224
+ L<Image::ExifTool::TagNames/InfiRay Tags>,
225
+ L<Image::ExifTool(3pm)|Image::ExifTool>
226
+
227
+ =cut
@@ -11,7 +11,7 @@ use strict;
11
11
  use vars qw($VERSION);
12
12
  use Image::ExifTool qw(:DataAccess :Utils);
13
13
 
14
- $VERSION = '1.33';
14
+ $VERSION = '1.35';
15
15
 
16
16
  sub ProcessOcad($$$);
17
17
  sub ProcessJPEG_HDR($$$);
@@ -83,6 +83,10 @@ sub ProcessJPEG_HDR($$$);
83
83
  Name => 'MPF',
84
84
  Condition => '$$valPt =~ /^MPF\0/',
85
85
  SubDirectory => { TagTable => 'Image::ExifTool::MPF::Main' },
86
+ }, {
87
+ Name => 'InfiRayVersion',
88
+ Condition => '$$valPt =~ /^....IJPEG\0/s',
89
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Version' },
86
90
  }, {
87
91
  Name => 'PreviewImage',
88
92
  Condition => '$$valPt =~ /^(|QVGA\0|BGTH)\xff\xd8\xff\xdb/',
@@ -106,6 +110,12 @@ sub ProcessJPEG_HDR($$$);
106
110
  Notes => 'DJI raw thermal data',
107
111
  Groups => { 0 => 'APP3', 1 => 'DJI', 2 => 'Image' },
108
112
  Binary => 1,
113
+ }, {
114
+ Name => 'ImagingData', # (written by InfiRay models)
115
+ Condition => '$$self{HasIJPEG}',
116
+ Notes => 'InfiRay IR+thermal+visible data',
117
+ Groups => { 0 => 'APP3', 1 => 'InfiRay', 2 => 'Image' },
118
+ Binary => 1,
109
119
  }, {
110
120
  Name => 'PreviewImage', # (written by HP R837 and Samsung S1060)
111
121
  Condition => '$$valPt =~ /^\xff\xd8\xff\xdb/',
@@ -120,9 +130,21 @@ sub ProcessJPEG_HDR($$$);
120
130
  Condition => '$$valPt =~ /^FPXR\0/',
121
131
  SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::Main' },
122
132
  }, {
123
- Name => 'ThermalParams', # (written by DJI FLIR models)
133
+ Name => 'InfiRayFactory',
134
+ Condition => '$$self{HasIJPEG}"',
135
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Factory' },
136
+ }, {
137
+ Name => 'ThermalParams', # (written by some DJI FLIR models)
124
138
  Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^\xaa\x55\x12\x06/',
125
139
  SubDirectory => { TagTable => 'Image::ExifTool::DJI::ThermalParams' },
140
+ }, {
141
+ Name => 'ThermalParams2', # (written by M3T)
142
+ Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^(.{32})?.{32}\x2c\x01\x20\0/s',
143
+ SubDirectory => { TagTable => 'Image::ExifTool::DJI::ThermalParams2' },
144
+ }, {
145
+ Name => 'ThermalParams3', # (written by M30T)
146
+ Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^.{32}\xaa\x55\x38\0/s',
147
+ SubDirectory => { TagTable => 'Image::ExifTool::DJI::ThermalParams3' },
126
148
  }, {
127
149
  Name => 'PreviewImage', # (eg. Samsung S1060)
128
150
  Notes => 'continued from APP3',
@@ -135,6 +157,10 @@ sub ProcessJPEG_HDR($$$);
135
157
  Name => 'SamsungUniqueID',
136
158
  Condition => '$$valPt =~ /ssuniqueid\0/',
137
159
  SubDirectory => { TagTable => 'Image::ExifTool::Samsung::APP5' },
160
+ }, {
161
+ Name => 'InfiRayPicture',
162
+ Condition => '$$self{HasIJPEG}',
163
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Picture' },
138
164
  }, {
139
165
  Name => 'ThermalCalibration', # (written by DJI FLIR models)
140
166
  Condition => '$$self{Make} eq "DJI"',
@@ -161,13 +187,17 @@ sub ProcessJPEG_HDR($$$);
161
187
  Name => 'GoPro',
162
188
  Condition => '$$valPt =~ /^GoPro\0/',
163
189
  SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
164
- # also seen Motorola APP6 "MMIMETA\0", with sub-types: AL3A,ALED,MMI0,MOTD,QC3A
190
+ }, {
191
+ Name => 'InfiRayMixMode',
192
+ Condition => '$$self{HasIJPEG}',
193
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::MixMode' },
165
194
  }, {
166
195
  Name => 'DJI_DTAT', # (written by ZH20T)
167
196
  Condition => '$$valPt =~ /^DTAT\0\0.\{/s',
168
197
  Groups => { 0 => 'APP6', 1 => 'DJI' },
169
198
  Notes => 'DJI Thermal Analysis Tool record',
170
199
  ValueConv => 'substr($val,7)',
200
+ # also seen Motorola APP6 "MMIMETA\0", with sub-types: AL3A,ALED,MMI0,MOTD,QC3A
171
201
  }],
172
202
  APP7 => [{
173
203
  Name => 'Pentax',
@@ -181,17 +211,33 @@ sub ProcessJPEG_HDR($$$);
181
211
  Name => 'Qualcomm',
182
212
  Condition => '$$valPt =~ /^\x1aQualcomm Camera Attributes/',
183
213
  SubDirectory => { TagTable => 'Image::ExifTool::Qualcomm::Main' },
214
+ }, {
215
+ Name => 'InfiRayOpMode',
216
+ Condition => '$$self{HasIJPEG}',
217
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::OpMode' },
218
+ }, {
219
+ Name => 'DJI-DBG',
220
+ Condition => '$$valPt =~ /^DJI-DBG\0/',
221
+ SubDirectory => { TagTable => 'Image::ExifTool::DJI::Info' },
184
222
  }],
185
- APP8 => {
223
+ APP8 => [{
186
224
  Name => 'SPIFF',
187
225
  Condition => '$$valPt =~ /^SPIFF\0/',
188
226
  SubDirectory => { TagTable => 'Image::ExifTool::JPEG::SPIFF' },
189
- },
190
- APP9 => {
227
+ }, {
228
+ Name => 'InfiRayIsothermal',
229
+ Condition => '$$self{HasIJPEG}',
230
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Isothermal' },
231
+ }],
232
+ APP9 => [{
191
233
  Name => 'MediaJukebox',
192
234
  Condition => '$$valPt =~ /^Media Jukebox\0/',
193
235
  SubDirectory => { TagTable => 'Image::ExifTool::JPEG::MediaJukebox' },
194
- },
236
+ }, {
237
+ Name => 'InfiRaySensor',
238
+ Condition => '$$self{HasIJPEG}',
239
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Sensor' },
240
+ }],
195
241
  APP10 => {
196
242
  Name => 'Comment',
197
243
  Condition => '$$valPt =~ /^UNICODE\0/',
@@ -59,7 +59,7 @@ my %jp2Map = (
59
59
  # map of where information is written in a JXL image
60
60
  my %jxlMap = (
61
61
  IFD0 => 'Exif',
62
- XMP => 'XML',
62
+ XMP => 'xml ',
63
63
  'Exif' => 'JP2',
64
64
  IFD1 => 'IFD0',
65
65
  EXIF => 'IFD0', # to write EXIF as a block
@@ -827,8 +827,8 @@ sub CreateNewBoxes($$)
827
827
  # add UUID boxes (and/or JXL Exif/XML boxes)
828
828
  foreach $dirName (sort keys %$addDirs) {
829
829
  # handle JPEG XL XMP and EXIF
830
- if ($dirName eq 'XML' or $dirName eq 'Exif') {
831
- my ($tag, $dir) = $dirName eq 'XML' ? ('xml ', 'XMP') : ('Exif', 'EXIF');
830
+ if ($dirName eq 'xml ' or $dirName eq 'Exif') {
831
+ my ($tag, $dir) = $dirName eq 'xml ' ? ('xml ', 'XMP') : ('Exif', 'EXIF');
832
832
  my $tagInfo = $Image::ExifTool::Jpeg2000::Main{$tag};
833
833
  $tagInfo = $$tagInfo[1] if ref $tagInfo eq 'ARRAY'; # (hack for stupid JXL XMP)
834
834
  my $subdir = $$tagInfo{SubDirectory};
@@ -1123,8 +1123,8 @@ sub ProcessJpeg2000Box($$$)
1123
1123
  my $subTable = GetTagTable($$subdir{TagTable}) || $tagTablePtr;
1124
1124
  if ($outfile) {
1125
1125
  # remove this directory from our create list
1126
- delete $$et{AddJp2Dirs}{$$tagInfo{Name}}; # (eg. 'EXIF')
1127
- delete $$et{AddJp2Dirs}{$boxID}; # (eg. 'Exif')
1126
+ delete $$et{AddJp2Dirs}{$$tagInfo{Name}}; # (eg. 'EXIF' or 'XMP')
1127
+ delete $$et{AddJp2Dirs}{$boxID}; # (eg. 'Exif' or 'xml ')
1128
1128
  my $newdir;
1129
1129
  # only edit writable UUID, Exif and jp2h boxes
1130
1130
  if ($uuid or $boxID eq 'Exif' or ($boxID eq 'xml ' and $$et{IsJXL}) or
@@ -13,7 +13,7 @@ use vars qw($VERSION);
13
13
  use Image::ExifTool qw(:DataAccess :Utils);
14
14
  use Image::ExifTool::XMP;
15
15
 
16
- $VERSION = '1.00';
16
+ $VERSION = '1.01';
17
17
 
18
18
  %Image::ExifTool::LIF::Main = (
19
19
  GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Image' },
@@ -30,7 +30,15 @@ $VERSION = '1.00';
30
30
  my $unixTimeZero = 134774 * 24 * 3600;
31
31
  my @vals = split ' ', $val;
32
32
  foreach (@vals) {
33
- $_ = 1e-7 * hex($_);
33
+ if (/[^0-9a-f]/i) {
34
+ $_ = '0000:00:00 00:00:00';
35
+ } elsif (length $_ > 8) {
36
+ my $lo = hex substr($_, -8);
37
+ my $hi = hex substr($_, 0, -8);
38
+ $_ = 1e-7 * ($hi * 4294967296 + $lo);
39
+ } else {
40
+ $_ = 1e-7 * hex($_);
41
+ }
34
42
  # shift from Jan 1, 1601 to Jan 1, 1970
35
43
  $_ = Image::ExifTool::ConvertUnixTime($_ - $unixTimeZero);
36
44
  }
@@ -15,7 +15,7 @@ use strict;
15
15
  use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
 
18
- $VERSION = '1.08';
18
+ $VERSION = '1.09';
19
19
 
20
20
  sub ProcessItemID($$$);
21
21
  sub ProcessLinkInfo($$$);
@@ -507,7 +507,7 @@ sub ProcessLinkInfo($$$)
507
507
  if ($lif & 0x01) {
508
508
  # read Volume ID
509
509
  $off = Get32u($dataPt, 0x0c);
510
- if ($off + 0x20 <= $dataLen) {
510
+ if ($off and $off + 0x20 <= $dataLen) {
511
511
  # my $len = Get32u($dataPt, $off);
512
512
  $et->HandleTag($tagTablePtr, 'DriveType', undef, %opts, Start=>$off+4);
513
513
  $et->HandleTag($tagTablePtr, 'DriveSerialNumber', undef, %opts, Start=>$off+8);
@@ -545,6 +545,7 @@ sub ProcessLinkInfo($$$)
545
545
  $off = Get32u($dataPt, 0x14);
546
546
  if ($off and $off + 0x14 <= $dataLen) {
547
547
  my $siz = Get32u($dataPt, $off);
548
+ return 0 if $off + $siz > $dataLen;
548
549
  $pos = Get32u($dataPt, $off + 0x08);
549
550
  if ($pos > 0x14 and $siz >= 0x18) {
550
551
  $pos = Get32u($dataPt, $off + 0x14);
@@ -552,7 +553,7 @@ sub ProcessLinkInfo($$$)
552
553
  } else {
553
554
  undef $unicode;
554
555
  }
555
- $val = GetString($dataPt, $pos, $unicode);
556
+ $val = GetString($dataPt, $off + $pos, $unicode);
556
557
  if (defined $val) {
557
558
  $size = length $val;
558
559
  $val = $et->Decode($val, 'UCS2') if $unicode;
@@ -567,7 +568,7 @@ sub ProcessLinkInfo($$$)
567
568
  } else {
568
569
  undef $unicode;
569
570
  }
570
- $val = GetString($dataPt, $pos, $unicode);
571
+ $val = GetString($dataPt, $off + $pos, $unicode);
571
572
  if (defined $val) {
572
573
  $size = length $val;
573
574
  $val = $et->Decode($val, 'UCS2') if $unicode;
@@ -14,7 +14,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
14
14
  use Image::ExifTool::Exif;
15
15
  use Image::ExifTool::GPS;
16
16
 
17
- $VERSION = '1.50';
17
+ $VERSION = '1.51';
18
18
 
19
19
  sub ProcessMIE($$);
20
20
  sub ProcessMIEGroup($$$);
@@ -391,7 +391,7 @@ my %offOn = ( 0 => 'Off', 1 => 'On' );
391
391
  -30", "-40.5", "40 30 0.00 S"
392
392
  },
393
393
  ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)',
394
- ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 0)',
394
+ ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 3)',
395
395
  PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
396
396
  PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1, "lat")',
397
397
  },
@@ -404,7 +404,7 @@ my %offOn = ( 0 => 'Off', 1 => 'On' );
404
404
  negative, but may be entered as positive numbers with a trailing 'W'
405
405
  },
406
406
  ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)',
407
- ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 0)',
407
+ ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 3)',
408
408
  PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
409
409
  PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1, "lon")',
410
410
  },
@@ -18,7 +18,7 @@ use strict;
18
18
  use vars qw($VERSION);
19
19
  use Image::ExifTool qw(:DataAccess :Utils);
20
20
 
21
- $VERSION = '1.16';
21
+ $VERSION = '1.17';
22
22
 
23
23
  %Image::ExifTool::MPEG::Audio = (
24
24
  GROUPS => { 2 => 'Audio' },
@@ -599,7 +599,7 @@ sub ProcessMPEGVideo($$)
599
599
  return 0;
600
600
  }
601
601
  # set file type if not done already
602
- $et->SetFileType('MPEG') unless $$et{VALUE}{FileType};
602
+ $et->SetFileType('MPEG') unless $$et{FileType};
603
603
 
604
604
  my $tagTablePtr = GetTagTable('Image::ExifTool::MPEG::Video');
605
605
  ProcessFrameHeader($et, $tagTablePtr, $w1, $w2);
@@ -21,7 +21,7 @@ sub ProcessKodakPatch($$$);
21
21
  sub WriteUnknownOrPreview($$$);
22
22
  sub FixLeicaBase($$;$);
23
23
 
24
- $VERSION = '2.12';
24
+ $VERSION = '2.14';
25
25
 
26
26
  my $debug; # set to 1 to enable debugging code
27
27
 
@@ -92,11 +92,12 @@ my $debug; # set to 1 to enable debugging code
92
92
  {
93
93
  Name => 'MakerNoteDJIInfo',
94
94
  Condition => '$$valPt =~ /^\[ae_dbg_info:/',
95
+ NotIFD => 1,
95
96
  SubDirectory => { TagTable => 'Image::ExifTool::DJI::Info' },
96
97
  },
97
98
  {
98
99
  Name => 'MakerNoteDJI',
99
- Condition => '$$self{Make} eq "DJI" and $$valPt !~ /^...\@AMBA/s',
100
+ Condition => '$$self{Make} eq "DJI" and $$valPt !~ /^(...\@AMBA|DJI)/s',
100
101
  SubDirectory => {
101
102
  TagTable => 'Image::ExifTool::DJI::Main',
102
103
  Start => '$valuePtr',