Skip to content

Commit

Permalink
Improve type stability in conversion methods
Browse files Browse the repository at this point in the history
This also optimizes conversion methods and changes the results slightly..
  • Loading branch information
kimikage committed Mar 2, 2021
1 parent cf7b34b commit 518d4ea
Showing 1 changed file with 36 additions and 22 deletions.
58 changes: 36 additions & 22 deletions src/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,20 +316,25 @@ function cnvt(::Type{XYZ{T}}, c::xyY) where T
end


const xyz_epsilon = 216 / 24389
const xyz_kappa = 24389 / 27
const xyz_epsilon = 216 / 24389 # (6/29)^3
const xyz_kappa = 24389 / 27 # (29/6)^3*8
const xyz_kappa_inv = 27 / 24389

function cnvt(::Type{XYZ{T}}, c::Lab, wp::XYZ = WP_DEFAULT) where T
fy = (c.l + 16) / 116
fx = c.a / 500 + fy
fx = fy + c.a / 500
fz = fy - c.b / 200

fx3 = fx^3
fy3 = fy^3
fz3 = fz^3

x = fx3 > xyz_epsilon ? fx3 : (116fx - 16) / xyz_kappa
y = c.l > xyz_kappa * xyz_epsilon ? ((c. l+ 16) / 116)^3 : c.l / xyz_kappa
z = fz3 > xyz_epsilon ? fz3 : (116fz - 16) / xyz_kappa
epsilon = oftype(fx3, xyz_epsilon)
kappa_inv = oftype(fx3, xyz_kappa_inv)

x = fx3 > epsilon ? fx3 : muladd(116, fx, -16) * kappa_inv
y = fy3 > epsilon ? fy3 : c.l * kappa_inv
z = fz3 > epsilon ? fz3 : muladd(116, fz, -16) * kappa_inv

XYZ{T}(x*wp.x, y*wp.y, z*wp.z)
end
Expand All @@ -345,15 +350,18 @@ end


function cnvt(::Type{XYZ{T}}, c::Luv, wp::XYZ = WP_DEFAULT) where T
(u_wp, v_wp) = xyz_to_uv(wp)
c.l == zero(c.l) && return XYZ{T}(zero(T), zero(T), zero(T))

a = (52 * (c.l==0 ? zero(T) : c.l / (c.u + 13 * c.l * u_wp)) - 1) / 3
y = c.l > xyz_kappa * xyz_epsilon ? wp.y * ((c.l + 16) / 116)^3 : wp.y * c.l / xyz_kappa
b = -5y
d = y * (39 * (c.l==0 ? zero(T) : c.l / (c.v + 13 * c.l * v_wp)) - 5)
x = d==b ? zero(T) : (d - b) / (a + 1/3)
z = a * x + b + zero(T)
u_wp, v_wp = xyz_to_uv(wp)

ls = c.l * oftype(u_wp, xyz_kappa_inv)
y = c.l > 8 ? wp.y * ((c.l + 16) / 116)^3 : wp.y * ls

u = c.u / (13c.l) + u_wp
v = c.v / (13c.l) + v_wp
v4 = 4v
x = y * 9u / v4
z = y * (12 - 3u - 20v) / v4
XYZ{T}(x, y, z)
end

Expand Down Expand Up @@ -407,12 +415,16 @@ cnvt(::Type{xyY{T}}, c::Color3) where {T} = cnvt(xyY{T}, convert(XYZ{T}, c))
# Everything to Lab
# -----------------

function fxyz2lab(v)
v > xyz_epsilon ? cbrt(v) : (xyz_kappa * v + 16) / 116
@inline function fxyz2lab(v)
ka = oftype(v, 841 / 108) # (29/6)^2 / 3 = xyz_kappa / 116
kb = oftype(v, 16 / 116) # 4/29
v > oftype(v, xyz_epsilon) ? cbrt(v) : muladd(ka, v, kb)
end
@noinline map_fxyz2lab(c) = mapc(fxyz2lab, c)

function cnvt(::Type{Lab{T}}, c::XYZ, wp::XYZ = WP_DEFAULT) where T
fx, fy, fz = fxyz2lab(c.x / wp.x), fxyz2lab(c.y / wp.y), fxyz2lab(c.z / wp.z)
Lab{T}(116fy - 16, 500(fx - fy), 200(fy - fz))
f = map_fxyz2lab(mapc((x, y)->x / y, c, wp))
Lab{T}(muladd(116, f.y, -16), 500(f.x - f.y), 200(f.y - f.z))
end


Expand Down Expand Up @@ -497,10 +509,12 @@ function cnvt(::Type{Luv{T}}, c::XYZ, wp::XYZ = WP_DEFAULT) where T
(u_, v_) = xyz_to_uv(c)

y = c.y / wp.y
epsilon = oftype(y, xyz_epsilon)
kappa = oftype(y, xyz_kappa)

l = y > xyz_epsilon ? 116 * cbrt(y) - 16 : xyz_kappa * y
u = 13 * l * (u_ - u_wp) + zero(T)
v = 13 * l * (v_ - v_wp) + zero(T)
l = y > epsilon ? 116 * cbrt(y) - 16 : kappa * y
u = 13 * l * (u_ - u_wp)
v = 13 * l * (v_ - v_wp)

Luv{T}(l, u, v)
end
Expand Down Expand Up @@ -562,8 +576,8 @@ function cnvt(::Type{DIN99{T}}, c::Lab) where T
cc = log(1+0.045*g)/(0.045*kch*ke)

# DIN99 chromaticities
a99 = g > 0 ? cc * ee / g : zero(T)
b99 = g > 0 ? cc * f / g : zero(T)
a99 = g > 0 ? convert(T, cc / g * ee) : zero(T)
b99 = g > 0 ? convert(T, cc / g * f ) : zero(T)

DIN99{T}(l99, a99, b99)

Expand Down

0 comments on commit 518d4ea

Please sign in to comment.