tscircuit / tscircuit/image-utils
percentThreshold is accepted and validated but discarded before comparison
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 10
- PR merge metrics
- No merged PRs in 30d
Description
The public comparison options accept percentThreshold, and prepareOptions rejects negative/non-finite values with a threshold-specific error. However, a valid value is then discarded: PreparedOptions has no threshold field, the returned object omits it, and compare always uses differentPixels === 0 for equal.
For two fully opaque 10x1 RGBA images differing at exactly one pixel, omitted/0/0.1/1/10/50/100 all return { equal: false, differentPixels: 1, totalPixels: 10 }. This occurs in both strict and non-strict mode with caret/antialiasing ignoring disabled. Negative, NaN and Infinity thresholds throw, so this is an actively accepted/validated option that does not affect comparison, rather than an arbitrary unknown JS property.
The option was introduced in #3 alongside pixel counts. Its tests calculate a percentage on the caller side and do not exercise percentThreshold. I found no documented unit or boundary convention, so this report does not assume a particular 0..1 versus 0..100 interpretation. Please either wire the option into a documented threshold policy or remove/deprecate the inert option and direct callers to compare the returned counts themselves. Existing raw differentPixels/totalPixels should remain available.
Reproduced on main 81a79bc3665a4fedab02d3a8e273b9ac5d1af906 (v0.0.10), Bun 1.4.2. Save at the repository root as reproduce-percent-threshold.ts and run bun reproduce-percent-threshold.ts:
import { encode } from "fast-png"
import looksSame from "./lib/looks-same"
const referenceData = new Uint8Array(10 * 4)
for (let i = 3; i < referenceData.length; i += 4) referenceData[i] = 255
const currentData = referenceData.slice()
currentData[0] = 255
const png = (data: Uint8Array) => encode({ width: 10, height: 1, channels: 4, depth: 8, data })
const reference = png(referenceData)
const current = png(currentData)
for (const strict of [false, true]) for (const percentThreshold of [undefined, 0, 0.1, 1, 10, 50, 100]) {
const result = await looksSame(reference, current, {
percentThreshold, strict, ignoreCaret: false, ignoreAntialiasing: false,
})
console.log(JSON.stringify({ strict, percentThreshold: percentThreshold ?? "omitted", ...result }))
}
for (const percentThreshold of [-1, Number.NaN, Number.POSITIVE_INFINITY]) {
try {
await looksSame(reference, current, { percentThreshold })
throw new Error("invalid threshold unexpectedly accepted")
} catch (error) {
if (!(error instanceof TypeError)) throw error
console.log(JSON.stringify({ invalid: String(percentThreshold), error: error.message }))
}
}
console.log(JSON.stringify({ identicalControl: await looksSame(reference, reference, { percentThreshold: 0 }) }))
Validation: all 14 changed-image configurations returned the same one-pixel difference; all three invalid-value controls threw the documented TypeError, and the identical-image control returned equal=true. TypeScript check passed. This is independent of #39: all source pixels here have alpha 255.
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 in lib/looks-same and trace prepareOptions, PreparedOptions, and compare to see where percentThreshold is validated and lost. Run reproduce-percent-threshold.ts first, then inspect the existing comparison tests; done means the option has a documented, tested policy or is removed/deprecated while differentPixels and totalPixels remain available.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- computer-vision, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100