Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/CoreColor/Models/XYZ.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
125 changes: 108 additions & 17 deletions Tests/CoreColorTests/RGBTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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/cgi-bin/cspace.pl
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))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
}
}