aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Lin <danny@kdrag0n.dev>2021-09-02 22:54:52 -0700
committerDanny Lin <danny@kdrag0n.dev>2021-09-02 22:58:53 -0700
commitba27ad797f935ecdd1d13190332fbfa2f3f8381d (patch)
tree16d0e231e63a42e634be75646a603da1e3f0ad18
parentd62eb68690bad87097e914847a8b823b2ee02af0 (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).
-rw-r--r--src/commonMain/kotlin/dev/kdrag0n/colorkt/data/Illuminants.kt22
-rw-r--r--src/commonMain/kotlin/dev/kdrag0n/colorkt/tristimulus/CieXyz.kt12
-rw-r--r--src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/Srlab2Tests.kt2
-rw-r--r--src/commonTest/kotlin/dev/kdrag0n/colorkt/tests/XyzTests.kt4
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")
}
}