From d2626669899775b0fc1e091b2cdf8874185d5562 Mon Sep 17 00:00:00 2001 From: yukonblue <77284557+yukonblue@users.noreply.github.com> Date: Sun, 10 Mar 2024 11:32:46 -0400 Subject: [PATCH 1/3] [Doc] Document link to XYZ -> LAB reference --- Sources/CoreColor/Models/XYZ.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/CoreColor/Models/XYZ.swift b/Sources/CoreColor/Models/XYZ.swift index d7b51e8..a9536ef 100644 --- a/Sources/CoreColor/Models/XYZ.swift +++ b/Sources/CoreColor/Models/XYZ.swift @@ -177,6 +177,7 @@ extension XYZ { } public func toLAB() -> LAB { + /// http://www.brucelindbloom.com/index.html?Math.html func f(_ t: Float) -> Float { t > CIE_E ? (cbrt(t)) : ((t * CIE_K + 16) / 116) } From 443d293714f592aec1b9d809e1dda3e82069f1f7 Mon Sep 17 00:00:00 2001 From: yukonblue <77284557+yukonblue@users.noreply.github.com> Date: Sun, 10 Mar 2024 11:39:31 -0400 Subject: [PATCH 2/3] Update links to reference calculator https://davengrace.com/dave/cspace/ --- Tests/CoreColorTests/RGBTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/CoreColorTests/RGBTests.swift b/Tests/CoreColorTests/RGBTests.swift index 2d5d818..ebaaca4 100644 --- a/Tests/CoreColorTests/RGBTests.swift +++ b/Tests/CoreColorTests/RGBTests.swift @@ -34,7 +34,7 @@ class RGBTests: ColorTestCase { } /// Reference calculator: - /// https://davengrace.com/cgi-bin/cspace.pl + /// https://davengrace.com/dave/cspace/ func test_sRGB_to_LinearSRGB() throws { try checkConversion(from: RGB(r: 0.0, g: 0.0, b: 0.0, alpha: 1.0, space: RGBColorSpaces.sRGB)) { (src: RGB) -> RGB in src.toLinearSRGB() @@ -120,7 +120,7 @@ class RGBTests: ColorTestCase { } /// Reference calculator: - /// https://davengrace.com/cgi-bin/cspace.pl + /// https://davengrace.com/dave/cspace/ func test_LinearSRGB_to_XYZ() throws { try check_RGB_to_XYZ(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), xyz: XYZ(x: 0.00, y: 0.00, z: 0.00, alpha: 1.0, space: XYZColorSpaces.XYZ65)) From 71ed58597f0a4a50adf263425a5f519a05b167c3 Mon Sep 17 00:00:00 2001 From: yukonblue <77284557+yukonblue@users.noreply.github.com> Date: Sun, 10 Mar 2024 11:42:17 -0400 Subject: [PATCH 3/3] [Tests][Refine] Refine `RGBTests` --- Tests/CoreColorTests/RGBTests.swift | 123 ++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 16 deletions(-) diff --git a/Tests/CoreColorTests/RGBTests.swift b/Tests/CoreColorTests/RGBTests.swift index ebaaca4..0fc81c2 100644 --- a/Tests/CoreColorTests/RGBTests.swift +++ b/Tests/CoreColorTests/RGBTests.swift @@ -119,22 +119,6 @@ class RGBTests: ColorTestCase { xyz: XYZ(x: 0.95045593, y: 1.0, z: 1.08905775, alpha: 1.0, space: XYZColorSpaces.XYZ65)) } - /// Reference calculator: - /// https://davengrace.com/dave/cspace/ - func test_LinearSRGB_to_XYZ() throws { - try check_RGB_to_XYZ(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), - xyz: XYZ(x: 0.00, y: 0.00, z: 0.00, alpha: 1.0, space: XYZColorSpaces.XYZ65)) - - try check_RGB_to_XYZ(rgb: RGB(r: 0.18, g: 0.18, b: 0.18, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), - xyz: XYZ(x: 0.1710821, y: 0.18000002, z: 0.1960304, alpha: 1.0, space: XYZColorSpaces.XYZ65)) - - try check_RGB_to_XYZ(rgb: RGB(r: 0.40, g: 0.50, b: 0.60, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), - xyz: XYZ(x: 0.45203704, y: 0.4859554, z: 0.637649, alpha: 1.0, space: XYZColorSpaces.XYZ65)) - - try check_RGB_to_XYZ(rgb: RGB(r: 1.00, g: 1.00, b: 1.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), - xyz: XYZ(x: 0.95045593, y: 1.0, z: 1.08905775, alpha: 1.0, space: XYZColorSpaces.XYZ65)) - } - func test_sRGB_to_CMYK() throws { try check_RGB_to_CMYK(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.sRGB), cmyk: CMYK(c: 0.00, m: 0.00, y: 0.00, k: 1.00, alpha: 1.00)) @@ -284,6 +268,20 @@ class RGBTests: ColorTestCase { try assertIsSameCMYK(converted, cmyk) } } + + private func check_RGB_to_LAB(rgb: RGB, lab: LAB) throws { + try checkConversion(from: rgb) { (src: RGB) -> LAB in + src.toLAB() + } check: { converted, _ in + try assertIsSameLAB(converted, lab) + } + + try checkConversion(from: rgb) { (src: RGB) -> LAB in + lab.space.convert(from: rgb) + } check: { converted, _ in + try assertIsSameLAB(converted, lab) + } + } } /// test cases from https://www.w3.org/TR/css-color-5/#colorcontrast @@ -364,3 +362,96 @@ extension RGBTests { } } } + +// MARK: Linear sRGB conversion tests + +/// Reference calculator: +/// https://davengrace.com/dave/cspace/ +extension RGBTests { + + func test_LinearSRGB_to_XYZ() throws { + try check_RGB_to_XYZ(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + xyz: XYZ(x: 0.00, y: 0.00, z: 0.00, alpha: 1.0, space: XYZColorSpaces.XYZ65)) + + try check_RGB_to_XYZ(rgb: RGB(r: 0.18, g: 0.18, b: 0.18, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + xyz: XYZ(x: 0.1710821, y: 0.18000002, z: 0.1960304, alpha: 1.0, space: XYZColorSpaces.XYZ65)) + + try check_RGB_to_XYZ(rgb: RGB(r: 0.40, g: 0.50, b: 0.60, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + xyz: XYZ(x: 0.45203704, y: 0.4859554, z: 0.637649, alpha: 1.0, space: XYZColorSpaces.XYZ65)) + + try check_RGB_to_XYZ(rgb: RGB(r: 1.00, g: 1.00, b: 1.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + xyz: XYZ(x: 0.95045593, y: 1.0, z: 1.08905775, alpha: 1.0, space: XYZColorSpaces.XYZ65)) + } + + func test_LinearSRGB_to_HSV() throws { + try check_RGB_to_HSV(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsv: HSV(h: Float.nan, s: 0.00, v: 0.00, alpha: 1.0)) + + try check_RGB_to_HSV(rgb: RGB(r: 0.18, g: 0.18, b: 0.18, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsv: HSV(h: Float.nan, s: 0.00, v: 0.18, alpha: 1.0)) + + try check_RGB_to_HSV(rgb: RGB(r: 0.40, g: 0.50, b: 0.60, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsv: HSV(h: 210.0, s: 0.33333333, v: 0.6, alpha: 1.0)) + + try check_RGB_to_HSV(rgb: RGB(r: 1.00, g: 1.00, b: 1.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsv: HSV(h: Float.nan, s: 0.00, v: 1.00, alpha: 1.0)) + } + + func test_LinearSRGB_to_HSL() throws { + try check_RGB_to_HSL(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsl: HSL(h: Float.nan, s: 0.00, l: 0.00, alpha: 1.0)) + + try check_RGB_to_HSL(rgb: RGB(r: 0.18, g: 0.18, b: 0.18, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsl: HSL(h: Float.nan, s: 0.00, l: 0.18, alpha: 1.0)) + + try check_RGB_to_HSL(rgb: RGB(r: 0.40, g: 0.50, b: 0.60, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsl: HSL(h: 210.0, s: 0.20, l: 0.50, alpha: 1.0)) + + try check_RGB_to_HSL(rgb: RGB(r: 1.00, g: 1.00, b: 1.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + hsl: HSL(h: Float.nan, s: 0.00, l: 1.00, alpha: 1.0)) + } + + func test_LinearSRGB_to_CMYK() throws { + try check_RGB_to_CMYK(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + cmyk: CMYK(c: 0.00, m: 0.00, y: 0.00, k: 1.00, alpha: 1.00)) + + try check_RGB_to_CMYK(rgb: RGB(r: 0.18, g: 0.18, b: 0.18, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + cmyk: CMYK(c: 0.00, m: 0.00, y: 0.00, k: 0.82, alpha: 1.00)) + + try check_RGB_to_CMYK(rgb: RGB(r: 0.40, g: 0.50, b: 0.60, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + cmyk: CMYK(c: 0.33333333, m: 0.16666667, y: 0.0, k: 0.4, alpha: 1.00)) + + try check_RGB_to_CMYK(rgb: RGB(r: 1.00, g: 1.00, b: 1.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + cmyk: CMYK(c: 0.00, m: 0.00, y: 0.00, k: 0.00, alpha: 1.00)) + } + + /// Reference calculator: + /// https://www.colorspaceconverter.com/converter/srgb-linear-to-luv + func test_LinearSRGB_to_LUV() throws { + try check_RGB_to_LUV(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + luv: LUV(l: 0.00, u: 0.00, v: 0.00, alpha: 1.00, space: LUVColorSpaces.LUV65)) + + try check_RGB_to_LUV(rgb: RGB(r: 0.18, g: 0.18, b: 0.18, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + luv: LUV(l: 49.49611, u: 0.00, v: 0.00, alpha: 1.00, space: LUVColorSpaces.LUV65)) + + try check_RGB_to_LUV(rgb: RGB(r: 0.40, g: 0.50, b: 0.60, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + luv: LUV(l: 75.19901, u: -10.304651, v: -14.957002, alpha: 1.00, space: LUVColorSpaces.LUV65)) + + try check_RGB_to_LUV(rgb: RGB(r: 1.00, g: 1.00, b: 1.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + luv: LUV(l: 100.00, u: 0.00, v: 0.00, alpha: 1.00, space: LUVColorSpaces.LUV65)) + } + + func test_LinearSRGB_to_LAB() throws { + try check_RGB_to_LAB(rgb: RGB(r: 0.00, g: 0.00, b: 0.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + lab: LAB(l: 0.00, a: 0.00, b: 0.00, alpha: 1.00, space: LABColorSpaces.LAB65)) + + try check_RGB_to_LAB(rgb: RGB(r: 0.18, g: 0.18, b: 0.18, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + lab: LAB(l: 49.49611, a: 0.00, b: 0.00, alpha: 1.00, space: LABColorSpaces.LAB65)) + + try check_RGB_to_LAB(rgb: RGB(r: 0.40, g: 0.50, b: 0.60, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + lab: LAB(l: 75.19901, a: -2.8122663, b: -10.077393, alpha: 1.00, space: LABColorSpaces.LAB65)) + + try check_RGB_to_LAB(rgb: RGB(r: 1.00, g: 1.00, b: 1.00, alpha: 1.0, space: RGBColorSpaces.LinearSRGB), + lab: LAB(l: 100.00, a: 0.00, b: 0.00, alpha: 1.00, space: LABColorSpaces.LAB65)) + } +}