diff options
| author | Danny Lin <danny@kdrag0n.dev> | 2021-09-02 22:54:52 -0700 |
|---|---|---|
| committer | Danny Lin <danny@kdrag0n.dev> | 2021-09-02 22:58:53 -0700 |
| commit | ba27ad797f935ecdd1d13190332fbfa2f3f8381d (patch) | |
| tree | 16d0e231e63a42e634be75646a603da1e3f0ad18 | |
| parent | d62eb68690bad87097e914847a8b823b2ee02af0 (diff) | |
illuminants: Use ASTM D65 by default
While agreement with the sRGB standard may be nice, most of our color
spaces and color appearance models (ZCAM and Oklab) consider "white" to
be ASTM D65 instead of the rounded sRGB chromaticities, and these color
models are more sensitive than converting to 8-bpc sRGB.
Tested by converting pure white to each color space and checking for
minimum chroma:
sRGB D65:
Oklab(L=0.9999988020105659, a=-2.1755553165359043E-5, b=-1.2315505659377113E-4)
Iz=0.9949976123811411 az=-2.362580742811815E-4 bz=-1.7212518608999972E-4 chroma=2.9230969424493827E-4
Zcam(brightness=865.6392743493063, lightness=100.0, colorfulness=0.3659209364945614, chroma=0.04227175768678253, hue=216.075109084568, saturation=4.495963941600806, vividness=42.000072326903116, blackness=19.99994281917249, whiteness=99.95772824231322, viewingConditions=ViewingConditions(surroundFactor=0.69, adaptingLuminance=10000.0, backgroundLuminance=1000.0, referenceWhite=CieXyzAbs(x=9504.559270516716, y=10000.0, z=10890.577507598784)))
ASTM D65:
Oklab(L=0.9999998095202896, a=-1.0091754968077904E-5, b=-8.610878004511324E-5)
Iz=0.9949945266665536 az=-2.2566494047437935E-4 bz=-1.3882055770908508E-4 chroma=2.649449237142818E-4
Zcam(brightness=865.6358715247319, lightness=100.0, colorfulness=0.33927763142554684, chroma=0.039194035573865825, hue=211.59826124866282, saturation=4.329200076703247, vividness=42.00006217836164, blackness=19.999950842497512, whiteness=99.96080596442613, viewingConditions=ViewingConditions(surroundFactor=0.69, adaptingLuminance=10000.0, backgroundLuminance=1000.0, referenceWhite=CieXyzAbs(x=9504.7, y=10000.0, z=10888.3)))
Raw CIE D65:
Oklab(L=0.9999998468817637, a=-9.776905608882558E-6, b=-8.59019382591919E-5)
Iz=0.9949945226634265 az=-2.2544728356810317E-4 bz=-1.386176506734671E-4 chroma=2.646532273494281E-4
Zcam(brightness=865.6358671102167, lightness=100.0, colorfulness=0.33899828752821487, chroma=0.03916176540372628, hue=211.58553550809668, saturation=4.327417499469805, vividness=42.00006207601551, blackness=19.99995092341122, whiteness=99.96083823459627, viewingConditions=ViewingConditions(surroundFactor=0.69, adaptingLuminance=10000.0, backgroundLuminance=1000.0, referenceWhite=CieXyzAbs(x=9504.705586542832, y=10000.0, z=10888.28736395884)))
MATLAB D65:
Oklab(L=0.9999951917581503, a=-4.595680552083037E-5, b=-8.142179944437E-5)
Iz=0.9949921589631224 az=-2.4802709743521056E-4 bz=-1.3714120747843062E-4 chroma=2.834169223084207E-4
Zcam(brightness=865.6332605011636, lightness=100.0, colorfulness=0.3559767253054511, chroma=0.0411232725853621, hue=208.93944875904936, saturation=4.434467746562692, vividness=42.00006845018307, blackness=19.999945884064758, whiteness=99.95887672741463, viewingConditions=ViewingConditions(surroundFactor=0.69, adaptingLuminance=10000.0, backgroundLuminance=1000.0, referenceWhite=CieXyzAbs(x=9504.0, y=10000.0, z=10888.0)))
Raw CIE D65 performs best in these tests, but ASTM D65 is very close and
matches the white point used by many other color libraries (and most
likely the color space/CAM authors as well).
4 files changed, 20 insertions, 20 deletions
diff --git a/src/commonMain/kotlin/dev/kdrag0n/colorkt/data/Illuminants.kt b/src/commonMain/kotlin/dev/kdrag0n/colorkt/data/Illuminants.kt index e499b14..6ff78ac 100644 --- a/src/commonMain/kotlin/dev/kdrag0n/colorkt/data/Illuminants.kt +++ b/src/commonMain/kotlin/dev/kdrag0n/colorkt/data/Illuminants.kt @@ -8,29 +8,29 @@ import kotlin.jvm.JvmField */ public object Illuminants { /** - * sRGB variant of CIE Standard Illuminant D65. ~6500K color temperature; approximates average daylight in Europe. - * This uses the white point chromaticities defined in the sRGB specification. + * ASTM variant of CIE Standard Illuminant D65. ~6500K color temperature; approximates average daylight in Europe. + * This uses the XYZ values defined in the ASTM E‑308 document. * - * @see <a href="https://en.wikipedia.org/wiki/SRGB">Wikipedia: sRGB</a> + * @see <a href="https://en.wikipedia.org/wiki/Illuminant_D65">Wikipedia: Illuminant D65</a> */ @JvmField public val D65: CieXyz = CieXyz( - x = xyToX(0.3127, 0.3290), + x = 0.95047, y = 1.0, - z = xyToZ(0.3127, 0.3290), + z = 1.08883, ) /** - * ASTM variant of CIE Standard Illuminant D65. ~6500K color temperature; approximates average daylight in Europe. - * This uses the XYZ values defined in the ASTM E‑308 document. + * sRGB variant of CIE Standard Illuminant D65. ~6500K color temperature; approximates average daylight in Europe. + * This uses the white point chromaticities defined in the sRGB specification. * - * @see <a href="https://en.wikipedia.org/wiki/Illuminant_D65">Wikipedia: Illuminant D65</a> + * @see <a href="https://en.wikipedia.org/wiki/SRGB">Wikipedia: sRGB</a> */ @JvmField - public val D65_ASTM: CieXyz = CieXyz( - x = 0.95047, + public val D65_SRGB: CieXyz = CieXyz( + x = xyToX(0.3127, 0.3290), y = 1.0, - z = 1.08883, + z = xyToZ(0.3127, 0.3290), ) /** diff --git a/src/commonMain/kotlin/dev/kdrag0n/colorkt/tristimulus/CieXyz.kt b/src/commonMain/kotlin/dev/kdrag0n/colorkt/tristimulus/CieXyz.kt index 5fa187e..e578186 100644 --- a/src/commonMain/kotlin/dev/kdrag0n/colorkt/tristimulus/CieXyz.kt +++ b/src/commonMain/kotlin/dev/kdrag0n/colorkt/tristimulus/CieXyz.kt @@ -40,9 +40,9 @@ public data class CieXyz( public fun toLinearSrgb(): LinearSrgb { // See LinearSrgb.toXyz for info about the source of this matrix. return LinearSrgb( - r = 3.2409699419045226 * x + -1.537383177570094 * y + -0.49861076029300355 * z, - g = -0.9692436362808796 * x + 1.8759675015077202 * y + 0.04155505740717562 * z, - b = 0.055630079696993635 * x + -0.2039769588889765 * y + 1.0569715142428784 * z, + r = 3.2404541621141045 * x + -1.5371385127977162 * y + -0.4985314095560159 * z, + g = -0.969266030505187 * x + 1.8760108454466944 * y + 0.04155601753034983 * z, + b = 0.05564343095911474 * x + -0.2040259135167538 * y + 1.0572251882231787 * z, ) } @@ -69,9 +69,9 @@ public data class CieXyz( // Using D65 xy chromaticities from the sRGB spec: x = 0.3127, y = 0.3290 // Always keep in sync with Illuminants.D65. return CieXyz( - x = 0.4123907992659593 * r + 0.357584339383878 * g + 0.18048078840183432 * b, - y = 0.21263900587151024 * r + 0.715168678767756 * g + 0.07219231536073373 * b, - z = 0.01933081871559182 * r + 0.11919477979462598 * g + 0.9505321522496608 * b, + x = 0.41245643908969226 * r + 0.357576077643909 * g + 0.18043748326639897 * b, + y = 0.21267285140562256 * r + 0.715152155287818 * g + 0.07217499330655959 * b, + z = 0.019333895582329303 * r + 0.11919202588130297 * g + 0.950304078536368 * b, ) } } diff --git a/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/Srlab2Tests.kt b/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/Srlab2Tests.kt index 248fa33..cab28b0 100644 --- a/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/Srlab2Tests.kt +++ b/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/Srlab2Tests.kt @@ -21,7 +21,7 @@ class Srlab2Tests { ) @Test fun colorioSample3() = xyzSrlabTest( - xyz = Illuminants.D65_ASTM, + xyz = Illuminants.D65, srlab2 = Srlab2(99.99977248346777, -0.004069281557519844, -0.00039226988315022027), ) @Test diff --git a/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/XyzTests.kt b/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/XyzTests.kt index ad5c7c1..70e1770 100644 --- a/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/XyzTests.kt +++ b/src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/XyzTests.kt @@ -31,7 +31,7 @@ class XyzTests { println("max = $maxChroma") println("avg = $avgChroma") - assertTrue(maxChroma <= 5.978733960281817e-14, "Max neutral chroma = $maxChroma") - assertTrue(avgChroma <= 1.1564648410521476e-14, "Average neutral chroma = $avgChroma") + assertTrue(maxChroma <= 7.108895957933346e-14, "Max neutral chroma = $maxChroma") + assertTrue(avgChroma <= 1.3133161994387564e-14, "Average neutral chroma = $avgChroma") } } |
