---
name: image-editing
description: Edit images locally with Pillow in one repeatable pipeline - crop to any aspect around a focus point, resize, pad, rotate, exposure / contrast / saturation / warmth, built-in looks or a .cube LUT, sharpen, denoise, vignette, logo or text watermark, border, rounded corners, and export as JPG / PNG / WebP under a size cap. Works on one image or a whole folder, with a dry run and a before / after sheet. Use when the user wants Kenerate images (or their own photos) cropped, resized, retouched, colour graded, watermarked, compressed or batch-processed, without spending credits.
compatibility: Python 3.9+ with Pillow. The Kenerate MCP server is only needed to make or AI-edit the images first.
metadata:
  author: kenerate
  version: "1.1"
  kenerate-tools: "generate_image upscale_image remove_background expand_image wait_for_generation"
---

# Image editing (Pillow pipeline)

Deterministic, free edits: `scripts/imgedit.py` runs an ordered list of ops over one image or a batch. AI edits
(change an object, swap a background, extend the canvas) stay on Kenerate. Rules: [references/KENERATE.md](references/KENERATE.md).

## When to use / not to use
- Use: "crop these to 4:5", "make them all 2000 px wide WebP under 300 KB", "add our logo bottom right",
  "warmer and punchier", "apply this LUT to the whole shoot", "round the corners", "sharpen the upscales".
- Not for: changing what is in the picture (use `generate_image` with `reference_image_urls` and an edit prompt -
  model from [references/MODELS.md](references/MODELS.md), e.g. `kenerate/gpt-image-2.5-sunburst`), cut-outs
  (`remove_background`), extending the canvas (`expand_image`), true 4K (`upscale_image(model="image-upscaler", resolution="4k")`).

## Ask the user
Which images (Kenerate urls, files, a folder), the target (platform / size / aspect), the look, watermark (file,
corner, opacity) and output format. If they name a font for a text watermark, use `--font-family "<name>"` (free
OFL / Apache fonts only; see KENERATE.md, "Fonts").

## 1. Plan the ops, then dry-run
```
python <skill-dir>/scripts/imgedit.py --inputs "<url or folder>" \
  --ops "crop=4:5@0.5,0.4; resize=1080x1350; look=warm-film:0.6; sharpen=0.8; watermark=logo.png@br,0.14,0.7" \
  --format jpg --max-kb 400 --dry-run
```
The dry run validates every op (unknown ops, missing watermark / LUT files, bad looks) and lists the output names.
Fix anything it reports before the real run. `python imgedit.py --help` lists every op.

## 2. Run with a preview
Drop `--dry-run`, add `--preview`: the script writes the files plus `_preview.jpg` (before / after pairs for the
first six). Show the sheet; adjust intensities (`look=name:0.4`) if it's too strong, then run the full batch.

Ops in brief: `crop=16:9[@fx,fy]` or `crop=x,y,w,h`; `resize=WxH[:contain|:stretch]`, `1080w`, `1080h`, `50%`;
`pad=WxH[:#hex|:blur]`; `rotate=90`; `flip=h|v`; `autocontrast`; `exposure=+0.3`; `contrast=1.1`; `saturation=1.2`;
`warmth=20`; `tint=-10`; `brightness=1.05`; `look=teal-orange|warm-film|cool-night|bleach-bypass|vintage-fade|mono|punchy|golden-hour|matte-pastel|noir[:k]`;
`lut=file.cube[:k]`; `sharpen=0.8`; `blur=2`; `denoise=1`; `vignette=0.35`; `grayscale`; `sepia`;
`watermark=file@pos,scale,opacity`; `text=© Brand@pos,size`; `border=20:#fff`; `round=40`.

## Progress and output
Four steps (check ops → fetch → edit with a per-file percentage → preview). `RESULT_JSON.outputs[]` has each file's
path, old / new size and KB. Files land in `kenerate-out/image-editing/` with `--suffix` (default `_edit`).

## If something fails
`"ok": false` names the bad op or file; fix and re-run. Files still over `--max-kb` are listed as a warning: resize
smaller or switch to `--format webp`. Rounded corners force PNG (JPG has no transparency).

## Limits
Pillow only (8-bit). No face retouching or object removal: those are Kenerate edits.
