- Replace content-aware-crop with ai-canvas-expand in TOOLS[], AI_TOOL_IDS,
and FEATURE_BUNDLES (matching the already-updated tool-registry.tsx and
feature-manifest.json from commit c6a5d3f)
- Fix trailing syntax error in features.ts (extra closing brace)
- Add ai-canvas-expand-settings mock to tool-registry test files
- Update watermark-image tests to expect 400 (validation rejection) instead
of 422 (processing failure) for corrupted image buffers, matching the
actual route behavior where validateImageBuffer catches them first
Covers session response fields, password guards, users list,
config endpoint, login redirect, callback edge cases, and
backward compatibility. Also adds migration to make password_hash
nullable (required for OIDC-only users) and vitest aliases for
@fastify/cookie and openid-client.
- Two-gate threshold: Otsu >= 60 uses Otsu; 40-59 uses fixed 100
(catches strong scratches on borderline images)
- Remove morphological OPEN after component filtering: it was eroding
thin scratch lines that were correctly detected
- Lower Otsu gate from 60 to 40 to avoid false-negating borderline images
The transparency-fixer now directly detects the baked-in checkerboard
pattern using per-pixel chroma analysis instead of BiRefNet AI matting.
Achromatic pixels in the gray range are classified as background
(transparent), chromatic pixels as foreground (opaque), with smooth
transitions at anti-aliased edges.
- No longer requires Python sidecar or background-removal bundle
- Watermark removal uses Sharp median(5) filter pre-processing
- Moved tool from "ai" to "utilities" category
- Removed from PYTHON_SIDECAR_TOOLS and background-removal enablesTools
- Near-instant processing (pure Sharp, no model inference)
The luminance anomaly detection + LaMa inpainting approach failed because
watermark signal on the matted foreground was too weak (10-15 units vs
threshold of 25). Median filter with kernel=5 effectively removes
semi-transparent watermark text while preserving the stamp structure.
Pipeline is now: median filter (if toggle on) -> BiRefNet matting -> defringe.
No longer requires object-eraser-colorize bundle for watermark removal.
Evidence-based spec informed by diagnostic testing on 4 sample images.
Addresses catastrophic scratch over-detection (up to 68.7% false
coverage on small images), LaMa 512x512 resolution loss, CodeFormer
over-smoothing on small faces, and excessive NLMeans defaults.
Add tier enum (fast/balanced/high) with balanced default to the Zod
settings schema. Pass tier through to outpaint options in both the HTTP
route and the pipeline/batch registry. Fix log message to say
"Starting AI canvas expand" and include tier in structured log fields.
Add TIER_PARAMS dict with fast/balanced/high presets controlling band
size, mask dilation, seam strip width, and Telea pre-inpainting. Parse
tier from sys.argv[7] with balanced fallback. Conditional Telea and
seam refinement steps skip cleanly for fast tier. Progressive outpaint
now accepts band_size and progress bounds for tier-appropriate scaling.
- Fix dispatcher pipe deadlock: drain stdout pipe in a background thread
to prevent blocking when ONNX runtime output exceeds 64KB pipe buffer
- Add 5-minute SSE stall timeout so the UI shows an error instead of
hanging forever when async AI processing stalls
- Guard CPU colorization: skip for images >2MP on CPU and when DDColor
model is not installed, with clear user-facing messages
- Add AVIF decode fallback via ImageMagick for bitstream variants that
Sharp's bundled libheif cannot decode (affects all tools)
EXR: add ffmpeg fallback when ImageMagick lacks the OpenEXR delegate
(common on macOS Homebrew installs). HDR: force 8-bit depth output to
prevent CLAHE crash (hist_local requires VIPS_FORMAT_UCHAR). Batch:
disable socket timeout and increase server requestTimeout to 30 min
so large AI batches don't get killed by Node.js defaults.
AVIF (and other Sharp-native formats) were written as raw bytes to a
.png temp file, causing PIL to fail with "cannot identify image file".
Every other AI module wrapper already converts via sharp().png().toBuffer()
before writing; face-landmarks was the only one that skipped this step.
HDR and EXR files decoded by ImageMagick can produce 16-bit PNG buffers.
Sharp's CLAHE operation (hist_local) requires VIPS_FORMAT_UCHAR (8-bit).
Check the buffer depth and convert to 8-bit sRGB before processing.