Filtrox is a AI-assisted photo grading tool built around Streamlit, Gemini, and Darktable. It generates multiple edit variations, lets you iteratively pick the direction you like, and renders the result by patching Darktable XMP history entries instead of editing pixels directly in Python.
- Takes a source image and a text prompt such as "warm cinematic sunset" or "clean bright portrait".
- Uses Gemini to generate multiple grading parameter sets.
- Applies those parameters through Darktable-compatible XMP/module settings.
- Lets you pick a preferred variation and generate the next round of refinements.
- Supports saved filters and batch application workflows in the Streamlit UI.
- app.py: main Streamlit app.
- src/photo_editing_agent.py: prompt construction and iterative variation logic.
- src/llm_backend.py: Gemini wrapper.
- src/darktable_processor.py: render bridge.
- src/xmp_gen.py: XMP patching and Darktable CLI execution.
- system_prompt.md: editing prompt used for generation.
- saved_filters/filters.json: saved presets created from the UI.
- Python 3.10+
- Darktable installed locally
darktable-cliavailable in your shell, or an explicit path set in.env- A Google Gemini API key
Python packages used by the app:
streamlitpillowpython-dotenvgoogle-generativeai
Create and activate a virtual environment, then install dependencies:
python -m venv .venv
source .venv/bin/activate
pip install streamlit pillow python-dotenv google-generativeaiCreate a .env file in the project root:
GEMINI_API_KEY=your_api_key_here
DARKTABLE_CLI_PATH=darktable-cliIf darktable-cli is not on your PATH, set DARKTABLE_CLI_PATH to the full executable path.
Start the Streamlit app:
streamlit run app.pyThen open the local Streamlit URL shown in the terminal.
- Upload or select an image.
- Enter a style request in natural language.
- Review the generated variations.
- Choose the closest result.
- Iterate again, or give explicit feedback to push the look further.
- Save a filter if you want to reuse it later.
- Apply saved or current filters to a batch of images.
The app tracks preferred and disliked factor ranges across iterations so later generations stay closer to your selected direction.
Files like C.json, a.json, and b.json are Darktable-style module presets used by the XMP patching pipeline.
The shape is:
{
"factors": {
"exposure": 0.25,
"temperature": 55,
"tint": 1.2,
"vibrance": 21,
"saturation": 10.5
},
"modules": {
"exposure": {
"enabled": 1,
"modversion": 7,
"params": {
"exposure": 0.3
}
}
}
}Notes:
factorsare the simplified high-level controls used for feedback and iteration.modulescontains the actual Darktable module payloads that get written into XMP history.- Each module usually includes
enabled,modversion, andparams. - The available modules in the sample presets include
exposure,sigmoid,toneequal,temperature,diffuse, and color-related modules such ascolorbalancergb.
- Generated sessions are written under sessions.
- Saved filters are stored in saved_filters/filters.json.
- Sample images and XMP files in the repository are useful as test inputs and reference presets.
- This project depends on external local software and an external API, so failures usually come from one of three places: missing
darktable-cli, invalid Gemini credentials, or malformed preset/XMP data. - The current LLM backend is Gemini-only by default.
- The repository does not currently include a pinned
requirements.txtor automated test suite for the Streamlit app.
- Add a
requirements.txtorpyproject.toml. - Add schema validation for preset JSON before render.
- Add smoke tests for XMP generation and CLI rendering.
- Split the Streamlit UI into smaller modules.