diff --git a/modules/color.lua b/modules/color.lua index e26e361..04ec3d1 100644 --- a/modules/color.lua +++ b/modules/color.lua @@ -21,7 +21,7 @@ local function hsv_to_color(hsv) local i local f, q, p, t local h, s, v - local a = hsv[4] or 255 + local a = hsv[4] or 1 s = hsv[2] v = hsv[3] @@ -29,10 +29,10 @@ local function hsv_to_color(hsv) return new(v, v, v, a) end - h = hsv[1] / 60 + h = hsv[1] / 60 -- sector 0 to 5 i = math.floor(h) - f = h - i + f = h - i -- factorial part of h p = v * (1-s) q = v * (1-s*f) t = v * (1-s*(1-f)) @@ -52,7 +52,7 @@ local function color_to_hsv(c) local r = c[1] local g = c[2] local b = c[3] - local a = c[4] or 255 + local a = c[4] or 1 local h, s, v local min = math.min(r, g, b) @@ -72,7 +72,7 @@ local function color_to_hsv(c) -- r = g = b = 0 s = 0, v is undefined s = 0 h = -1 - return { h, s, v, 255 } + return { h, s, v, 1 } end if r == max then @@ -94,12 +94,12 @@ end --- The public constructor. -- @param x Can be of three types:
--- number red component 0-255 +-- number red component 0-1 -- table {r, g, b, a} -- nil for {0,0,0,0} --- @tparam number g Green component 0-255 --- @tparam number b Blue component 0-255 --- @tparam number a Alpha component 0-255 +-- @tparam number g Green component 0-1 +-- @tparam number b Blue component 0-1 +-- @tparam number a Alpha component 0-1 -- @treturn color out function color.new(r, g, b, a) -- number, number, number, number @@ -126,13 +126,13 @@ function color.new(r, g, b, a) end --- Convert hue,saturation,value table to color object. --- @tparam table hsva {hue 0-359, saturation 0-1, value 0-1, alpha 0-255} +-- @tparam table hsva {hue 0-359, saturation 0-1, value 0-1, alpha 0-1} -- @treturn color out color.hsv_to_color_table = hsv_to_color --- Convert color to hue,saturation,value table -- @tparam color in --- @treturn table hsva {hue 0-359, saturation 0-1, value 0-1, alpha 0-255} +-- @treturn table hsva {hue 0-359, saturation 0-1, value 0-1, alpha 0-1} color.color_to_hsv_table = color_to_hsv --- Convert hue,saturation,value to color object. @@ -148,7 +148,7 @@ end -- @tparam number h hue 0-359 -- @tparam number s saturation 0-1 -- @tparam number v value 0-1 --- @tparam number a alpha 0-255 +-- @tparam number a alpha 0-1 -- @treturn color out function color.from_hsva(h, s, v, a) return hsv_to_color { h, s, v, a } @@ -158,18 +158,18 @@ end -- @tparam color to invert -- @treturn color out function color.invert(c) - return new(255 - c[1], 255 - c[2], 255 - c[3], c[4]) + return new(1 - c[1], 1 - c[2], 1 - c[3], c[4]) end --- Lighten a color by a component-wise fixed amount (alpha unchanged) -- @tparam color to lighten --- @tparam number amount to increase each component by, 0-255 scale +-- @tparam number amount to increase each component by, 0-1 scale -- @treturn color out function color.lighten(c, v) return new( - utils.clamp(c[1] + v, 0, 255), - utils.clamp(c[2] + v, 0, 255), - utils.clamp(c[3] + v, 0, 255), + utils.clamp(c[1] + v, 0, 1), + utils.clamp(c[2] + v, 0, 1), + utils.clamp(c[3] + v, 0, 1), c[4] ) end @@ -178,15 +178,35 @@ function color.lerp(a, b, s) return a + s * (b - a) end +--- Unpack a color into individual components in 0-1. +-- @tparam color to unpack +-- @treturn number r in 0-1 +-- @treturn number g in 0-1 +-- @treturn number b in 0-1 +-- @treturn number a in 0-1 +function color.unpack(c) + return c[1], c[2], c[3], c[4] +end + +--- Unpack a color into individual components in 0-255. +-- @tparam color to unpack +-- @treturn number r in 0-255 +-- @treturn number g in 0-255 +-- @treturn number b in 0-255 +-- @treturn number a in 0-255 +function color.as_255(c) + return c[1] * 255, c[2] * 255, c[3] * 255, c[4] * 255 +end + --- Darken a color by a component-wise fixed amount (alpha unchanged) -- @tparam color to darken --- @tparam number amount to decrease each component by, 0-255 scale +-- @tparam number amount to decrease each component by, 0-1 scale -- @treturn color out function color.darken(c, v) return new( - utils.clamp(c[1] - v, 0, 255), - utils.clamp(c[2] - v, 0, 255), - utils.clamp(c[3] - v, 0, 255), + utils.clamp(c[1] - v, 0, 1), + utils.clamp(c[2] - v, 0, 1), + utils.clamp(c[3] - v, 0, 1), c[4] ) end @@ -207,7 +227,7 @@ end -- directly set alpha channel -- @tparam color to alter --- @tparam number new alpha 0-255 +-- @tparam number new alpha 0-1 -- @treturn color out function color.alpha(c, v) local t = color.new() @@ -280,13 +300,13 @@ function color.gamma_to_linear(r, g, b, a) if type(r) == "table" then local c = {} for i = 1, 3 do - c[i] = convert(r[i] / 255) * 255 + c[i] = convert(r[i]) end - c[4] = convert(r[4] / 255) * 255 + c[4] = convert(r[4]) return c else - return convert(r / 255) * 255, convert(g / 255) * 255, convert(b / 255) * 255, a or 255 + return convert(r), convert(g), convert(b), a or 1 end end @@ -307,13 +327,13 @@ function color.linear_to_gamma(r, g, b, a) if type(r) == "table" then local c = {} for i = 1, 3 do - c[i] = convert(r[i] / 255) * 255 + c[i] = convert(r[i]) end - c[4] = convert(r[4] / 255) * 255 + c[4] = convert(r[4]) return c else - return convert(r / 255) * 255, convert(g / 255) * 255, convert(b / 255) * 255, a or 255 + return convert(r), convert(g), convert(b), a or 1 end end diff --git a/spec/color_spec.lua b/spec/color_spec.lua index 5f7aa16..5309ced 100644 --- a/spec/color_spec.lua +++ b/spec/color_spec.lua @@ -65,28 +65,66 @@ describe("color:", function() end end) + it("unpack", function() + local c = color(122/255, 20/255, 122/255, 255/255) + local r, g, b, a = c:unpack() + assert_is_float_equal(c[1], r) + assert_is_float_equal(c[2], g) + assert_is_float_equal(c[3], b) + assert_is_float_equal(c[4], a) + r, g, b, a = c:as_255() + assert_is_float_equal(122, r) + assert_is_float_equal(20, g) + assert_is_float_equal(122, b) + assert_is_float_equal(255, a) + end) + + it("set hsv", function() + -- hsv value conversion values from http://colorizer.org/ + local c = color(122/255, 20/255, 122/255, 1) + local hsv = c:color_to_hsv_table() + assert_is_approx_equal(hsv[1], 300) + assert_is_approx_equal(hsv[2], 0.8361) + assert_is_approx_equal(hsv[3], 0.4784) + local r = c:hue(200) + assert_is_approx_equal(r[1], 20/255) + assert_is_approx_equal(r[2], 88/255) + assert_is_approx_equal(r[3], 122/255) + r = c:saturation(0.2) + assert_is_approx_equal(r[1], 122/255) + assert_is_approx_equal(r[2], 97.6/255) + assert_is_approx_equal(r[3], 122/255) + r = c:value(0.2) + assert_is_approx_equal(r[1], 51/255) + assert_is_approx_equal(r[2], 8.36/255) + assert_is_approx_equal(r[3], 51/255) + end) + it("lighten a color", function() local c = color(0, 0, 0, 0) - local r = c:lighten(10) - assert.is.equal(r[1], 10) + local r = c:lighten(0.1) + assert.is.equal(r[1], 0.1) r = c:lighten(1000) - assert.is.equal(r[1], 255) + assert.is.equal(r[1], 1) end) it("darken a color", function() - local c = color(255, 255, 255, 255) - local r = c:darken(10) - assert.is.equal(r[1], 245) + local c = color(1, 1, 1, 1) + local r = c:darken(0.04) + assert.is.equal(r[1], 0.96) r = c:darken(1000) assert.is.equal(r[1], 0) end) it("modify alpha", function() - local c = color(255, 255, 255, 255) - local r = c:alpha(10) - assert.is.equal(r[4], 10) + local c = color(1, 1, 1, 1) + local r = c:alpha(0.1) + assert.is.equal(r[4], 0.1) r = c:opacity(0.5) - assert.is.equal(r[4], 255/2) + assert.is.equal(r[4], 0.5) + r = c:opacity(0.5) + :opacity(0.5) + assert.is.equal(r[4], 0.25) end) end) @@ -95,9 +133,6 @@ end) invert(c) lerp(a, b, s) multiply(c, v) -hue(color, hue) -saturation(color, percent) -value(color, percent) gamma_to_linear(r, g, b, a) linear_to_gamma(r, g, b, a) to_string(a)