exiftool_vendored 12.55.0 → 12.57.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +38 -1
  3. data/bin/MANIFEST +5 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +19 -19
  7. data/bin/arg_files/xmp2exif.args +4 -1
  8. data/bin/exiftool +97 -53
  9. data/bin/fmt_files/kml.fmt +3 -0
  10. data/bin/fmt_files/kml_track.fmt +3 -0
  11. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +13 -6
  12. data/bin/lib/Image/ExifTool/Canon.pm +8 -2
  13. data/bin/lib/Image/ExifTool/Exif.pm +31 -2
  14. data/bin/lib/Image/ExifTool/FlashPix.pm +73 -8
  15. data/bin/lib/Image/ExifTool/FujiFilm.pm +2 -1
  16. data/bin/lib/Image/ExifTool/GPS.pm +7 -2
  17. data/bin/lib/Image/ExifTool/InfiRay.pm +227 -0
  18. data/bin/lib/Image/ExifTool/JPEG.pm +40 -6
  19. data/bin/lib/Image/ExifTool/Jpeg2000.pm +5 -5
  20. data/bin/lib/Image/ExifTool/MIE.pm +3 -3
  21. data/bin/lib/Image/ExifTool/Nikon.pm +862 -1264
  22. data/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  23. data/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  24. data/bin/lib/Image/ExifTool/Olympus.pm +3 -1
  25. data/bin/lib/Image/ExifTool/OpenEXR.pm +32 -15
  26. data/bin/lib/Image/ExifTool/PNG.pm +80 -2
  27. data/bin/lib/Image/ExifTool/Photoshop.pm +36 -5
  28. data/bin/lib/Image/ExifTool/QuickTime.pm +18 -2
  29. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +25 -14
  30. data/bin/lib/Image/ExifTool/README +11 -2
  31. data/bin/lib/Image/ExifTool/Real.pm +2 -2
  32. data/bin/lib/Image/ExifTool/Sigma.pm +2 -1
  33. data/bin/lib/Image/ExifTool/Sony.pm +5 -1
  34. data/bin/lib/Image/ExifTool/TagLookup.pm +4667 -4624
  35. data/bin/lib/Image/ExifTool/TagNames.pod +400 -90
  36. data/bin/lib/Image/ExifTool/VCard.pm +19 -5
  37. data/bin/lib/Image/ExifTool/Writer.pl +36 -16
  38. data/bin/lib/Image/ExifTool.pm +92 -35
  39. data/bin/lib/Image/ExifTool.pod +54 -53
  40. data/bin/perl-Image-ExifTool.spec +18 -18
  41. data/lib/exiftool_vendored/version.rb +1 -1
  42. metadata +3 -2
@@ -88,7 +88,7 @@ sub ProcessCTMD($$$);
88
88
  sub ProcessExifInfo($$$);
89
89
  sub SwapWords($);
90
90
 
91
- $VERSION = '4.64';
91
+ $VERSION = '4.65';
92
92
 
93
93
  # Note: Removed 'USM' from 'L' lenses since it is redundant - PH
94
94
  # (or is it? Ref 32 shows 5 non-USM L-type lenses)
@@ -621,8 +621,10 @@ $VERSION = '4.64';
621
621
  '61182.41' => 'Canon RF 1200mm F8L IS USM + RF1.4x', #42
622
622
  '61182.42' => 'Canon RF 1200mm F8L IS USM + RF2x', #42
623
623
  '61182.43' => 'Canon RF 135mm F1.8 L IS USM', #42
624
+ '61182.44' => 'Canon RF 24-50mm F4.5-6.3 IS STM', #42
625
+ '61182.45' => 'Canon RF-S 55-210mm F5-7.1 IS STM', #42
624
626
  # we need the RFLensType values for the following...
625
- '61182.44' => 'Canon RF 5.2mm F2.8L Dual Fisheye 3D VR', #PH (NC)
627
+ '61182.46' => 'Canon RF 5.2mm F2.8L Dual Fisheye 3D VR', #PH (NC)
626
628
  65535 => 'n/a',
627
629
  );
628
630
 
@@ -983,7 +985,9 @@ $VERSION = '4.64';
983
985
  0x80000465 => 'EOS R10', #42
984
986
  0x80000467 => 'PowerShot ZOOM',
985
987
  0x80000468 => 'EOS M50 Mark II / Kiss M2', #IB
988
+ 0x80000480 => 'EOS R50', #42
986
989
  0x80000481 => 'EOS R6 Mark II', #42
990
+ 0x80000487 => 'EOS R8', #42
987
991
  0x80000520 => 'EOS D2000C', #IB
988
992
  0x80000560 => 'EOS D6000C', #PH (guess)
989
993
  );
@@ -6840,6 +6844,8 @@ my %ciMaxFocal = (
6840
6844
  300 => 'Canon RF 1200mm F8L IS USM + RF2x', #42
6841
6845
  302 => 'Canon RF 15-30mm F4.5-6.3 IS STM', #42
6842
6846
  303 => 'Canon RF 135mm F1.8 L IS USM', #42
6847
+ 304 => 'Canon RF 24-50mm F4.5-6.3 IS STM', #42
6848
+ 305 => 'Canon RF-S 55-210mm F5-7.1 IS STM', #42
6843
6849
  # Note: add new RF lenses to %canonLensTypes with ID 61182
6844
6850
  },
6845
6851
  },
@@ -56,7 +56,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
56
56
  use Image::ExifTool qw(:DataAccess :Utils);
57
57
  use Image::ExifTool::MakerNotes;
58
58
 
59
- $VERSION = '4.42';
59
+ $VERSION = '4.43';
60
60
 
61
61
  sub ProcessExif($$$);
62
62
  sub WriteExif($$$);
@@ -578,6 +578,13 @@ my %opcodeInfo = (
578
578
  ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
579
579
  ByteOrder => 'LittleEndian',
580
580
  },
581
+ {
582
+ Condition => '$$self{Compression} and $$self{Compression} eq "34892"', # DNG Lossy JPEG
583
+ Name => 'OtherImageStart',
584
+ IsOffset => 1,
585
+ OffsetPair => 0x117, # point to associated byte counts
586
+ DataTag => 'OtherImage',
587
+ },
581
588
  {
582
589
  # (APP1 IFD2 is for Leica JPEG preview)
583
590
  Condition => q[
@@ -664,6 +671,12 @@ my %opcodeInfo = (
664
671
  ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
665
672
  ByteOrder => 'LittleEndian',
666
673
  },
674
+ {
675
+ Condition => '$$self{Compression} and $$self{Compression} eq "34892"', # DNG Lossy JPEG
676
+ Name => 'OtherImageLength',
677
+ OffsetPair => 0x111, # point to associated offset
678
+ DataTag => 'OtherImage',
679
+ },
667
680
  {
668
681
  # (APP1 IFD2 is for Leica JPEG preview)
669
682
  Condition => q[
@@ -4706,12 +4719,28 @@ my %subSecConv = (
4706
4719
  0 => 'OtherImageStart',
4707
4720
  1 => 'OtherImageLength',
4708
4721
  },
4722
+ Desire => {
4723
+ 2 => 'OtherImageStart (1)',
4724
+ 3 => 'OtherImageLength (1)',
4725
+ },
4709
4726
  Notes => q{
4710
4727
  this tag is writable, and may be used to update existing embedded images,
4711
4728
  but not create or delete them
4712
4729
  },
4713
- # retrieve the thumbnail from our EXIF data
4730
+ # retrieve all other images
4714
4731
  RawConv => q{
4732
+ if ($val[2] and $val[3]) {
4733
+ my $i = 1;
4734
+ for (;;) {
4735
+ my %val = ( 0 => $$val{2}, 1 => $$val{3} );
4736
+ $self->FoundTag($tagInfo, \%val);
4737
+ ++$i;
4738
+ $$val{2} = "$$val{0} ($i)";
4739
+ last unless defined $$self{VALUE}{$$val{2}};
4740
+ $$val{3} = "$$val{1} ($i)";
4741
+ last unless defined $$self{VALUE}{$$val{3}};
4742
+ }
4743
+ }
4715
4744
  @grps = $self->GetGroup($$val{0});
4716
4745
  Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"OtherImage");
4717
4746
  },
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
21
21
  use Image::ExifTool::Exif;
22
22
  use Image::ExifTool::ASF; # for GetGUID()
23
23
 
24
- $VERSION = '1.41';
24
+ $VERSION = '1.42';
25
25
 
26
26
  sub ProcessFPX($$);
27
27
  sub ProcessFPXR($$$);
@@ -318,6 +318,10 @@ my %fpxFileType = (
318
318
  unrecognized Windows Compound Binary file as a FlashPix (FPX) file. See
319
319
  L<http://graphcomp.com/info/specs/livepicture/fpx.pdf> for the FlashPix
320
320
  specification.
321
+
322
+ Note that Microsoft is not consistent with the time zone used for some
323
+ date/time tags, and it may be either UTC or local time depending on the
324
+ software used to create the file.
321
325
  },
322
326
  "\x05SummaryInformation" => {
323
327
  Name => 'SummaryInfo',
@@ -483,10 +487,18 @@ my %fpxFileType = (
483
487
  },
484
488
  IeImg => {
485
489
  Name => 'EmbeddedImage',
486
- Notes => 'embedded images in Scene7 vignette VNT files',
490
+ Notes => q{
491
+ embedded images in Scene7 vignette VNT files. EmbeddedImageRectangle is
492
+ generated for applicable images, and may be associated with the
493
+ corresponding EmbeddedImage via the family 3 group name
494
+ },
487
495
  Groups => { 2 => 'Preview' },
488
496
  Binary => 1,
489
497
  },
498
+ IeImg_rect => { # (not a real tag -- extracted from Contents of VNT file)
499
+ Name => 'EmbeddedImageRectangle',
500
+ Hidden => 1,
501
+ },
490
502
  );
491
503
 
492
504
  # Summary Information properties
@@ -1059,6 +1071,7 @@ my %fpxFileType = (
1059
1071
  %Image::ExifTool::FlashPix::Contents = (
1060
1072
  PROCESS_PROC => \&ProcessProperties,
1061
1073
  GROUPS => { 2 => 'Image' },
1074
+ OriginalFileName => { Name => 'OriginalFileName', Hidden => 1 }, # (not a real tag -- extracted from Contents of VNT file)
1062
1075
  );
1063
1076
 
1064
1077
  # CompObj tags
@@ -1537,11 +1550,43 @@ sub ProcessContents($$$)
1537
1550
  my $isFLA;
1538
1551
 
1539
1552
  # all of my FLA samples contain "Contents" data, and no other FPX-like samples have
1540
- # this, but check the data for a familiar pattern to be sure this is FLA: the
1541
- # Contents of all of my FLA samples start with two bytes (0x29,0x38,0x3f,0x43 or 0x47,
1542
- # then 0x01) followed by a number of zero bytes (from 0x18 to 0x26 of them, related
1543
- # somehow to the value of the first byte), followed by the string "DocumentPage"
1544
- $isFLA = 1 if $$dataPt =~ /^..\0+\xff\xff\x01\0\x0d\0CDocumentPage/s;
1553
+ # this (except Scene7 VNT viles), but check the data for a familiar pattern to be
1554
+ # sure this is FLA: the Contents of all of my FLA samples start with two bytes
1555
+ # (0x29,0x38,0x3f,0x43 or 0x47, then 0x01) followed by a number of zero bytes
1556
+ # (from 0x18 to 0x26 of them, related somehow to the value of the first byte),
1557
+ # followed by the string "DocumentPage"
1558
+ if ($$dataPt =~ /^..\0+\xff\xff\x01\0\x0d\0CDocumentPage/s) {
1559
+ $isFLA = 1;
1560
+ } elsif ($$dataPt =~ /^\0{4}.(.{1,255})\x60\xa1\x3f\x22\0{5}(.{8})/sg) {
1561
+ # this looks like a VNT file
1562
+ $et->OverrideFileType('VNT', 'image/x-vignette');
1563
+ # hack to set proper file description (extension is the same for V-Note files)
1564
+ $Image::ExifTool::static_vars{OverrideFileDescription}{VNT} = 'Scene7 Vignette',
1565
+ my $name = $1;
1566
+ my ($w, $h) = unpack('V2',$2);
1567
+ $et->FoundTag(ImageWidth => $w);
1568
+ $et->FoundTag(ImageHeight => $h);
1569
+ $et->HandleTag($tagTablePtr, OriginalFileName => $name);
1570
+ if ($$dataPt =~ /\G\x01\0{4}(.{12})/sg) {
1571
+ # (first 4 bytes seem to be number of objects, next 4 bytes are zero, then ICC size)
1572
+ my $size = unpack('x8V', $1);
1573
+ # (not useful?) $et->FoundTag(NumObjects => $num);
1574
+ if ($size and pos($$dataPt) + $size < length($$dataPt)) {
1575
+ my $dat = substr($$dataPt, pos($$dataPt), $size);
1576
+ $et->FoundTag(ICC_Profile => $dat);
1577
+ pos($$dataPt) += $size;
1578
+ }
1579
+ $$et{IeImg_lkup} = { };
1580
+ # - the byte after TargetRole1 is 0x0d or 0x11 for separate images in my samples,
1581
+ # and 0x1c or 0x23 for inline masks
1582
+ while ($$dataPt =~ /\x0bTargetRole1.\x80\0\0\x01.{4}(.{24})/sg) {
1583
+ my ($index, @coords) = unpack('Vx4V4', $1);
1584
+ next if $index == 0xffffffff;
1585
+ $$et{IeImg_lkup}{$index} and $et->WarnOnce('Duplicate image index');
1586
+ $$et{IeImg_lkup}{$index} = "@coords";
1587
+ }
1588
+ }
1589
+ }
1545
1590
 
1546
1591
  # do a brute-force scan of the "Contents" for UTF-16 XMP
1547
1592
  # (this may always be little-endian, but allow for either endianness)
@@ -2337,8 +2382,24 @@ sub ProcessFPX($$)
2337
2382
  );
2338
2383
  my $subTablePtr = GetTagTable($$subdir{TagTable});
2339
2384
  $et->ProcessDirectory(\%dirInfo, $subTablePtr, $$subdir{ProcessProc});
2385
+ } elsif (defined $size and $size > length($buff)) {
2386
+ $et->WarnOnce('Truncated object');
2340
2387
  } else {
2341
- $et->FoundTag($tagInfo, $buff);
2388
+ $buff = substr($buff, 0, $size) if defined $size and $size < length($buff);
2389
+ if ($tag =~ /^IeImg_0*(\d+)$/) {
2390
+ # set document number for embedded images and their positions (if available, VNT files)
2391
+ my $num = $1;
2392
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT};
2393
+ $et->FoundTag($tagInfo, $buff);
2394
+ if ($$et{IeImg_lkup} and $$et{IeImg_lkup}{$num}) {
2395
+ # save position of this image
2396
+ $et->HandleTag($tagTablePtr, IeImg_rect => $$et{IeImg_lkup}{$num});
2397
+ delete $$et{IeImg_lkup}{$num};
2398
+ }
2399
+ delete $$et{DOC_NUM};
2400
+ } else {
2401
+ $et->FoundTag($tagInfo, $buff);
2402
+ }
2342
2403
  }
2343
2404
  # save object index number for all found tags
2344
2405
  my $num2 = $$et{NUM_FOUND};
@@ -2395,6 +2456,10 @@ sub ProcessFPX($$)
2395
2456
  # process Word document table
2396
2457
  ProcessDocumentTable($et);
2397
2458
 
2459
+ if ($$et{IeImg_lkup} and %{$$et{IeImg_lkup}}) {
2460
+ $et->Warn('Image positions exist without corresponding images');
2461
+ }
2462
+
2398
2463
  return 1;
2399
2464
  }
2400
2465
 
@@ -31,7 +31,7 @@ use vars qw($VERSION);
31
31
  use Image::ExifTool qw(:DataAccess :Utils);
32
32
  use Image::ExifTool::Exif;
33
33
 
34
- $VERSION = '1.86';
34
+ $VERSION = '1.87';
35
35
 
36
36
  sub ProcessFujiDir($$$);
37
37
  sub ProcessFaceRec($$$);
@@ -808,6 +808,7 @@ my %faceCategories = (
808
808
  0x00 => 'Normal',
809
809
  0x10 => 'F-log',
810
810
  0x20 => 'HLG',
811
+ 0x30 => 'F-log2', #forum14384
811
812
  },
812
813
  },
813
814
  0x3804 => { #forum10037
@@ -482,13 +482,13 @@ sub PrintTimeStamp($)
482
482
  #------------------------------------------------------------------------------
483
483
  # Convert degrees to DMS, or whatever the current settings are
484
484
  # Inputs: 0) ExifTool reference, 1) Value in degrees,
485
- # 2) format code (0=no format, 1=CoordFormat, 2=XMP format)
485
+ # 2) format code (0=no format, 1=CoordFormat, 2=XMP format, 3=signed unformatted)
486
486
  # 3) 'N' or 'E' if sign is significant and N/S/E/W should be added
487
487
  # Returns: DMS string
488
488
  sub ToDMS($$;$$)
489
489
  {
490
490
  my ($et, $val, $doPrintConv, $ref) = @_;
491
- my ($fmt, @fmt, $num, $sign, $rtnVal);
491
+ my ($fmt, @fmt, $num, $sign, $rtnVal, $neg);
492
492
 
493
493
  unless (length $val) {
494
494
  # don't convert an empty value
@@ -505,6 +505,10 @@ sub ToDMS($$;$$)
505
505
  }
506
506
  $ref = " $ref" unless $doPrintConv and $doPrintConv eq '2';
507
507
  } else {
508
+ if ($doPrintConv and $doPrintConv eq '3') {
509
+ $neg = 1 if $val < 0;
510
+ $doPrintConv = 0;
511
+ }
508
512
  $val = abs($val);
509
513
  $ref = '';
510
514
  }
@@ -554,6 +558,7 @@ sub ToDMS($$;$$)
554
558
  # trim trailing zeros in XMP
555
559
  $rtnVal =~ s/(\d)0+$ref$/$1$ref/ if $doPrintConv eq '2';
556
560
  } else {
561
+ $neg and map { $_ *= -1 } @c;
557
562
  $rtnVal = "@c$ref";
558
563
  }
559
564
  return $rtnVal;
@@ -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/',
@@ -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