enhancement: extract binary data from FLIR radiometric jpg

Started by tomas123, March 20, 2013, 12:49:46 PM

Previous topic - Next topic

tomas123

sorry, I found the document today, when I searched for: Flir FFF
a simple ask and the document is the 4. hit  :-\
( I think, the pdf is not public)

You can open FFF Files with free Software: Flir Tools
...but it gives us no new information

only for information:
as atachment a free-of-sense-picture native from my B40 in FFF format
its the same file structure, as you snip the JPG EXIF-TAG APP1 at the position: FFF (first magic bytes of *.fff)



Phil Harvey

Thanks.  I'll add the ability to read the FFF files too.  (It is easy, since it is the same as the APP1 segment as you mentioned, except for a couple of minor complications... not the least of which is that Hasselblad uses the same file extension for their image format.)

- 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

some minor informationen

I looked around for "unsigned long dwNumUsedIndex; /* Number of indexes" and compared the header from some Flir Tools.
The index number is a large place holder for zero filled "tag data (Tag Size 32Byte=>0x20)" and you can correct calculate the first address of camera datas

see my sample
Quote
unsigned long dwIndexOff; /* Pointer to indexes
unsigned long dwNumUsedIndex; /* Number of indexes


Flir B40
JPEG APP1 (42268 bytes):
    0cb4: 46 4c 49 52 00 01 00 00 46 46 46 00 00 00 00 00 [FLIR....FFF.....]
    0cc4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 [...............d]
    0cd4: 00 00 00 40 00 00 00 0e 00 00 00 02 00 00 00 00 [...@............] 0x40+0x0e*0x20=0x0200
    0ce4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a5 14 [................]
    0cf4: 00 00 00 00 8d 50 c2 44
----------------------tagFLIRFILEHEAD---------------------------------------
                                  00 20 00 01 00 00 00 71 [.....P.D. .....q] 0x20 =>  'CameraInfo', TAG_MAIN_T wMainType; /* Main type of index
    0d04: 00 00 00 01 00 00 02 00 00 00 09 ac 00 00 00 00 [................] Address of FLIR Record 0x20 unsigned long dwDataPtr; /* Pointer to data
    0d14: 00 00 00 00 38 d1 b5 bc 00 22 00 01 00 00 00 68 [....8....".....h]



Flir Quickreport
JPEG APP1 (42200 bytes):
    0306: 46 4c 49 52 00 01 00 00 46 46 46 00 4d 54 58 20 [FLIR....FFF.MTX ]
    0316: 49 52 00 00 00 00 00 00 00 00 00 00 00 00 00 64 [IR.............d]
    0326: 00 00 00 40 00 00 00 0c 00 00 00 02 00 00 00 00 [...@............] 0x40+0x0c*0x20=0x01c0
    0336: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
    0346: 00 00 00 00 00 00 00 00
----------------------tagFLIRFILEHEAD---------------------------------------
                                  00 01 00 02 00 00 00 64 [...............d] 0x01 => Name => 'RawData',
    0356: 00 00 00 01 00 00 01 c0 00 00 96 20 00 00 00 00 [........... ....] Address of FLIR Record 0x01
    0366: 00 00 00 00 00 00 00 00 00 20 00 01 00 00 00 66 [......... .....f]



Flir Tools
JPEG APP1 (42784 bytes):
    e544: 46 4c 49 52 00 01 00 00 46 46 46 00 4d 54 58 20 [FLIR....FFF.MTX ]
    e554: 49 52 00 00 00 00 00 00 00 00 00 00 00 00 00 64 [IR.............d]
    e564: 00 00 00 40 00 00 00 1e 00 00 00 02 00 00 00 00 [...@............] 0x40+0x1e*0x20=0x0400
    e574: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
    e584: 00 00 00 00 00 00 00 00
----------------------tagFLIRFILEHEAD---------------------------------------
                                  00 01 00 02 00 00 00 64 [...............d] 0x01 => Name => 'RawData'
    e594: 00 00 00 01 00 00 04 00 00 00 96 20 00 00 00 00 [........... ....] Address of FLIR Record 0x01
    e5a4: 00 00 00 00 00 00 00 00 00 20 00 01 00 00 00 71 [......... .....q]



Flir WebViewer (Silverlight)
JPEG APP1 (65532 bytes):
    15a8: 46 4c 49 52 00 01 00 19 46 46 46 00 4d 54 58 20 [FLIR....FFF.MTX ]
    15b8: 49 52 00 00 00 00 00 00 00 00 00 00 00 00 00 64 [IR.............d]
    15c8: 00 00 00 40 00 00 00 0d 00 00 00 02 00 00 00 00 [...@............] 0x40+0x0d*0x20=0x01e0
    15d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
    15e8: 00 00 00 00 00 00 00 00
----------------------tagFLIRFILEHEAD---------------------------------------
                                  00 01 00 02 00 00 00 64 [...............d] 0x01 => Name => 'RawData'
    15f8: 00 00 00 01 00 00 01 e0 00 09 60 20 00 00 00 00 [..........` ....] Address of FLIR Record 0x01
    1608: 00 00 00 00 00 00 00 00 00 20 00 01 00 00 00 6a [......... .....j]

Only the camera calculates a checksum. All Tools sets dwChecksum to zero.

Phil Harvey

These numbers just give the location and the number of entries in what I call the record directory (the FLIR equivalent of the EXIF IFD).  You aren't guaranteed that the camera data comes immediately after this, but in practice it is likely that it does.  Instead, the offsets in the record directory should be used to determine the location of the camera data records.

- 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

These are only minor hints to complete the puzzle.
Nobody will calculate the first address if he can read the adress direct from "tagFLIRFILEINDEX  unsigned long dwDataPtr; /* Pointer to data ."

I write a awk script for saving a stitched 16 Bit panorama in radiometric jpg and so I must rebuild all header values...

Nice hint: if you rename a *.fff  to *.jpg you can open the picture with Flir Quickreport V1.2 SP2 (my windows runs in a VirtualBox)

Phil Harvey

I found another interesting reference while Googling around today:

http://support.flir.com/DocDownload/Assets/62/English/1557488%24A.pdf

This gives some details about the "FLIR public image file format" (FPF), which shares some characteristics with the FFF format, and provides hints about the meanings of some of the unknown tags.

- 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

here is the missing header file fpfimg.h (see page 97)
http://code.google.com/p/dvelib/source/browse/trunk/flirPublicFormat/fpfConverter/Fpfimg.h?spec=svn3&r=3

and here is a fpf file
http://dvelib.googlecode.com/svn-history/r3/trunk/flirPublicFormat/fpfConverter/test/1.fpf

tomas123

let's play Rosetta Stone

I loaded my file IR_1546.jpg from B40 to ThermaCAM Researcher Pro 2.10 (trial) and saved it without some manipulation as Ir_1546.fpf

Phil Harvey

#38
This is fantastic!

I have gone through your samples in detail, and have improved the tag names for a few tags and confirmed some others.

The only potentially useful information in the FPF file that I am missing from the FFF information is:

1) the date/time stamp (although this is in the JPEG EXIF, it should be in the FFF somewhere too) <-- I'll look for this

2) The are the filter name, part number and serial number. <-- perhaps you could locate these by writing random ASCII strings into the FFF information after the LensSerialNumber?

Here is what I am currently decoding:

> exiftool ../testpics/FLIR/IR_1546.* -flir:all -H -G
======== ../testpics/FLIR/IR_1546.fpf
[FLIR]          0x0028 Image Type                      : Temperature
[FLIR]          0x002a Pixel Format                    : float
[FLIR]          0x002c Image Width                     : 160
[FLIR]          0x002e Image Height                    : 120
[FLIR]          0x0030 Trig Count                      : 0
[FLIR]          0x0034 Frame Count                     : 1
[FLIR]          0x0078 Camera Model                    : FLIR E40
[FLIR]          0x0098 Camera Part Number              : 49001-2001
[FLIR]          0x00b8 Camera Serial Number            : 49033333
[FLIR]          0x00d8 Blackbody Range Min             : -20.0 C
[FLIR]          0x00dc Blackbody Range Max             : 120.0 C
[FLIR]          0x00e0 Lens Model                      : FOL18
[FLIR]          0x0100 Lens Part Number                :
[FLIR]          0x0120 Lens Serial Number              :
[FLIR]          0x0140 Filter Model                    :
[FLIR]          0x0150 Filter Part Number              :
[FLIR]          0x0180 Filter Serial Number            :
[FLIR]          0x01e0 Emissivity                      : 0.95
[FLIR]          0x01e4 Object Distance                 : 1.00 m
[FLIR]          0x01e8 Reflected Apparent Temperature  : 20.0 C
[FLIR]          0x01ec Atmospheric Temperature         : 20.0 C
[FLIR]          0x01f0 Relative Humidity               : 50.0 %
[FLIR]          0x01f4 Computed Atmospheric Trans      : 0.99
[FLIR]          0x01f8 Estimated Atmospheric Trans     : 0.00
[FLIR]          0x01fc Reference Temperature           : 20.0 C
[FLIR]          0x0200 IR Window Temperature           : 20.0 C
[FLIR]          0x0204 IR Window Transmission          : 1.00
[FLIR]          0x0248 Date Time                       : 2013:02:22 11:19:20.891
[FLIR]          0x02a4 Camera Scale Min                : -5.9 C
[FLIR]          0x02a8 Camera Scale Max                : 4.0 C
[FLIR]          0x02ac Calculated Scale Min            : -13.2 C
[FLIR]          0x02b0 Calculated Scale Max            : 6.5 C
[FLIR]          0x02b4 Actual Scale Min                : -5.9 C
[FLIR]          0x02b8 Actual Scale Max                : 4.0 C
======== ../testpics/FLIR/IR_1546.jpg
[MakerNotes]    0x0001 Image Maximum Temperature       : 8
[MakerNotes]    0x0002 Image Minimum Temperature       : -13
[MakerNotes]    0x0003 Emissivity                      : 0.95
[APP1]          0x0001 Raw Thermal Image Width         : 160
[APP1]          0x0002 Raw Thermal Image Height        : 120
[APP1]          0x0010 Raw Thermal Image Type          : TIFF
[APP1]          0x0010 Raw Thermal Image               : (Binary data 38604 bytes, use -b option to extract)
[APP1]          0x0020 Emissivity                      : 0.95
[APP1]          0x0024 Object Distance                 : 1.00 m
[APP1]          0x0028 Reflected Apparent Temperature  : 20.0 C
[APP1]          0x002c Atmospheric Temperature         : 20.0 C
[APP1]          0x0030 IR Window Temperature           : 20.0 C
[APP1]          0x0034 IR Window Transmission          : 1.00
[APP1]          0x003c Relative Humidity               : 50.0 %
[APP1]          0x0090 Blackbody Range Max             : 120.0 C
[APP1]          0x0094 Blackbody Range Min             : -20.0 C
[APP1]          0x00d4 Camera Model                    : FLIR E40
[APP1]          0x00f4 Camera Part Number              : 49001-2001
[APP1]          0x0104 Camera Serial Number            : 49033333
[APP1]          0x0114 Camera Software                 : 20.0.0
[APP1]          0x0170 Lens Model                      : FOL18
[APP1]          0x0190 Lens Part Number                :
[APP1]          0x01a0 Lens Serial Number              :
[APP1]          0x0000 Palette Colors                  : 224
[APP1]          0x0006 Above Color                     : 169 128 128
[APP1]          0x0009 Below Color                     : 49 128 128
[APP1]          0x000c Overflow Color                  : 67 215 98
[APP1]          0x000f Underflow Color                 : 40 109 239
[APP1]          0x0012 Isotherm 1 Color                : 99 128 128
[APP1]          0x0015 Isotherm 2 Color                : 92 115 209
[APP1]          0x001a Palette Method                  : 0
[APP1]          0x001b Palette Stretch                 : 1
[APP1]          0x0050 Palette Name                    : Iron
[APP1]          0x0070 Palette                         : (Binary data 672 bytes, use -b option to extract)
    2 image files read


- Phil

Edit:  I found the date/time stamp: two long integers at offset 0x384 in the CameraInfo.  My only problem is handling the time zone.  For many of my samples this time is different from the EXIF times by an integral number of hours, but for your samples these times are the same.  What time zone are you in?  I'm hoping +00:00.  If so, could you try changing your system timezone and converting IR_1546.jpg again to see if the time stored in the FPF file is GMT or local time?  Thanks.  (I'm on a Mac, so running the ThermaCAM software is difficult for me.)
...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

I changed all camera settings to different values and took different photos:
- DST -1
- DST +/- 0
- DST +1
- Picture in  Picture
- Infrared Zoom 2x
then I patched one photo by writing random ASCII strings after the LensSerialNumber

all these pictures I converted to FPF-Format

tomas123

 
Quote from: Phil Harvey on April 11, 2013, 02:47:39 PM
I'm on a Mac, so running the ThermaCAM software is difficult for me.
on my Mac I work with virtualbox (on old XP-machine and a small Win7x32) for running some nice windows tools (like Hxd HexEditor etc.)

unfortunately the free "Flir Tools for Mac" are not stable, but it works

if you install Silverlight on MAC :-\ then you can start the Flir Online Viewer http://support.flir.com/webviewer
if you type * in the open file dialog box, then you can upload a *.fff file vor viewing and you can save the FFF-file as radiometric jpg  :)
the Flir Online Viewer needs 1Mbit/sec  >:(

Phil Harvey

I got your files, thanks!  I have only taken a look at the "Name_patched" file so far, but unfortunately your random ASCII strings stopped just before where I expected the filter name to be stored. (After the LensSerialNumber.)

I'll try downloading the FLIR tools for Mac when I'm on a faster internet connection (I'm on dialup right now).

- 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

OK, I am now able to decode the time zone from the FFF information (it was located at offset 0x38c in the CameraInfo):

> exiftool ~/Desktop/{fpf,jpg}/*1* -datetimeoriginal -G1
======== /Users/phil/Desktop/fpf/Ir_2517_dst-1.fpf
[FLIR]          Date/Time Original              : 2013:04:12 09:24:01.131
======== /Users/phil/Desktop/fpf/Ir_2519_dst+0.fpf
[FLIR]          Date/Time Original              : 2013:04:12 09:24:44.292
======== /Users/phil/Desktop/fpf/Ir_2521_dst+1.fpf
[FLIR]          Date/Time Original              : 2013:04:12 09:25:14.279
======== /Users/phil/Desktop/jpg/IR_2517_DST-1.jpg
[ExifIFD]       Date/Time Original              : 2013:04:12 09:24:01
[FLIR]          Date/Time Original              : 2013:04:12 09:24:01.131-01:00
======== /Users/phil/Desktop/jpg/IR_2519_DST+0.jpg
[ExifIFD]       Date/Time Original              : 2013:04:12 09:24:44
[FLIR]          Date/Time Original              : 2013:04:12 09:24:44.292+00:00
======== /Users/phil/Desktop/jpg/IR_2521_DST+1.jpg
[ExifIFD]       Date/Time Original              : 2013:04:12 09:25:14
[FLIR]          Date/Time Original              : 2013:04:12 09:25:14.279+01:00
    6 image files read


And the times in all of my samples are now consistent.  Thanks!

- 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

you are a hard tag hunter

I repatched the jpg and converted it to fpf
Also two screenshots from Flir Tools with the Name of lens_filter and objectiv

I don't think anyone on this planet reaches this point :-)

Phil Harvey

GOT IT!  Thanks!  I can now decode the filter strings too! :)

- 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 ($).