go-colorful icon indicating copy to clipboard operation
go-colorful copied to clipboard

[wip] oklab

Open flowchartsman opened this issue 3 years ago • 1 comments

xyz -> oklab for draft to fix #54

oklab->xyz failing due to fp inaccuracy (I think?) with calculated matrix inverse. Might have to go through linear rgb for now. Port should be easy. Ref: https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab.

flowchartsman avatar Feb 15 '22 07:02 flowchartsman

I tested walking it through linear rgb and also with integrating the matrices from comments at: https://github.com/LeaVerou/color.js/issues/109#issuecomment-938312745, but the precision failures on oklab->xyz still remain. This isn't my normal area of expertise, so I'm still unclear of where to take it from here, but hopefully this is helpful.

//OklabToXyz converts from Oklab space to CIE XYZ-space
func OklabToXyz(l, a, b float64) (x, y, z float64) {
	// l_ := 0.9999999985*l + 0.3963377922*a + 0.2158037581*b
	// m_ := 1.0000000089*l - 0.1055613423*a - 0.0638541748*b
	// s_ := 1.0000000547*l - 0.0894841821*a - 1.2914855379*b

	// ll := l_ * l_ * l_
	// m := m_ * m_ * m_
	// s := s_ * s_ * s_

	// x = 1.2270138511*ll - 0.5577999807*m + 0.2812561490*s
	// y = -0.0405801784*ll + 1.1122568696*m - 0.0716766787*s
	// z = -0.0763812845*ll - 0.4214819784*m + 1.5861632204*s
	// return

	r, g, B := OklabToLinearRgb(l, a, b)
	return LinearRgbToXyz(r, g, B)
}

//OklabToLinearRgb converts from Oklab space to Linear RGB space.
func OklabToLinearRgb(l, a, b float64) (r, g, B float64) {
	ll := 0.9999999984505196*l + 0.39633779217376774*a + 0.2158037580607588*b
	m := 1.0000000088817607*l - 0.10556134232365633*a - 0.0638541747717059*b
	s := 1.0000000546724108*l - 0.08948418209496574*a - 1.2914855378640917*b

	ll = ll * ll * ll
	m = m * m * m
	s = s * s * s

	r = 4.076741661347994*ll - 3.3077115904081933*m + 0.23096992872942793*s
	g = -1.2684380040921763*ll + 2.6097574006633715*m - 0.3413193963102196*s
	B = -0.004196086541837079*ll - 0.7034186144594495*m + 1.7076147009309446*s
	return r, g, B
}
    colors_test.go:466: 1. OklabToXyz => (1.001), want 1 (x)
    colors_test.go:469: 2. OklabToXyz => (1.001), want 1 (y)
    colors_test.go:472: 2. OklabToXyz => (0.001), want 0 (z)
    colors_test.go:466: 3. OklabToXyz => (0.001), want 0 (x)
    colors_test.go:472: 3. OklabToXyz => (1.002), want 1 (z)

flowchartsman avatar Feb 15 '22 16:02 flowchartsman

years later :) I just merged this PR that adds these: https://github.com/lucasb-eyer/go-colorful/pull/66

lucasb-eyer avatar Mar 05 '24 08:03 lucasb-eyer