mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-24 10:09:01 -06:00
README: product-style showcase with screenshots of public-domain photos developed in LightCraft; reproducible showcase scripts; display-referred tone map for JPEGs (exact pass-through); fixes (crop panel wrap, overlay clipping, greyscale histogram, painted chevrons)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a7ea39573b
commit
440cedfa9c
@@ -0,0 +1,18 @@
|
||||
# README showcase
|
||||
|
||||
The screenshots in `docs/images/` are captured by driving LightCraft over its control channel.
|
||||
|
||||
```sh
|
||||
# public-domain set (downloaded into the gitignored corpus/, see assets/ATTRIBUTION.md for sources)
|
||||
cargo run --release -p lightcraft -- --control 7980 corpus/images/pd &
|
||||
python3 docs/showcase/run.py docs/showcase/pd-edits.jsonl
|
||||
|
||||
# procedural demo library
|
||||
cargo run --release -p lightcraft -- --control 7980 &
|
||||
python3 docs/showcase/run.py docs/showcase/demo.jsonl
|
||||
|
||||
# compress for the repo (macOS)
|
||||
for f in docs/images/*.png; do sips -s format jpeg -s formatOptions 82 "$f" --out "${f%.png}.jpg" && rm "$f"; done
|
||||
```
|
||||
|
||||
`run.py` sends each JSON line (`{"method":…,"params":…}` or `{"sleep": seconds}`) to `127.0.0.1:7980`.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Demo-library showcase: run LightCraft with `--control 7980` (no files → procedural demo library)
|
||||
{"method":"ui.resize","params":{"width":1600,"height":1000}}
|
||||
{"method":"engine.execute","params":{"command":"view.photoGrid"}}
|
||||
{"method":"ui.set","params":{"leftPanel":true,"right":"edit","thumbSize":230,"openSections":["light","color"],"presets":false}}
|
||||
{"sleep":7}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/grid-demo.png"}}
|
||||
# masking: radial gradient over the sun on "Lake at first light"
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[1]}}}
|
||||
{"method":"engine.execute","params":{"command":"view.detail"}}
|
||||
{"method":"ui.set","params":{"leftPanel":false}}
|
||||
{"method":"engine.execute","params":{"command":"develop.set","params":{"values":{"light.highlights":-55,"light.shadows":35,"color.vibrance":25,"effects.clarity":15}}}}
|
||||
{"method":"engine.execute","params":{"command":"panel.masking"}}
|
||||
{"method":"engine.execute","params":{"command":"mask.add","params":{"kind":"linear","start":[0.5,0.0],"end":[0.5,0.45],"name":"Sky"}}}
|
||||
{"method":"engine.execute","params":{"command":"mask.adjust","params":{"values":{"exposure":-0.6,"temp":25,"saturation":20,"dehaze":20}}}}
|
||||
{"method":"engine.execute","params":{"command":"mask.add","params":{"kind":"radial","center":[0.62,0.4],"rx":0.2,"ry":0.14,"feather":70,"name":"Sun glow"}}}
|
||||
{"method":"engine.execute","params":{"command":"mask.adjust","params":{"values":{"exposure":0.5,"temp":40,"saturation":15}}}}
|
||||
{"sleep":7}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/masking.png"}}
|
||||
# presets column + colour mixer
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[6]}}}
|
||||
{"method":"engine.execute","params":{"command":"panel.edit"}}
|
||||
{"method":"engine.execute","params":{"command":"preset.apply","params":{"id":"lc.golden-hour","amount":100}}}
|
||||
{"method":"engine.execute","params":{"command":"panel.presets"}}
|
||||
{"method":"ui.set","params":{"openSections":["color"],"openFlyouts":["mixer"],"mixerMode":"purple"}}
|
||||
{"sleep":7}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/presets-mixer.png"}}
|
||||
{"method":"engine.execute","params":{"command":"panel.presets"}}
|
||||
# black & white + grain on the dunes
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[2]}}}
|
||||
{"method":"engine.execute","params":{"command":"preset.apply","params":{"id":"lc.bw-high-contrast","amount":100}}}
|
||||
{"method":"engine.execute","params":{"command":"develop.set","params":{"values":{"grain.amount":30,"vignette.amount":-25}}}}
|
||||
{"method":"ui.set","params":{"beforeAfter":"split","openSections":["effects"],"openFlyouts":[]}}
|
||||
{"sleep":7}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/bw-split.png"}}
|
||||
{"method":"ui.set","params":{"beforeAfter":"off"}}
|
||||
@@ -0,0 +1,66 @@
|
||||
# Public-domain showcase: run LightCraft with `--control 7980 corpus/images/pd` (see docs/showcase/README.md)
|
||||
{"method":"ui.resize","params":{"width":1600,"height":1000}}
|
||||
{"method":"engine.execute","params":{"command":"photo.setMeta","params":{"ids":[1],"title":"The Tetons and the Snake River","creator":"Ansel Adams (1942), U.S. National Archives","keywords":["mountains","river","black and white","national park"]}}}
|
||||
{"method":"engine.execute","params":{"command":"photo.setMeta","params":{"ids":[2],"title":"Migrant Mother","creator":"Dorothea Lange (1936), Library of Congress","keywords":["portrait","documentary"]}}}
|
||||
{"method":"engine.execute","params":{"command":"photo.setMeta","params":{"ids":[3],"title":"Earthrise","creator":"NASA / Bill Anders, Apollo 8 (1968)","keywords":["space","earth","moon"]}}}
|
||||
{"method":"engine.execute","params":{"command":"photo.setMeta","params":{"ids":[4],"title":"The Blue Marble","creator":"NASA, Apollo 17 (1972)","keywords":["space","earth"]}}}
|
||||
{"method":"engine.execute","params":{"command":"photo.rate","params":{"ids":[1,2,3,4],"rating":5}}}
|
||||
{"method":"engine.execute","params":{"command":"photo.flag","params":{"ids":[1,3],"flag":"pick"}}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[1]}}}
|
||||
{"method":"engine.execute","params":{"command":"develop.set","params":{"values":{"light.exposure":0.15,"light.contrast":28,"light.highlights":-45,"light.shadows":38,"light.whites":22,"light.blacks":-22,"effects.clarity":28,"effects.dehaze":18,"effects.texture":12,"vignette.amount":-18}}}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[2]}}}
|
||||
{"method":"engine.execute","params":{"command":"develop.set","params":{"values":{"light.contrast":18,"light.highlights":-35,"light.shadows":42,"light.blacks":-15,"effects.clarity":22,"effects.texture":18,"vignette.amount":-22,"grading.highlights.hue":42,"grading.highlights.sat":16,"grading.shadows.hue":28,"grading.shadows.sat":12}}}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[3]}}}
|
||||
{"method":"engine.execute","params":{"command":"develop.set","params":{"values":{"wb.temp":6800,"light.exposure":0.25,"light.contrast":12,"light.highlights":-30,"light.shadows":25,"light.blacks":-18,"effects.dehaze":22,"effects.clarity":16,"color.vibrance":22}}}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[4]}}}
|
||||
{"method":"engine.execute","params":{"command":"develop.set","params":{"values":{"light.contrast":16,"light.highlights":-38,"light.shadows":20,"light.blacks":-20,"effects.dehaze":15,"effects.clarity":12,"color.vibrance":30}}}}
|
||||
# hero
|
||||
{"method":"ui.set","params":{"leftPanel":false,"filmstrip":true,"beforeAfter":"off","openSections":["light","effects"],"openFlyouts":[],"right":"edit","presets":false}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[1]}}}
|
||||
{"method":"engine.execute","params":{"command":"view.detail"}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/hero-tetons.png"}}
|
||||
# before / after
|
||||
{"method":"ui.set","params":{"beforeAfter":"sideBySide","openSections":["light"]}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/ba-tetons.png"}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[2]}}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/ba-migrant-mother.png"}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[3]}}}
|
||||
{"method":"ui.set","params":{"openSections":["light","color"]}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/ba-earthrise.png"}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[4]}}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/ba-blue-marble.png"}}
|
||||
# colour grading
|
||||
{"method":"ui.set","params":{"beforeAfter":"off","openSections":["color"],"openFlyouts":["grading"]}}
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[2]}}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/grading-migrant-mother.png"}}
|
||||
# tone curve
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[1]}}}
|
||||
{"method":"engine.execute","params":{"command":"develop.curve","params":{"channel":"master","points":[[0,0.04],[0.25,0.2],[0.5,0.52],[0.78,0.84],[1,0.97]]}}}
|
||||
{"method":"ui.set","params":{"openSections":["light"],"openFlyouts":["curve"],"curveChannel":"master"}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/curve-tetons.png"}}
|
||||
# crop & straighten
|
||||
{"method":"engine.execute","params":{"command":"crop.aspect","params":{"aspect":"16x9"}}}
|
||||
{"method":"engine.execute","params":{"command":"crop.straighten","params":{"angle":2.5}}}
|
||||
{"method":"engine.execute","params":{"command":"panel.crop"}}
|
||||
{"sleep":6}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/crop-tetons.png"}}
|
||||
{"method":"engine.execute","params":{"command":"crop.reset"}}
|
||||
{"method":"engine.execute","params":{"command":"panel.edit"}}
|
||||
# info + keywords
|
||||
{"method":"engine.execute","params":{"command":"library.select","params":{"ids":[3]}}}
|
||||
{"method":"engine.execute","params":{"command":"panel.info"}}
|
||||
{"sleep":5}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/info-earthrise.png"}}
|
||||
{"method":"engine.execute","params":{"command":"panel.edit"}}
|
||||
# grid
|
||||
{"method":"engine.execute","params":{"command":"view.squareGrid"}}
|
||||
{"method":"ui.set","params":{"leftPanel":true,"thumbSize":300}}
|
||||
{"sleep":5}
|
||||
{"method":"ui.screenshot","params":{"path":"docs/images/grid-pd.png"}}
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
"""lcb.py FILE.jsonl — run control requests from a JSON-lines file ({"method":..., "params":...} or {"sleep": s})."""
|
||||
import json, socket, sys, time
|
||||
def call(method, params):
|
||||
s = socket.create_connection(("127.0.0.1", 7980), timeout=180)
|
||||
s.sendall((json.dumps({"id": 1, "method": method, "params": params}) + "\n").encode())
|
||||
buf = b""
|
||||
while not buf.endswith(b"\n"):
|
||||
c = s.recv(1 << 20)
|
||||
if not c: break
|
||||
buf += c
|
||||
return json.loads(buf)
|
||||
for line in open(sys.argv[1]):
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#"): continue
|
||||
r = json.loads(line)
|
||||
if "sleep" in r:
|
||||
time.sleep(r["sleep"]); continue
|
||||
out = call(r["method"], r.get("params", {}))
|
||||
print(r["method"], json.dumps(out)[:160])
|
||||
Reference in New Issue
Block a user