Repository navigation
fix(images): choose backgrounds for transparent image conversions - #3
Conversation
…lack Converting a transparent image to a format without transparency dropped the alpha channel, so transparent areas came out black (PNG, WebP or SVG to JPG). A new background option decides what they become: - Unset: formats that can store transparency keep it; JPEG and PPM get white. - A color (`white`, `black`, `#rrggbb` or `#rgb`): transparency is flattened onto it, for any image output. Half-transparent pixels blend with it, and 16-bit and float images keep their precision. - `transparent`: kept where possible; refused with a clear message for JPEG and PPM. It applies to the image engine, PDF pages (rendered onto the color, or a clear page background for PNG and other formats with transparency), SVG (drawn onto the color) and HEIC and AVIF output. The CLI takes --background, presets take `background = "..."`, and Quick convert shows a Background control for image targets. Fixes CNV-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the CNV-5 review: - Video to PNG or JPEG ignored the background: FFmpeg's JPEG encoder dropped alpha to black. Still frames now come out of FFmpeg as PNG and go through the image encoder like any other image. Video to GIF with a background color is refused with a clear message rather than ignored. - macOS's sips path ignored a chosen color: the PNG is flattened before sips encodes HEIC, and after it decodes to PNG. - BMP kept RGBA alpha but dropped gray-alpha's; gray-alpha images are now written as RGBA. - Quick convert showed Transparent as the default for PDF to PNG, but PDF pages render on white unless Transparent is picked. The default label now follows the source, and the control is hidden for video to GIF. Refs CNV-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the second CNV-5 review: - Video to PNG re-encoded FFmpeg's frame and lost its color (cICP, cHRM) and pixel-aspect (pHYs) tags. PNG frames keep FFmpeg's file again; only JPEG goes through the image encoder, and a chosen color flattens the PNG. - Quick convert's default label now comes from each file's route: White when it renders through PDF (documents too) or the format can't keep transparency, Transparent otherwise, and Automatic when the selected files differ. - A preset's background no longer applies where the control is hidden (video to GIF), where it could only make the conversion fail. Refs CNV-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CNV-5 Transparent images turn black when converted to JPG; add a background option
ProblemConverting an image with transparency to a format without it (PNG or WebP to JPG, SVG to JPG) turns the transparent areas black. The encoder drops the alpha channel, and fully transparent pixels are stored as black. People expect white, and some want a different background. GoalLet people choose what transparent areas become, with a sensible default. Acceptance criteria
How to verifyconvt logo.png --to jpg # white background
convt logo.png --to jpg --background black # black
convt logo.png --to jpg --background "#ff8800" # orange
convt logo.png --to webp --background white # flattened WebP
convt logo.png --to jpg --background transparent # errorThen pick a background in Quick convert in the app. |
|
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify review — findings
Adds a background option for transparent areas: --background takes black, white, a hex color or transparent (refused for formats that can't store it), and JPEG and PPM fall back to white by default. Quick convert gets a Background select for image targets that shows the engine default (or "Automatic" when files would differ) and keeps a preset's custom color pickable. The control is hidden for video-to-GIF, where the engines don't take a color yet, so a preset's background is dropped there instead of failing the conversion.
Review partial — this diff was larger than one review pass covers, so later files were not reviewed; some findings may be missing.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 507 functions depend on the 501 functions this change touches.
Health — this change adds coupling hotspots:
- new:
validate()— 5 callers, 6 callees - new:
encoded_fixture()— 6 callers, 3 callees - new:
encode_depth()— 2 callers, 7 callees - new:
rgb_to_srgb_matrix()— 3 callers, 4 callees - new:
run()— 1 callers, 10 callees - new:
pack()— 1 callers, 6 callees - new:
a_document_offers_the_pack_and_downloads_only_after_the_click()— 0 callers, 10 callees - new:
full_matrix()— 0 callers, 10 callees - …and 32 more — each is listed as a finding
Verification — 507 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 507 function(s) in the blast radius were not formally verified this run
Docs that may be stale (advisory)
.agents/skills/test-convt-web/SKILL.md§ Sign in as a fixture (lines 45-75): references changed symbolsname.agents/skills/test-convt-web/SKILL.md§ Billing locally (lines 98-105): references changed symbolsname.agents/skills/test-convt-web/SKILL.md§ Cleanup (lines 131-134): references changed symbolsname.agents/skills/test-convt-web/SKILL.md§ P9 cloud converter and API keys (lines 135-142): references changed symbolsconvertAGENTS.md§ Layout (lines 7-25): references changed symbolsfmtAGENTS.md§ Commands (lines 26-42): references changed symbolsfmtdesign-assets/brand/README.md§ Colors (lines 14-23): references changed symbolslogodocs/licence-inventory.md§ Distribution and source obligations (lines 7-16): references changed symbolssourcesdocs/licence-inventory.md§ PDFium, HEIC and native runtime closure (lines 40-53): references changed symbolssourcesdocs/licence-inventory.md§ Rust dependencies (lines 60-71): references changed symbolssources
…and 10 more.
· 40 more finding(s) on lines outside this diff (see the check run).
Summary
Transparent images converted to JPG kept hidden RGB values instead of showing a white background. Add
--background white|black|transparent|#rrggbb, preset support, and a Background dropdown in Quick convert. JPG and PPM default to white; alpha-capable images retain transparency unless a color is chosen. PDF pages can render with a transparent or colored background.Evidence
Before, the actual transparent PNG → JPG CLI run on Linux and macOS produced
(12, 128, 128)at the transparent corner. After, the same fixture produces:cargo test,bun run rs:check, and all 101cargo test -p convt-appheadless tests passed on Linux. Both Quick convert background tests passed. All 13 background integration tests passed on macOS in round 2, including colored PNG and JPEG pixel-aspect checks.Merge Danger
Door: two-way. Reverting restores the previous conversion behavior; no migration or network behavior changes.
Blast radius: image backgrounds through the shared conversion engines, CLI presets, and Quick convert. Video-to-JPG encoding also changes to preserve alpha compositing and pixel aspect ratios.
Fixes CNV-5
Created with GPT-6.1 Sol in T3 Code.