tscircuit / tscircuit/image-utils
PNG comparison ignores alpha-only changes, including in strict mode and diffs
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 10
- PR merge metrics
- No merged PRs in 30d
Description
An alpha-only change in an 8-bit RGBA PNG is ignored by both looksSame and createDiff. Opaque black [0,0,0,255] and fully transparent black [0,0,0,0] compare as { equal: true, differentPixels: 0, totalPixels: 1 }, even with strict: true and both ignore options disabled. Black at alpha 128 is also reported equal to opaque black. On a white background these pixels have clearly different appearance.
createDiff returns an opaque black pixel instead of the requested magenta highlight. The decoder retains the alpha values, but DecodedPng.getPixel returns only RGB, so the equality fast path and perceptual comparator cannot see them. No PNG encoding fallback is involved. This is separate from #20, which explicitly leaves existing alpha comparison behavior unchanged.
Reproduced on main 81a79bc3665a4fedab02d3a8e273b9ac5d1af906 (v0.0.10), Bun 1.4.2. Save as tests/alpha-comparison-repro.test.ts and run bun test tests/alpha-comparison-repro.test.ts:
import { expect, test } from "bun:test"
import { encode, decode } from "fast-png"
import looksSame from "../lib/looks-same"
const pixel = (alpha: number, red = 0) => encode({
width: 1, height: 1, channels: 4, depth: 8,
data: new Uint8Array([red, 0, 0, alpha]),
})
for (const strict of [false, true]) {
for (const alpha of [0, 128]) {
test(`alpha=${alpha}, strict=${strict}`, async () => {
const opaque = pixel(255)
const other = pixel(alpha)
expect(decode(opaque).data[3]).toBe(255)
expect(decode(other).data[3]).toBe(alpha)
expect(await looksSame(opaque, other, {
strict, ignoreCaret: false, ignoreAntialiasing: false,
})).toEqual({ equal: false, differentPixels: 1, totalPixels: 1 })
})
}
}
test("alpha-only change is highlighted in the diff", async () => {
const output = await looksSame.createDiff({
reference: pixel(255), current: pixel(0), strict: true,
ignoreCaret: false, ignoreAntialiasing: false,
highlightColor: "#ff00ff",
})
expect(Array.from(decode(output).data)).toEqual([255, 0, 255, 255])
})
test("identical pixels and opaque RGB changes remain controls", async () => {
expect((await looksSame(pixel(255), pixel(255), { strict: true })).equal).toBe(true)
expect((await looksSame(pixel(255), pixel(255, 255), { strict: true })).equal).toBe(false)
})
Observed: 1 control test passes, 5 regressions fail; TypeScript check passes. The identical-pixel and opaque RGB-change controls behave correctly. This report does not prescribe whether hidden RGB under alpha zero should be ignored or which compositing background to use; the opaque-versus-transparent examples differ under either alpha-aware strict comparison or ordinary white-background visual comparison.
Prepared with Codex (Astra) assistance and verified locally.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with lib/looks-same and the DecodedPng.getPixel path described in the issue, then run bun test tests/alpha-comparison-repro.test.ts. Done means the five alpha-related regressions pass while the identical-pixel and opaque RGB-change control tests remain passing, including the requested magenta diff output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bun, typescript
- Domain
- computer-vision
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100