Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DJI → FLIR Thermal Converter

Convert DJI thermal R-JPEGs into FLIR-format radiometric JPEGs that open directly in FLIR Tools, FLIR Thermal Studio, and ResearchIR with full per-pixel temperature data intact.

Ships as a single double-clickable Windows .exe. No Python install, no DJI SDK download, no command line. Pick a folder, get a folder.

⬇️ Download

Download DJI-to-FLIR.exe (latest release)  ·  All releases

Windows 10 / 11, 64-bit. Self-contained — nothing else to install.


Example

Before (DJI R-JPEG) After (FLIR-format radiometric)
before after

The "after" file is a real FLIR-format R-JPEG that opens in FLIR Tools / Thermal Studio / ResearchIR with the full radiometric stream intact. Round-trip temperature error versus the DJI SDK's own decoded values is < 0.01 °C on test M4T captures.

The whole UI

  1. Click Convert a folder…
  2. Pick a folder of DJI photos (mixed visible + thermal + videos is fine).
  3. Wait for the progress bar.
  4. Output appears next to the source folder as <folder name>_FLIR/.

That's it. No checkboxes, no path-typing, no format pickers. Native Windows tkinter look-and-feel, runs entirely offline.

Supported cameras: H30T, H20T, M30T, M3T, M4T, M4TD.


Why this is technically non-trivial

DJI and FLIR both store "radiometric" thermal JPEGs — every pixel encodes temperature, not just a color — but they use completely different on-disk formats with no published mapping between their two calibration systems:

  • DJI packs raw thermal data into a proprietary APP3 segment that only DJI's own SDK (libdirp.dll) can decode. The decoder applies the camera's per-unit IIRP calibration internally.
  • FLIR packs raw thermal data into an "FFF" container split across one or more APP1 segments, alongside the Planck constants (R1, B, F, O, R2), atmospheric coefficients (ATA1/2, ATB1/2, ATX), and scene parameters (emissivity, distance, reflected/atmospheric temp, humidity).

DJI's tools won't open FLIR files; FLIR's tools won't open DJI files.

The catch that breaks the obvious approaches: ExifTool marks every FLIR radiometric tag as writable = false in FLIR.pm. You can read the tags out of an existing FLIR file but you cannot write them into one. A naïve "extract DJI temperatures, write FLIR tags via ExifTool" pipeline is impossible.

The approach — template-shell with direct FFF binary patching

The converter uses a real FLIR R-JPEG (Thermimage's IR_2412.jpg, MIT license) as a structural template. For each DJI input:

  1. Extract factory-grade temperatures via the DJI Thermal SDK v1.8 over a ctypes wrapper — applies the camera's IIRP calibration.
  2. Re-encode to FLIR's raw uint16 by inverting Thermimage's published Planck equation against the template's calibration.
  3. Walk the JPEG segment chain to extract the template's FLIR APP1 segments and reassemble them into a single FFF blob.
  4. Parse the FFF directory (mixed-endian: BE header + index, LE record bodies) to locate the RawData record (0x0001) and CameraInfo record (0x0020).
  5. Patch RawData in place with the new uint16 stream, re-split the FFF back into APP1-sized chunks (≤ 65 520 bytes per the JPEG segment-length cap), re-inject into the JPEG bytestream.
  6. Patch CameraInfo's sensor dimensions so FLIR Thermal Studio interprets the raw stream correctly when the DJI sensor size differs from the template's source camera.
  7. Pass through EXIF/GPS via a bundled ExifTool — only tags ExifTool can write (DateTimeOriginal, GPS, Model).

Planck calibration, atmospherics, emissivity, distance, reflected temperature, and humidity are left at the template's values — deliberately, because those are exactly what FLIR Tools / Thermal Studio expects, and the user adjusts them post-hoc in FLIR's software just like with a native FLIR capture.

If the SDK can't decode a file (corrupt input, or a camera not in the v1.8 support list) it's flagged as an error and skipped rather than silently degraded — accuracy is the whole point.


Repo layout

main.py                  # tkinter UI (single window, three states)
build.spec               # PyInstaller --onefile spec
requirements.txt
converter/
  pipeline.py            # folder walk + per-file orchestration
  tsdk.py                # libdirp.dll ctypes wrapper (SDK v1.8)
  tier2_flir_jpeg.py     # FLIR R-JPEG binary builder (~925 lines)
  camera_profiles.py     # per-camera sensor metadata
  dji_app3.py            # APP3 raw-thermal segment reader (diagnostic)
  dji_iirp.py            # IIRP per-camera calibration reader
  flir_format/
    planck.py            # temp ↔ raw uint16 (Thermimage formulas)
    tags.py              # FLIR EXIF/XMP tag names
    template.jpg         # canonical FLIR R-JPEG template
examples/                # before/after sample images
docs/BUILD.md            # how to build the .exe from source

Bundled at build time (license / size reasons, not in this repo):

  • tsdk_dlls/ — DJI Thermal SDK v1.8 binaries (requires DJI dev account)
  • exiftool.exe + exiftool_files/ — ExifTool's Windows distribution

Build it yourself

See docs/BUILD.md.

Stack

Python 3.11+ · NumPy · Pillow · piexif · ctypes for the DJI Thermal SDK · tkinter for the native UI · PyInstaller --onefile for the self-contained Windows distribution.

References

License

MIT — see LICENSE.

The DJI Thermal SDK and ExifTool are not redistributed in this repo; they're pulled in at build time on the developer's machine. The end-user .exe bundles them under their respective licenses.

About

Converts DJI radiometric R-JPEGs into FLIR-compatible thermal files via byte-level FFF patching and Planck-equation inversion — <0.01°C round-trip error. Offline single-exe Python tool, in production drone-inspection use.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages