zphoto-core is the embeddable image engine that powers zphoto. It ports the union of Adobe Photoshop (raster) and Adobe Illustrator (vector) into one pure-Rust library, and the defining decision is a single shared layer stack — vector artwork composites onto the same layers as raster pixels, not a separate document. There is no GUI here: hosts drive everything through one command surface, Engine::invoke(cmd, args) -> Result<Value>, and render the result themselves. The engine exposes a C FFI and a Tauri v2 plugin, so the same code embeds in the desktop app and in other MenkeTechnologies apps. Created by MenkeTechnologies.
Raster + Vector, one stack
~371 raster commands and 71 vector commands operate on the same layer model — compositing, masks, and ordering work uniformly across pixels and paths.
One command surface
Every operation goes through Engine::invoke(cmd, args), returning a serde_json::Value — trivial to bridge from any host (Tauri IPC, FFI, tests).
8 / 16 / 32-bit
Pixels are edited at 8-, 16-, and 32-bit depth with f64 geometry, so adjustments and filters keep precision Photoshop-style.
Embeddable, no GUI
Pure Rust with a C FFI (ffi) and a Tauri plugin (tauri_plugin) — no windowing, no platform UI, no C++ blob.
Capability surface
The breadth the engine targets — the union of Photoshop and Illustrator areas. See the engineering report for the module map and verification policy.
- Layers / compositing — layer stack, blend modes, opacity, masks (
model). - Filters — blur, sharpen, noise, distort, stylize, render (
filter). - Adjustments — levels, curves, hue/saturation, color balance, channel ops.
- Fills — solid, gradient, pattern (
fill). - Paint / retouch — brush, eraser, clone/heal, smudge (
paint). - Vector — Bézier paths, shapes, strokes/fills, boolean ops on the shared stack (
vector). - Text — point/area type, type on a path, rasterize (
text). - Codecs — decode/encode raster formats into and out of the model (
codec).
Using the engine
One entry point; the host supplies a command name and JSON args and renders the returned value:
use zphoto_core::Engine;
use serde_json::json;
let engine = Engine::new();
// every operation is a string command + JSON args through one surface
engine.invoke("layer.add", &json!({ "name": "overlay" }))?;
engine.invoke("filter.gaussian_blur", &json!({ "radius": 4.0 }))?;
engine.invoke("adjust.levels", &json!({ "black": 12, "white": 240 }))?;
let png = engine.invoke("io.export", &json!({ "format": "png" }))?;
Where it goes next
Per-command coverage of the Photoshop / Illustrator surface is tracked, source-derived, in zphoto's port report; no command is marked done without a real engine symbol. See the engineering report for the module map.