Renames the app throughout: page titles, eyebrow/version labels, Docker startup banner, main.py's header docstring, and the repo links in the footer (now pointing at git.djeex.fr/Djeex/instameex and github.com/Djeex/instameex, matching the renamed Gitea/GitHub repos). Docker image and container are now named "instameex" too (docker/compose.yaml), replacing the old instagram-hdr naming. Adds the new logo: logo.svg is wired up as the favicon on both pages, and logo-long.svg replaces the plain-text "Instameex" eyebrow on the upload page as a properly sized wordmark. The startup banner box width was recalculated by hand for the new content (name plus Source:/Mirror: links instead of the old license/upstream-credit lines), verified against a real container rebuild so the border characters stay aligned. kostis-kounadis/instagram-hdr-assembler references are left alone throughout (README and banner): that's the separate upstream project this app's gain-map logic is adapted from, not this app's own name.
3.3 KiB
Mix your SDR and HDR exports into an Instagram-ready HDR photo.
Note
⚠️ This is an heavily vibe-coded proof of concept — do not expose it to the internet — use it at your own risk. Github repo is a mirror of https://git.djeex.fr/Djeex/instameex. You'll find full package, history and release note there.
Instameex
A small web front end for assembling Instagram-compatible HDR JPEGs (gain map) from an SDR export and an HDR export out of Lightroom or Camera Raw.
The gain-map assembly logic (src/script/app/assembler.py) is adapted from kostis-kounadis/instagram-hdr-assembler, itself based on the reverse-engineering work of karachungen/instagram-hdr-converter. Original MIT license kept in LICENSE.
How it works
- Upload an SDR file (
.jpg/.jpeg) and an HDR file: either a gain-map JPEG (.jpg/.jpeg) or Lightroom's 32-bit float linear HDR TIFF export (.tif/.tiff). - Both files must have identical dimensions and match one of Instagram's
feed resolutions exactly:
1080x1080(1:1),1080x1350(4:5), or1080x566(1.91:1). - The real HDR pixel data is obtained from the HDR file: decoded back
out of a gain-map JPEG (
ultrahdr_app, undoing its own embedded base image and gain map), or read directly from a linear TIFF and given HLG's system-gamma OOTF so it's on the same display-referred scale a gain-map JPEG's HDR intent would be. A gain map is only correct against the exact base it was computed from, and that's rarely the SDR file you upload, so reusing an existing one as-is would quietly reconstruct the wrong HDR look. Your SDR file is cleaned up and re-encoded at 4:2:0 chroma subsampling (Pillow), then a fresh gain map is computed against it and packaged into the final UltraHDR JPEG (ultrahdr_app). The output's visible image is exactly your SDR file; only the gain map is recomputed. The TIFF route skips the gain-map JPEG's 8-bit-in-8-bit precision ceiling, giving a more accurate result. - The validation report is shown on the result page, including the "GainMapMin is negative" warning when present, with a download link for the finished JPEG.
Uploads and results don't stick around: SDR/HDR originals are deleted
right after conversion, the result a few seconds after you leave the
result page (heartbeat + background reaper), and jobs/ is wiped on every
app startup.
Running locally, without Docker
pip install -r requirements.txt
# also install exiftool and compile libultrahdr, see docker/Dockerfile
# for the exact packages and commands (validated on Alpine)
PORT=5050 python3 main.py # PORT is optional, defaults to 5000
Running with Docker
docker compose -f docker/compose.yaml up -d --build
Opens on http://<host>:5050 (port 5000 collides with AirPlay Receiver on
macOS, hence 5050 by default; change it in docker/compose.yaml if
needed).
Running this on the open internet
Don't do it.
