mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
fix(thumbhash): re-condition alpha fixture and assert solid.png header
alpha.png varied only alpha over a constant color, so compositing atop the average canceled L/P/Q exactly like solid.png, leaving it just as float-noise unstable and silently dropping alpha-path coverage. Vary R/G/B with position too so alpha.png carries real signal and reproduces byte-exactly, then replace the blanket solid.png skip with a precise assertion on its well-conditioned header bytes and quantized-zero scales. Also apply a range-over-int modernizer hint in reference_test.go.
This commit is contained in:
parent
0c78c65b3c
commit
02d253b2b0
@ -53,14 +53,10 @@ func loadGoldens() map[string]string {
|
||||
}
|
||||
|
||||
var _ = Describe("reference port", func() {
|
||||
// solid.png and alpha.png are exactly uniform in color, so their true DCT AC term is 0 and the
|
||||
// hash instead encodes float rounding noise from cos(), where Go and V8 disagree in the last bit.
|
||||
floatUnstable := map[string]bool{"solid.png": true, "alpha.png": true}
|
||||
|
||||
It("reproduces every golden vector", func() {
|
||||
for name, want := range loadGoldens() {
|
||||
if floatUnstable[name] {
|
||||
continue
|
||||
if name == "solid.png" {
|
||||
continue // see the dedicated header-only spec below
|
||||
}
|
||||
w, h, rgba := loadFixture(name)
|
||||
got := base64.StdEncoding.EncodeToString(referenceEncode(w, h, rgba))
|
||||
@ -68,6 +64,22 @@ var _ = Describe("reference port", func() {
|
||||
}
|
||||
})
|
||||
|
||||
// solid.png is uniform, so its true AC term is 0 and the golden's AC nibbles are just float
|
||||
// rounding noise from cos(); only the header (DC terms + scales, which quantize to 0) is well-defined.
|
||||
It("reproduces the well-conditioned header of a uniform image", func() {
|
||||
want, err := base64.StdEncoding.DecodeString(loadGoldens()["solid.png"])
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
w, h, rgba := loadFixture("solid.png")
|
||||
got := referenceEncode(w, h, rgba)
|
||||
Expect(got[:5]).To(Equal(want[:5]), "header bytes")
|
||||
|
||||
header24 := int(got[0]) | int(got[1])<<8 | int(got[2])<<16
|
||||
header16 := int(got[3]) | int(got[4])<<8
|
||||
Expect((header24>>18)&31).To(Equal(0), "lScale")
|
||||
Expect((header16>>3)&63).To(Equal(0), "pScale")
|
||||
Expect((header16>>9)&63).To(Equal(0), "qScale")
|
||||
})
|
||||
|
||||
It("produces 24 bytes for a square opaque image", func() {
|
||||
w, h, rgba := loadFixture("square.png")
|
||||
Expect(referenceEncode(w, h, rgba)).To(HaveLen(24))
|
||||
@ -122,7 +134,7 @@ func referenceEncode(w, h int, rgba []byte) []byte {
|
||||
|
||||
encodeChannel := func(channel []float64, nx, ny int) (dc float64, ac []float64, scale float64) {
|
||||
fx := make([]float64, w)
|
||||
for cy := 0; cy < ny; cy++ {
|
||||
for cy := range ny {
|
||||
for cx := 0; cx*ny < nx*(ny-cy); cx++ {
|
||||
f := 0.0
|
||||
for x := range w {
|
||||
|
||||
BIN
core/artwork/thumbhash/testdata/alpha.png
vendored
BIN
core/artwork/thumbhash/testdata/alpha.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 21 KiB |
10
core/artwork/thumbhash/testdata/gen_fixtures.mjs
vendored
10
core/artwork/thumbhash/testdata/gen_fixtures.mjs
vendored
@ -58,10 +58,12 @@ const solid = (rgba, i) => {
|
||||
rgba[i + 2] = 180
|
||||
rgba[i + 3] = 255
|
||||
}
|
||||
const alphaRamp = (rgba, i, x, y, w) => {
|
||||
rgba[i] = 200
|
||||
rgba[i + 1] = 50
|
||||
rgba[i + 2] = 90
|
||||
// RGB must vary with position too: a constant color composited over its own average cancels to a
|
||||
// flat L/P/Q (the bug this fixture exists to catch), so pair a color gradient with the alpha ramp.
|
||||
const alphaRamp = (rgba, i, x, y, w, h) => {
|
||||
rgba[i] = Math.floor((255 * x) / w)
|
||||
rgba[i + 1] = Math.floor((255 * y) / h)
|
||||
rgba[i + 2] = Math.floor((255 * (x + y)) / (w + h))
|
||||
rgba[i + 3] = Math.floor((255 * x) / w)
|
||||
}
|
||||
|
||||
|
||||
2
core/artwork/thumbhash/testdata/golden.json
vendored
2
core/artwork/thumbhash/testdata/golden.json
vendored
@ -1,5 +1,5 @@
|
||||
{
|
||||
"alpha.png": "HCmDBQA3j3mHeHeXiGCI94h3gHd4iIh4eA==",
|
||||
"alpha.png": "JFiKBQw3s4ewiId3eBtPOfuEgHd4iIh4eA==",
|
||||
"landscape.png": "3wcOFJpwd3dxd3eHh3ePgAj4hw==",
|
||||
"portrait.png": "3/cNFBpxB4d3d3d4d3eAjwj3eA==",
|
||||
"solid.png": "HoUBBwB4eHeHd3hweId3h3h4B2+Ih4gA",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user