exiftool_vendored 12.54.0 → 12.56.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.69';
32
+ $VERSION = '1.70';
33
33
 
34
34
  sub JITTER() { return 2 } # maximum time jitter
35
35
 
@@ -210,7 +210,7 @@ sub LoadTrackLog($$;$)
210
210
  my $fix = { };
211
211
  my $csvDelim = $et->Options('CSVDelim');
212
212
  $csvDelim = ',' unless defined $csvDelim;
213
- my (@saveFix, $timeSpan);
213
+ my (@saveFix, @saveTime, $timeSpan);
214
214
  for (;;) {
215
215
  $raf->ReadLine($_) or last;
216
216
  # determine file format
@@ -357,8 +357,13 @@ sub LoadTrackLog($$;$)
357
357
  }
358
358
  # read KML "Point" coordinates
359
359
  @$fix{'lon','lat','alt'} = split ',', $1;
360
+ $$has{alt} = 1 if $$fix{alt};
360
361
  } else {
361
- $$fix{$tag} = $1;
362
+ if ($tok eq 'when' and $$fix{'time'}) {
363
+ push @saveTime, $1; # flightaware KML stores times in array
364
+ } else {
365
+ $$fix{$tag} = $1;
366
+ }
362
367
  if ($isOrient{$tag}) {
363
368
  $$has{orient} = 1;
364
369
  } elsif ($tag eq 'alt') {
@@ -375,7 +380,11 @@ sub LoadTrackLog($$;$)
375
380
  $td = 1;
376
381
  }
377
382
  # validate and store GPS fix
378
- next unless defined $$fix{lat} and defined $$fix{lon} and $$fix{'time'};
383
+ next unless defined $$fix{lat} and defined $$fix{lon};
384
+ unless (defined $$fix{'time'}) {
385
+ next unless @saveTime;
386
+ $$fix{'time'} = shift @saveTime; # get next time in flightaware KML list
387
+ }
379
388
  unless ($$fix{lat} =~ /^[+-]?\d+\.?\d*/ and $$fix{lon} =~ /^[+-]?\d+\.?\d*/) {
380
389
  $e0 or $et->VPrint(0, "Coordinate format error in $from\n"), $e0 = 1;
381
390
  next;
@@ -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.34';
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/',
@@ -119,6 +129,10 @@ sub ProcessJPEG_HDR($$$);
119
129
  Name => 'FPXR', # (non-standard location written by some HP models)
120
130
  Condition => '$$valPt =~ /^FPXR\0/',
121
131
  SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::Main' },
132
+ }, {
133
+ Name => 'InfiRayFactory',
134
+ Condition => '$$self{HasIJPEG}"',
135
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Factory' },
122
136
  }, {
123
137
  Name => 'ThermalParams', # (written by DJI FLIR models)
124
138
  Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^\xaa\x55\x12\x06/',
@@ -135,6 +149,10 @@ sub ProcessJPEG_HDR($$$);
135
149
  Name => 'SamsungUniqueID',
136
150
  Condition => '$$valPt =~ /ssuniqueid\0/',
137
151
  SubDirectory => { TagTable => 'Image::ExifTool::Samsung::APP5' },
152
+ }, {
153
+ Name => 'InfiRayPicture',
154
+ Condition => '$$self{HasIJPEG}',
155
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Picture' },
138
156
  }, {
139
157
  Name => 'ThermalCalibration', # (written by DJI FLIR models)
140
158
  Condition => '$$self{Make} eq "DJI"',
@@ -161,13 +179,17 @@ sub ProcessJPEG_HDR($$$);
161
179
  Name => 'GoPro',
162
180
  Condition => '$$valPt =~ /^GoPro\0/',
163
181
  SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
164
- # also seen Motorola APP6 "MMIMETA\0", with sub-types: AL3A,ALED,MMI0,MOTD,QC3A
182
+ }, {
183
+ Name => 'InfiRayMixMode',
184
+ Condition => '$$self{HasIJPEG}',
185
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::MixMode' },
165
186
  }, {
166
187
  Name => 'DJI_DTAT', # (written by ZH20T)
167
188
  Condition => '$$valPt =~ /^DTAT\0\0.\{/s',
168
189
  Groups => { 0 => 'APP6', 1 => 'DJI' },
169
190
  Notes => 'DJI Thermal Analysis Tool record',
170
191
  ValueConv => 'substr($val,7)',
192
+ # also seen Motorola APP6 "MMIMETA\0", with sub-types: AL3A,ALED,MMI0,MOTD,QC3A
171
193
  }],
172
194
  APP7 => [{
173
195
  Name => 'Pentax',
@@ -181,17 +203,29 @@ sub ProcessJPEG_HDR($$$);
181
203
  Name => 'Qualcomm',
182
204
  Condition => '$$valPt =~ /^\x1aQualcomm Camera Attributes/',
183
205
  SubDirectory => { TagTable => 'Image::ExifTool::Qualcomm::Main' },
206
+ }, {
207
+ Name => 'InfiRayOpMode',
208
+ Condition => '$$self{HasIJPEG}',
209
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::OpMode' },
184
210
  }],
185
- APP8 => {
211
+ APP8 => [{
186
212
  Name => 'SPIFF',
187
213
  Condition => '$$valPt =~ /^SPIFF\0/',
188
214
  SubDirectory => { TagTable => 'Image::ExifTool::JPEG::SPIFF' },
189
- },
190
- APP9 => {
215
+ }, {
216
+ Name => 'InfiRayIsothermal',
217
+ Condition => '$$self{HasIJPEG}',
218
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Isothermal' },
219
+ }],
220
+ APP9 => [{
191
221
  Name => 'MediaJukebox',
192
222
  Condition => '$$valPt =~ /^Media Jukebox\0/',
193
223
  SubDirectory => { TagTable => 'Image::ExifTool::JPEG::MediaJukebox' },
194
- },
224
+ }, {
225
+ Name => 'InfiRaySensor',
226
+ Condition => '$$self{HasIJPEG}',
227
+ SubDirectory => { TagTable => 'Image::ExifTool::InfiRay::Sensor' },
228
+ }],
195
229
  APP10 => {
196
230
  Name => 'Comment',
197
231
  Condition => '$$valPt =~ /^UNICODE\0/',
@@ -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.13';
18
+ $VERSION = '1.14';
19
19
 
20
20
  sub HandleStruct($$;$$$$);
21
21
 
@@ -708,11 +708,11 @@ my %uidInfo = (
708
708
  );
709
709
 
710
710
  # standardized tag names (ref 2)
711
- %Image::ExifTool::Matroska::Tags = (
711
+ %Image::ExifTool::Matroska::StdTag = (
712
712
  GROUPS => { 2 => 'Video' },
713
713
  VARS => { LONG_TAGS => 1 },
714
714
  NOTES => q{
715
- Standardized Matroska tags (see
715
+ Standardized Matroska tags, stored in a SimpleTag structure (see
716
716
  L<https://www.matroska.org/technical/tagging.html>).
717
717
  },
718
718
  ORIGINAL => 'Original', # struct
@@ -826,7 +826,7 @@ sub HandleStruct($$;$$$$)
826
826
  {
827
827
  local $_;
828
828
  my ($et, $struct, $pid, $pname, $lang, $ctry) = @_;
829
- my $tagTbl = GetTagTable('Image::ExifTool::Matroska::Tags');
829
+ my $tagTbl = GetTagTable('Image::ExifTool::Matroska::StdTag');
830
830
  my $tag = $$struct{TagName};
831
831
  my $tagInfo = $$tagTbl{$tag};
832
832
  # create tag if necessary