Python Photo Workbench
PhotoWorkbench adds realistic borders, paper texture, soft edges, drop shadow, LUT color grading, and film grain to photos. It is a CLI-first tool with optional GUI application, presets and resource folders stored in your user config directory.
Features
- Clean border layouts or polaroid-style frames
- Soft feathered edges and configurable drop shadow
- Paper texture with adjustable noise and blend strength
- Optional LUT color grading via .cube files
- Optional film grain with tunable parameters
- Preset support via JSON configuration files
Install
pip install photoworkbench
GUI Application
The pip package installs two launch modes:
- CLI mode:
photoworkbench(same options aspwb.py) - GUI mode:
photoworkbench-gui
Start the GUI with:
photoworkbench-gui
Example: Polaroid Frame
python src/photoworkbench/pwb.py input.jpg output.jpg \
--border-size 100 \
--border-color "245,242,235" \
--polaroid \
--polaroid-bottom-factor 1.8 \
--soft-edges \
--feather-radius 8 \
--shadow \
--shadow-offset 15 \
--shadow-blur 12 \
--texture \
--texture-strength 0.15 \
--noise-strength 20
Example: LUT + Film Grain
python src/photoworkbench/pwb.py input.jpg output.jpg \
--enable-lut \
--lut-path "look.cube" \
--lut-strength 0.85 \
--enable-filmgrain \
--filmgrain-scale 1.0 \
--filmgrain-src-gamma 1.0 \
--filmgrain-grain-power 0.7 \
--filmgrain-highs 0.2 \
--filmgrain-shadows 0.2 \
--filmgrain-type 1 \
--filmgrain-grain-sat 0.5 \
--filmgrain-sharpen 1 \
--filmgrain-seed 42
Presets and Resource Paths
PhotoWorkbench looks for user presets and LUTs in the app config directory:
- Presets:
~/.config/photoworkbench/presets/ - LUTs:
~/.config/photoworkbench/luts/
You can pass an absolute path, a path relative to the current working directory, or just a filename that exists in the resource folder.
Preset Format
Preset files are JSON and can contain any CLI option names. Example my-border.json:
{
"border_size": 120,
"border_color": "245,242,235",
"enable_shadow": true,
"enable_soft_edges": true,
"enable_texture": true,
"feather_radius": 8,
"shadow_offset": 12,
"shadow_blur": 10,
"texture_strength": 0.12,
"noise_strength": 18
}
Use it with:
python src/photoworkbench/pwb.py input.jpg output.jpg --preset-path my-border.json
CLI Reference
usage: pwb.py [-h] [--preset-path PRESET_PATH] [--border-size BORDER_SIZE]
[--border-size-percent BORDER_SIZE_PERCENT]
[--border-color BORDER_COLOR] [--polaroid] [--enable-border]
[--polaroid-bottom-factor POLAROID_BOTTOM_FACTOR] [--shadow]
[--soft-edges] [--texture] [--enable-lut]
[--lut-path LUT_PATH] [--lut-strength LUT_STRENGTH]
[--enable-filmgrain] [--filmgrain-scale FILMGRAIN_SCALE]
[--filmgrain-src-gamma FILMGRAIN_SRC_GAMMA]
[--filmgrain-grain-power FILMGRAIN_GRAIN_POWER]
[--filmgrain-highs FILMGRAIN_HIGHS]
[--filmgrain-shadows FILMGRAIN_SHADOWS]
[--filmgrain-type FILMGRAIN_TYPE]
[--filmgrain-grain-sat FILMGRAIN_GRAIN_SAT]
[--filmgrain-gray-scale] [--filmgrain-sharpen FILMGRAIN_SHARPEN]
[--filmgrain-seed FILMGRAIN_SEED] [--feather-radius FEATHER_RADIUS]
[--shadow-offset SHADOW_OFFSET] [--shadow-blur SHADOW_BLUR]
[--texture-strength TEXTURE_STRENGTH]
[--noise-strength NOISE_STRENGTH]
input output
Layout
--border-sizesets the border size in pixels for all sides.--border-size-percentuses a percentage of the image short side (overrides pixel size).--border-colortakesR,G,Bvalues, for example"255,255,255".--polaroidenables a thicker bottom border.--polaroid-bottom-factorscales the bottom border height.--enable-borderdisables border generation.
Styling
--soft-edgesdisables feathered edges.--feather-radiuscontrols the feather size in pixels.--shadowdisables the drop shadow.--shadow-offsetsets the shadow offset in pixels.--shadow-blursets the shadow blur radius.--texturedisables paper texture.--texture-strengthblends texture with the background (0 to 1).--noise-strengthcontrols texture noise intensity.- Defaults: shadow, soft edges, and texture are off in the CLI; enable them in presets by setting
enable_shadow,enable_soft_edges, andenable_texturetotrue.
Color and Grain
--enable-lutenables LUT color grading.--lut-pathpoints to a.cubefile.--lut-strengthblends LUT results (0 to 1).--enable-filmgrainenables film grain processing.--filmgrain-scale,--filmgrain-src-gamma,--filmgrain-grain-powertune the base grain.--filmgrain-highs,--filmgrain-shadowstune highlights/shadows grain influence.--filmgrain-typeselects a grain type preset.--filmgrain-grain-satcontrols grain color saturation.--filmgrain-gray-scaleforces monochrome grain.--filmgrain-sharpenapplies sharpening passes.--filmgrain-seedsets a deterministic grain seed.
Notes
The filmgrain algorithm is the work of "larspontoppidan" (https://github.com/larspontoppidan/filmgrainer).
- EXIF orientation is normalized so portrait images stay upright.
- EXIF metadata is preserved when available.
Dependencies
- Pillow
- appdirs
- lut-tools
- filmgrainer
Install with your preferred Python packaging workflow, then run the CLI examples above.
Metadata
Release files for photoworkbench 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| photoworkbench-0.1.0.tar.gz | 29.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| photoworkbench-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.1 kB
Release files / photoworkbench-0.1.0.tar.gz
| Download URL | photoworkbench-0.1.0.tar.gz |
|---|---|
| Size | 29.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a465b4c533d53ccb6d918eec4ca717432624d5cbc3866cac3c310b46e2241204
|
|
BLAKE2b-256 checksum How to use checksums |
77eca3029a627bbdd81ac1f5e327b19d4ff29e5452a91d05afe6963bb48dd3b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|
Release files / photoworkbench-0.1.0-py3-none-any.whl
| Download URL | photoworkbench-0.1.0-py3-none-any.whl |
|---|---|
| Size | 27.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cf9a434b3eed572c830f63bea01dae0ff71b7e93921798e90c7585e16d115157
|
|
BLAKE2b-256 checksum How to use checksums |
43721eef83c419787d56fcbfd9d1126493acf093990530a43773e5abb4187c8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|