some new Tags in Flir Images

Started by tomas123, January 11, 2014, 05:18:26 PM

Previous topic - Next topic

tomas123

Hallo Phil,

there are some activities around Flir Cameras in eevblog.com
http://www.eevblog.com/forum/testgear/flir-e4-thermal-imaging-camera-teardown/

Daves is writing a Windows Binary around Exiftool to decode some Flir Images.
see screenshot http://www.eevblog.com/forum/testgear/flir-e4-thermal-imaging-camera-teardown/msg364059/#msg364059

He ask me, how to decode the Flir tag 0x21 (describe the position of measuring markers).
Here is my provisional result:

The current place holder in flir.pm
    # 0x21 - ToolInfo (spot tool, line tool, area tool) (Measure - ref 3)


I looked inside the tag 0x21 and can decode the structure, but my exiftool knowledge is not enough to write the (tricky) code with splitting the variable block size.

as attachment a sample from the new Flir E4 (out of cam and after processing with Flir Tools)

here is a formatted output, to mark the different block size of variable count measuring point
the measuring point are added with flir tools

Quote$ exiftool -config  config.txt -v4 FLIR0232-Tools.jpg | grep -A55 "FLIR Record 0x21"
Unknown format ustring at /usr/bin/lib/Image/ExifTool.pm line 3958, <EXIFTOOL_FILE> chunk 5.
  | FLIR Record 0x21, offset 0xea18, length 0x01e4
  | MEAS (SubDirectory) -->
  | - Tag 0x0021 (484 bytes):
  |     ea18: 01 00 0c 00 24 00 00 00 00 00 00 00
                                                  48 00 00 01 [....$.......H...]  //size of first segment: 0x48
  |     ea28: 04 00 08 00 30 00 01 00 01 00 00 00 00 00 02 00 [....0...........] // 4 Byte coordinates (=2 values)
  |     ea38: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  |     ea48: 98 00 6f 00 53 00 70 00 31 00 00 00 01 00 00 00 [..o.S.p.1.......] //green: 4 Byte x/y coordinates / blue: name string
  |     ea58: 00 02 00 00 01 00 01 00 00 ff ff 00 00 00 00 00 [................]
  |     ea68: ff ff e1 00
                          54 00 00 01 08 00 08 00 34 00 04 00 [....T.......4...] //size of second segment:: 0x54  Byte, 8/2=4 coodinates values
  |     ea78: 01 00 00 00 00 00 d4 00 00 00 00 00 00 00 00 00 [................]
  |     ea88: 00 00 00 00 00 00 00 00 b5 00 9d 00 23 01 95 00 [............#...] // 8 Byte=4 values
  |     ea98: 4c 00 69 00 31 00 00 00 01 00 00 00 00 02 00 00 [L.i.1...........] // string: line 1
  |     eaa8: 01 00 01 00 00 ff ff 00 00 00 00 00 ff ff e1 00 [................]
  |     eab8: 00 00 00 00 00 00 00 00
                                      54 00 00 01 08 00 08 00 [........T.......] //size of third segment: 0x54
  |     eac8: 34 00 02 00 01 00 00 00 00 00 d4 00 00 00 00 00 [4...............]
  |     ead8: 00 00 00 00 00 00 00 00 00 00 00 00 d3 00 05 00 [................]
  |     eae8: 28 00 1b 00 41 00 72 00 31 00 00 00 01 00 00 00 [(...A.r.1.......] // Area 1
  |     eaf8: 00 02 00 00 01 00 01 00 00 ff ff 00 00 00 00 00 [................]
  |     eb08: ff ff e1 00 00 00 00 00 00 00 00 00
                                                  64 00 00 01 [............d...]
  |     eb18: 0c 00 08 00 38 00 03 00 01 00 00 00 00 00 d4 00 [....8...........] // 12 Byte = 6 coord. values
  |     eb28: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  |     eb38: 69 00 b1 00 97 00 b1 00 69 00 99 00 45 00 6c 00 [i.......i...E.l.] // Ellipse 1
  |     eb48: 31 00 00 00 01 00 18 00 00 02 00 00 01 00 01 00 [1...............]
  |     eb58: 00 ff ff 00 00 00 00 00 ff ff e1 00 05 00 0c 00 [................]
  |     eb68: 3c 00 99 00 5c 00 32 00 00 00 00 00 00 00 00 00 [<...\.2.........]

  |     eb78: 5c 00 00 01 0c 00 08 00 38 00 08 00 01 00 00 00 [\.......8.......]
  |     eb88: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  |     eb98: 00 00 00 00 02 00 01 00 02 00 03 00 01 00 02 00 [................]
  |     eba8: 44 00 74 00 31 00 00 00 01 00 18 00 00 02 00 00 [D.t.1...........] // Difference Temp 1
  |     ebb8: 01 00 01 00 00 ff ff 00 00 00 00 00 ff ff e1 00 [................]
  |     ebc8: 03 00 00 00 00 01 00 00 00 00 00 00 00
                                                     00 00 01 [................]
  |     ebd8: 04 00 00 00 00 00 07 00 00 00 00 00 00 00 00 00 [................]
  |     ebe8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  |     ebf8: 00 00 00 00                                     [....]
  | + [BinaryData directory, 484 bytes]
  | | Meas1SegmentLength = 72
  | | - Tag 0x000c (2 bytes, int16u[1]):
  | |     ea24: 48 00                                           [H.]
  | | Meas1CoordinatesByteCount = 4
  | | - Tag 0x0010 (2 bytes, int16u[1]):
  | |     ea28: 04 00                                           [..]
  | | Meas1Description = 1
  | | - Tag 0x0016 (1 bytes, int8u[1]):
  | |     ea2e: 01                                              [.]
  | | Meas1X = 152
  | | - Tag 0x0030 (2 bytes, int16u[1]):
  | |     ea48: 98 00                                           [..]
  | | Meas1Y = 111
  | | - Tag 0x0032 (2 bytes, int16u[1]):
  | |     ea4a: 6f 00                                           [o.]
  | | Meas1Name = Sp1
  | | - Tag 0x0034 (8 bytes, ustring[8]):
  | |     ea4c: 53 00 70 00 31 00 00 00                         [S.p.1...]         [S.p.1...]


I have trouble with the variable count of coordinate values (4/8/12 Bytes).

I wrote a demo config for the first measuring point, where you can find more informations (for GainDeadMap and CoarseMap see my third post below):

config.txt
# The %Image::ExifTool::UserDefined hash defines new tags to be added to existing tables.
%Image::ExifTool::UserDefined = (

     'Image::ExifTool::FLIR::FFF' => {
    0x05 => {
        Name => 'GainDeadMap',
        SubDirectory => { TagTable => 'Image::ExifTool::FLIR::RawData' },
       },

    0x06 => {
        Name => 'CoarseMap',
        SubDirectory => { TagTable => 'Image::ExifTool::FLIR::RawData' },
       },       

    0x21 => {
        Name => 'MEAS',
        SubDirectory => { TagTable => 'Image::ExifTool::FLIR::MEAS' },
       }, 
    },
);   
   
# define new table
%Image::ExifTool::FLIR::MEAS = (
    GROUPS => { 0 => 'APP1', 2 => 'Image' },
    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
    FIRST_ENTRY => 0,
    NOTES => q{
        ToolInfo (spot tool, line tool, area tool)
    },
     0x00 => {
        # use this tag only to determine the byte order
        # (the value should be 0x0003 if the byte order is correct)
        Name => 'CameraInfoByteOrder',
        Format => 'int16u',
        Hidden => 1,
        RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef',
    },
 
    0x0C => {
        Name => 'Meas1SegmentLength',
          Format => 'int16u',
          PrintConv => 'sprintf("0x%x",$val)',
    },

    0x10 => {
        Name => 'Meas1CoordinatesByteCount',
          Format => 'int16u',
          PrintConv => 'sprintf("0x%x",$val)',
    },

    0x16 => {
        Name => 'Meas1Description',
        DataMember => 'Meas1Description',
        RawConv => '$$self{Meas1Description} = $val',
        PrintConv => {
            1 => 'Spot',
            2 => 'Area',
            3 => 'Ellipse',
            4 => 'Line',
            8 => 'Difference',
        },
    },
 
    0x30 => {
        Name => 'Meas1X',
          Format => 'int16u',
    },
    0x32 => {
        Name => 'Meas1Y',
          Format => 'int16u',
    },
    0x34 => {
        Name => 'Meas1Name',
          Format => 'var_ustring[8]',
    },
);



with this config I can decode the first point (with error message)
the string address 0x34 after the coordinates is only valid, if the first point a Spot (4 Byte x/y coordinates)

$  exiftool -config  config.txt -meas* FLIR0232-Tools.jpg
Unknown format ustring at /usr/bin/lib/Image/ExifTool.pm line 3958, <EXIFTOOL_FILE> chunk 5.
Meas 1 Segment Length           : 0x48
Meas 1 Coordinates Byte Count   : 0x4
Meas 1 Description              : Spot
Meas 1X                         : 152
Meas 1Y                         : 111
Meas 1 Name                     : Sp1


I have no idea, how to decode the second measuring point with a flexible size of the first point.
The order of values Spot/Line/Area etc. can change.

Thanks for help.


PS: I don't know the exact meaning of the 6 values for describe the Ellipse (Area is simple).

I think it's enough to count the geometrical values for further using in scripts.
i.e. Meas1A, Meas1B , Meas2A, Meas2B, Meas2C, Meas2D

You know what to do - you collected the most experience with tag names

tomas123

#1
new post for next tags:

the Flir E4 image above is  a sample for a new file format of embedded visible images (JPG)

here a sample from an old E40 (magic bytes PNG)
>exiftool -v3 IR_0289.jpg
  | FLIR Record 0x0e, offset 0x16bb8, length 0xd6544
  | EmbeddedImage (SubDirectory) -->
  | - Tag 0x000e (877892 bytes):
  |    16bb8: 03 00 00 04 00 03 00 00 00 00 00 00 ff 03 00 00 [................]
  |    16bc8: ff 02 00 00 05 00 00 00 00 00 00 00 00 00 00 00 [................]
  |    16bd8: 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 [.PNG........IHDR]
  |    16be8: 00 00 04 00 00 00 03 00 08 02 00 00 00 35 d8 82 [.............5..]
  |    16bf8: 5a 00 00 20 00 49 44 41 54 78 01 6c bd 07 92 64 [Z.. .IDATx.l...d]
  |     [snip 877812 bytes]
  | + [BinaryData directory, 877892 bytes]
  | | EmbeddedImageWidth = 1024
  | | - Tag 0x0001 (2 bytes, int16u[1]):
  | |    16bba: 00 04                                           [..]
  | | EmbeddedImageHeight = 768
  | | - Tag 0x0002 (2 bytes, int16u[1]):
  | |    16bbc: 00 03                                           [..]
  | | EmbeddedImageType = .PNG
  | | - Tag 0x0010 (4 bytes, undef[4]):
  | |    16bd8: 89 50 4e 47                                     [.PNG]
  | | EmbeddedImage = .PNG.....IHDR....5..Z IDATx.l...dI.eg.IDdfeU.i......f...l.2".....[snip]



the new E4 is the first Flir with an embedded jpg image (Magic number ff d8).
$ exiftool -v3 FLIR0232.jpg | grep -A25 "FLIR Record 0x0e"
  | FLIR Record 0x0e, offset 0xe8b0, length 0x9d46
  | EmbeddedImage (SubDirectory) -->
  | - Tag 0x000e (40262 bytes):
  |     e8b0: 03 00 80 02 e0 01 00 00 00 00 00 00 7f 02 00 00 [................]
  |     e8c0: df 01 00 00 05 00 00 00 5b 00 00 00 00 00 00 00 [........[.......]
  |     e8d0: ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 [......JFIF......]
  |     e8e0: 00 01 00 00 ff e1 09 50 45 78 69 66 00 00 49 49 [.......PExif..II]
  |     e8f0: 2a 00 08 00 00 00 09 00 0f 01 02 00 10 00 00 00 [*...............]
  |     [snip 40182 bytes]
  | + [BinaryData directory, 40262 bytes]
  | | EmbeddedImageWidth = 640
  | | - Tag 0x0001 (2 bytes, int16u[1]):
  | |     e8b2: 80 02                                           [..]
  | | EmbeddedImageHeight = 480
  | | - Tag 0x0002 (2 bytes, int16u[1]):
  | |     e8b4: e0 01                                           [..]
  | | EmbeddedImageType = ....
  | | - Tag 0x0010 (4 bytes, undef[4]):
  | |     e8d0: ff d8 ff e0                                     [....]
  | | EmbeddedImage = .....JFIF.......PExifII*......z...................(....1.........[snip]
  | | - Tag '16.1' (40230 bytes, undef[40230]):
  | |     e8d0: ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 [......JFIF......]
  | |     e8e0: 00 01 00 00 ff e1 09 50 45 78 69 66 00 00 49 49 [.......PExif..II]
  | |     e8f0: 2a 00 08 00 00 00 09 00 0f 01 02 00 10 00 00 00 [*...............]
  | |     e900: 7a 00 00 00 10 01 02 00 05 00 00 00 8a 00 00 00 [z...............]
  | |     e910: 12 01 03 00 01 00 00 00 00 00 00 00 1a 01 05 00 [................]


the current version of exiftool can't yet detect the image type jpg and gives DAT as unkonwn format

flir.pm
    16 => {
        Name => 'EmbeddedImageType',
        Format => 'undef[4]',
       RawConv => '$val =~ /^.PNG/s ? "PNG" : "DAT"',
        Notes => '"PNG" for PNG image in Y Cb Cr colors, or "DAT" for other image data',
    },
    16.1 => {
        Name => 'EmbeddedImage',
        Format => 'undef[$size-0x20]',
        Binary => 1,
    },


Quote$  exiftool -embedded* FLIR0232.jpg
Embedded Image Width            : 640
Embedded Image Height           : 480
Embedded Image Type             : DAT
Embedded Image                  : (Binary data 40230 bytes, use -b option to extract)

it's a minor "bug", because DAT is a also good marker for jpg  :)

tomas123

#2
and now the last two tags

we have another two place holders in flir.pm
    # 5 = GainDeadMap (ref 3)
    # 6 = CoarseMap (ref 3)


some users posted their GainDeadMap and CoarseMap files for 2D FFT analyze in eevblog forum
http://www.eevblog.com/forum/testgear/flir-e4-thermal-imaging-camera-teardown/msg345324/#msg345324

as attachment a sample for this two files

is simple to decode this

config.txt
# The %Image::ExifTool::UserDefined hash defines new tags to be added to existing tables.
%Image::ExifTool::UserDefined = (

     'Image::ExifTool::FLIR::FFF' => {
    0x05 => {
        Name => 'GainDeadMap',
        SubDirectory => { TagTable => 'Image::ExifTool::FLIR::RawData' },
       },

    0x06 => {
        Name => 'CoarseMap',
        SubDirectory => { TagTable => 'Image::ExifTool::FLIR::RawData' },
       },       

    },
);   
   


using:
Quote$  exiftool -config  config.txt -v1 ds250*
======== ds250C_we.crs
  ExifToolVersion = 9.46
  FileName = ds250C_we.crs
  Directory = .
  FileSize = 154144
  FileModifyDate = 1385197074
  FileAccessDate = 1389479512
  FileInodeChangeDate = 1389450710
  FilePermissions = 33261
  FileType = FLIR
  MIMEType = application/unknown
  FLIR Record 0x06, offset 0x0200, length 0x25820
  CoarseMap (SubDirectory) -->
  + [BinaryData directory, 153632 bytes]
  | RawThermalImageWidth = 320
  | RawThermalImageHeight = 240
  | RawThermalImageType = ##$#$#%###%#$$$"#$#"####$"$#$#$"##$##$$"$#$#$"#"%#$#$##"$#$##[snip]
  | RawThermalImage = 35
======== ds250C_we_ap_fi_le_static.gan
  ExifToolVersion = 9.46
  FileName = ds250C_we_ap_fi_le_static.gan
  Directory = .
  FileSize = 154144
  FileModifyDate = 1385197074
  FileAccessDate = 1389479395
  FileInodeChangeDate = 1389450710
  FilePermissions = 33261
  FileType = FLIR
  MIMEType = application/unknown
  FLIR Record 0x05, offset 0x0200, length 0x25820
  GainDeadMap (SubDirectory) -->
  + [BinaryData directory, 153632 bytes]
  | RawThermalImageWidth = 320
  | RawThermalImageHeight = 240
  | RawThermalImageType = q.g.........a.....]...7.....+.B.....T...B.....B.:.....j.W....[snip]
  | RawThermalImage = 45681
    2 image files read


$  exiftool -config  config1.txt -raw* ds250*
======== ds250C_we.crs
Raw Thermal Image Width         : 320
Raw Thermal Image Height        : 240
Raw Thermal Image Type          : TIFF
Raw Thermal Image               : (Binary data 153804 bytes, use -b option to extract)
======== ds250C_we_ap_fi_le_static.gan
Raw Thermal Image Width         : 320
Raw Thermal Image Height        : 240
Raw Thermal Image Type          : TIFF
Raw Thermal Image               : (Binary data 153804 bytes, use -b option to extract)
    2 image files read


Phil Harvey

This looks great, thanks.  I'll take a look at this in detail within the next couple of days and post back here if I have any questions.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

tomas123


Nice, to hear from you.
I have tried to prepare the data so you have a comfortable entry point  :)
If you need more sample images, ask me.

Phil Harvey

Hi Tomas,

I have added support for embedded JPG images, and added decoding of the GainDeadMap and CoarseMap as you suggested.

Regarding the ToolInfo.  I have the FLIR software, and looked at this information before.  The structure seems fairly straightforward, but it will be a bit of work to parse this information into a set of tags that makes sense.  At the time I had decided that it wasn't worth the trouble (especially since it doesn't exist in the original image, and I don't feel a strong need to have ExifTool decode everything that is written by external software).  But I will reconsider if you think that extracting this information would be useful.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

tomas123

#6
Hi Phil,

thanks for fast reply.

The default preset of Flir Cameras is overlaying one measuring marker (i.e. spot in center).

Quote from: Phil Harvey on January 12, 2014, 12:42:48 PM
At the time I had decided that it wasn't worth the trouble
ok, no problem
I wrote above, that Dave want to rebuild the Flir Images with exiftool and need the position of the spot marker.
If you (the master  8) ) can't write a quick solution for this special case (incompatible with fixed byte positions), we should at least specify the first measuring marker with the known values.
We can output all fixed bytes, before the variable part begin.

A suggest:

config.txt
# The %Image::ExifTool::UserDefined hash defines new tags to be added to existing tables.
%Image::ExifTool::UserDefined = (

  'Image::ExifTool::FLIR::FFF' => {

    0x21 => {
        Name => 'MEAS',
        SubDirectory => { TagTable => 'Image::ExifTool::FLIR::MEAS' },
       }, 
   },
);   
   
# define new table
%Image::ExifTool::FLIR::MEAS = (
    GROUPS => { 0 => 'APP1', 2 => 'Image' },
    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
    FIRST_ENTRY => 0,
    NOTES => q{
        ToolInfo (spot tool, line tool, area tool)
    },
     0x00 => {
        # use this tag only to determine the byte order
        # (the value should be 0x0003 if the byte order is correct)
        Name => 'CameraInfoByteOrder',
        Format => 'int16u',
        Hidden => 1,
        RawConv => 'ToggleByteOrder() if $val >= 0x0100; undef',
    },
 
    0x16 => {
        Name => 'Meas1Description',
        DataMember => 'Meas1Description',
        RawConv => '$$self{Meas1Description} = $val',
        PrintConv => {
            1 => 'Spot 1',
            2 => 'Area 1',
            3 => 'Ellipse 1',
            4 => 'Line 1',
            8 => 'Difference 1',
        },
    },
 
    0x30 => {
        Name => 'Meas1X',
          Format => 'int16u',
    },
    0x32 => {
        Name => 'Meas1Y',
          Format => 'int16u',
    },
);


using
$  exiftool -config  config.txt -meas*  FLIR0*.jpg
======== FLIR0074.jpg
Meas 1 Description              : Ellipse 1
Meas 1X                         : 155
Meas 1Y                         : 105
======== FLIR0076.jpg
Meas 1 Description              : Spot 1
Meas 1X                         : 160
Meas 1Y                         : 120
======== FLIR0078.jpg
Meas 1 Description              : Line 1
Meas 1X                         : 128
Meas 1Y                         : 124
======== FLIR0232-Tools.jpg
Meas 1 Description              : Area 1
Meas 1X                         : 103
Meas 1Y                         : 99
======== FLIR0232-empty_points.jpg
Meas 1 Description              : Unknown (7)
Meas 1X                         : 0
Meas 1Y                         : 0
======== FLIR0232.jpg
Meas 1 Description              : Spot 1
Meas 1X                         : 160
Meas 1Y                         : 120


Unknown (7) is the result, if no measuring markers exist.

Thanks for help.



PS: Do you have a solution for embedded jpg's  (see second post)?
       RawConv => '$val =~ /^.PNG/s ? "PNG" : "DAT"',

Phil Harvey

Thanks, I'll consider this.

I fixed the DAT problem with this conversion:

        RawConv => '$val =~ /^\x89PNG/s ? "PNG" : ($val =~ /^\xff\xd8\xff/ ? "JPG" : "DAT")',

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Phil Harvey

Hi Tomas,

I have a preliminary version of the tool info (FFF tag 0x21) decoding which gives this output:

> exiftool ~/Desktop/FLIR0232-Tools.jpg "-tool*"
Tool 1 Type                     : Spot
Tool 1 Parameters               : 152 111
Tool 1 Label                    : Sp1
Tool 2 Type                     : Line
Tool 2 Parameters               : 181 157 291 149
Tool 2 Label                    : Li1
Tool 3 Type                     : Area
Tool 3 Parameters               : 211 5 40 27
Tool 3 Label                    : Ar1
Tool 4 Type                     : Ellipse
Tool 4 Parameters               : 105 177 151 177 105 153
Tool 4 Label                    : El1
Tool 5 Type                     : Difference
Tool 5 Parameters               : 2 1 2 3 1 2
Tool 5 Label                    : Dt1


How does this look to you?  Are the values being decoded properly?  Are my tag names OK (I changed them from your suggestions)?  Is there anything else that should be extracted?

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Phil Harvey

After playing around with the FLIR Tools software a bit more, I think you were right that "Meas" is a better prefix for these tags than "Tool".  I will change this.

Also, I find that the Unicode text string is not always null terminated (FLIR Tools v2.0 for the Mac), which is a bit of a pain, so I will end the string on any funny character.

As well, I have added decoding of FFF tag 0x28, which stores an image from the "Paint colors" tool.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Phil Harvey

#10
The FLIR Tools v2.0 for Mac does some funny things.  The "Difference" measurement doesn't work, and the "Line" measurement produces an extra record of type 5 with parameters "0 0" and no label.  Here is an example image where I added a measurement line and nothing else:

  | FLIR Record 0x21, offset 0x0ebc, length 0x0090
  | MeasInfo (SubDirectory) -->
  | - Tag 0x0021 (144 bytes):
  |     0ebc: 01 00 0c 00 24 00 01 00 00 00 00 00 30 00 00 01 [....$.......0...]
  |     0ecc: 08 00 04 00 00 00 04 00 01 00 00 00 01 00 fe 1f [................]
  |     0edc: 02 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 [..@.............]
  |     0eec: 00 00 f9 00 7f 02 f9 00 31 00 00 00 28 00 00 02 [........1...(...]
  |     0efc: 04 00 00 00 00 00 05 00 01 00 04 00 01 00 02 00 [................]
  |     [snip 64 bytes]
  | + [MeasInfo 1 directory, 48 bytes]
  | |     0ec8: 30 00 00 01 08 00 04 00 00 00 04 00 01 00 00 00 [0...............]
  | |     0ed8: 01 00 fe 1f 02 00 40 00 00 00 00 00 00 00 00 00 [......@.........]
  | |     0ee8: 00 00 00 00 00 00 f9 00 7f 02 f9 00 31 00 00 00 [............1...]
  | | Meas1Type = 4
  | | - Tag 'Meas1Type' (2 bytes, int16u[1]):
  | |     0ed2: 04 00                                           [..]
  | | Meas1Params = 0 249 639 249
  | | - Tag 'Meas1Params' (8 bytes, int16u[4]):
  | |     0eec: 00 00 f9 00 7f 02 f9 00                         [........]
  | | Meas1Label = 1
  | | - Tag 'Meas1Label' (2 bytes):
  | |     0ef4: 31 00                                           [1.]
  | + [MeasInfo 2 directory, 40 bytes]
  | |     0ef8: 28 00 00 02 04 00 00 00 00 00 05 00 01 00 04 00 [(...............]
  | |     0f08: 01 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 [................]
  | |     0f18: 00 00 00 00 00 00 00 00                         [........]
  | | Meas2Type = 5
  | | - Tag 'Meas2Type' (2 bytes, int16u[1]):
  | |     0f02: 05 00                                           [..]
  | | Meas2Params = 0 0
  | | - Tag 'Meas2Params' (4 bytes, int16u[2]):
  | |     0f1c: 00 00 00 00                                     [....]
  | | Meas2Label =
  | | - Tag 'Meas2Label' (0 bytes):


If I add another line, then another record type 5 is generated.  Other tool types don't do this.

- Phil

Edit: Updated verbose output after making a few tweaks to the code.
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Phil Harvey

#11
Running through my test pics, I found a sample with measurement tool type 6 (attached):

======== ../testpics/FLIR/IRWater.jpg
Meas 1 Type                     : Spot
Meas 1 Params                   : 320 240
Meas 1 Label                    : 1
Meas 2 Type                     : Unknown (6)
Meas 2 Params                   : 0 1 0 1 9142 0 9142 0
Meas 2 Label                    : 1


There are 8 parameters, but they don't look like coordinates, and my version of the FLIR Tools software doesn't show anything for this.

If we count your value of 7 (maybe meaning "free" or "unused"), then we have seen all tool types 1 through 8.  The problem is that I don't know what to call 5 or 6.

- Phil

Edit:  I think that type 6 may be "Isotherm".  My FLIR Tools does show an isotherm for this image, but doesn't allow me to add/delete/change isotherms so I can't verify this.  Perhaps you can do this with the Windows version of the FLIR Tools.
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

tomas123

Hi Phil,

great work. I'm curious how you've solved the variable segment length :)

It is not necessary to decode all parameters ("Meas x Params"). 
I think, nobody use the special measurement tools on the small camera display and most flir cams have only a reduced tool set (spot etc)

I loaded the IRWater.jpg in Flir Tools for Windows.
Type 6 is a (custom) Alarm of 17,3°C and I think, that 9142 is the corresponding level of the raw sensor value.

A suggest for the unicode strings:
It's possible that is a fixed string of (max) 3 chars.
Read the 3x2=6 Byte and terminate self with 0x00 0x00.

I confirm your tag names.

Phil Harvey

#13
Odd.  It seems the FLIR Tools displays this information differently on a Mac.

In your screencap it says: Alarm (Custom), Below, Limit: 17.3

On the Mac version I see: Isotherm (Below), Limit: -60.0<

I think it is probably displaying the same information (otherwise "Below" and "Limit" are just coincidental), but the names and numbers are different.

I can't edit these values in my version of FLIR Tools, but I will poke at the file with a hex editor and see if I can discover anything.

I solved the variable segment length problem by hard-coding the routine to parse this information.  I really think that data-driven parsing is much superior, but none of my standard parsing routines could easily handle the variable-length segments.  This is one reason why I thought it would be a bit of work to implement this.  (The other is that the tag names had to be generated dynamically to allow for any number of measurement tools.)

The fixed-length Unicode strings don't solve the problem because I have seen a (hex) byte sequence like 31 00 01 00 fe ff written by the Mac FLIR Tools, and I don't think that 0x0001 is meant to be a Unicode character.

- Phil

Edit: Changing things with a hex editor didn't work.  If I change anything, then no tool information is displayed.  There must be a checksum somewhere that I am invalidating by poking around.  Pity.

I have prepared a pre-release for you if you want to play with this before the official release.
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

tomas123

Quote from: Phil Harvey on January 13, 2014, 07:55:48 PM
Odd.  It seems the FLIR Tools displays this information differently on a Mac.

Flir Tools for MAC is completely different to Windows (a redesign with Database,  following the new IOS/Android Tools)
It's not worth hunting all Flir Tools parameters.

I looked in your pre release code.
You are unfortunately the only perl code hacker for exiftool  :(
Exiftool is more enormous as many community projects.
Great work!!!!