This repository has been archived by the owner on May 6, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
930 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
github: csqrl | ||
custom: ["https://csqrl.itch.io/colour-utils"] | ||
custom: | ||
- "https://csqrl.itch.io/colour-utils" | ||
- "https://roblox.com/groups/9536808/csqrl#!/store" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
local Assert = require(script.Parent._Util.Assert) | ||
local Saturate = require(script.Parent.Saturate) | ||
|
||
local assertTypeOf = Assert.prepTypeOf("Saturate") | ||
|
||
--[=[ | ||
@function Desaturate | ||
@within ColourUtils | ||
@param colour Color3 -- The colour to desaturate. | ||
@param coefficient number -- The coefficient to desaturate by [0-1]. | ||
@return Color3 -- The desaturated colour. | ||
]=] | ||
return function(colour: Color3, coefficient: number): Color3 | ||
assertTypeOf("colour", "Color3", colour) | ||
assertTypeOf("coefficient", "number", coefficient) | ||
|
||
return Saturate(colour, -coefficient) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
local BasicallyIdentical = require(script.Parent._Util.BasicallyIdentical) | ||
|
||
return function() | ||
local Desaturate = require(script.Parent.Desaturate) | ||
|
||
local TEST_BASE = Color3.fromHex("#00a2ff") | ||
local TEST_RESULT = Color3.fromHex("#80d0ff") | ||
local TEST_AMOUNT = 0.5 | ||
|
||
it("should desaturate a colour", function() | ||
local colour = Desaturate(TEST_BASE, TEST_AMOUNT) | ||
|
||
expect(BasicallyIdentical(TEST_RESULT, colour)).to.equal(true) | ||
end) | ||
|
||
it("throws if argument is not a Color3", function() | ||
expect(function() | ||
Desaturate(nil, TEST_AMOUNT) | ||
end).to.throw() | ||
|
||
expect(function() | ||
Desaturate(true, TEST_AMOUNT) | ||
end).to.throw() | ||
end) | ||
|
||
it("throws if amount is not a number", function() | ||
expect(function() | ||
Desaturate(TEST_BASE, nil) | ||
end).to.throw() | ||
|
||
expect(function() | ||
Desaturate(TEST_BASE, true) | ||
end).to.throw() | ||
end) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
local Assert = require(script.Parent._Util.Assert) | ||
|
||
local round = math.round | ||
local floor = math.floor | ||
local clamp = math.clamp | ||
local min = math.min | ||
local max = math.max | ||
local abs = math.abs | ||
|
||
--[=[ | ||
@interface HSL | ||
@within HSL | ||
.H number | ||
.S number | ||
.L number | ||
]=] | ||
export type HSL = { | ||
H: number, | ||
S: number, | ||
L: number, | ||
} | ||
|
||
--[=[ | ||
@function toHSL | ||
@within HSL | ||
@param colour Color3 -- The colour to convert. | ||
@return HSL -- The HSL representation of the colour. | ||
]=] | ||
local function ToHSL(colour: Color3): HSL | ||
Assert.typeOf("ToHSL", "colour", "Color3", colour) | ||
|
||
local channelMin = min(colour.R, colour.G, colour.B) | ||
local channelMax = max(colour.R, colour.G, colour.B) | ||
local delta = channelMax - channelMin | ||
|
||
local hue = 0 | ||
local lightness = (channelMax + channelMin) / 2 | ||
local saturation = if delta == 0 then 0 else delta / (1 - abs(2 * lightness - 1)) | ||
|
||
if delta == 0 then | ||
hue = 0 | ||
elseif channelMax == colour.R then | ||
hue = ((colour.G - colour.B) / delta) % 6 | ||
elseif channelMax == colour.G then | ||
hue = (colour.B - colour.R) / delta + 2 | ||
else | ||
hue = (colour.R - colour.G) / delta + 4 | ||
end | ||
|
||
hue = round(hue * 60) | ||
|
||
if hue < 0 then | ||
hue += 360 | ||
end | ||
|
||
saturation = clamp(abs(round(saturation * 100)), 0, 100) | ||
lightness = clamp(abs(round(lightness * 100)), 0, 100) | ||
|
||
return { | ||
H = hue, | ||
S = saturation, | ||
L = lightness, | ||
} | ||
end | ||
|
||
--[=[ | ||
@function fromHSL | ||
@within HSL | ||
@param hsl HSL -- The HSL colour to convert. | ||
@return Color3 -- The resulting Color3. | ||
]=] | ||
local function FromHSL(hsl: HSL): Color3 | ||
Assert.typeOf("FromHSL", "hsl", "table", hsl) | ||
|
||
Assert.typeOf("FromHSL", "hsl.H", "number", hsl.H) | ||
Assert.typeOf("FromHSL", "hsl.S", "number", hsl.S) | ||
Assert.typeOf("FromHSL", "hsl.L", "number", hsl.L) | ||
|
||
local saturation = hsl.S / 100 | ||
local lightness = hsl.L / 100 | ||
|
||
local c = (1 - abs(2 * lightness - 1)) * saturation | ||
local x = c * (1 - abs((hsl.H / 60) % 2 - 1)) | ||
local m = lightness - c / 2 | ||
|
||
local red, green, blue = 0, 0, 0 | ||
|
||
if hsl.H >= 0 and hsl.H < 60 then | ||
red, green, blue = c, x, 0 | ||
elseif hsl.H >= 60 and hsl.H < 120 then | ||
red, green, blue = x, c, 0 | ||
elseif hsl.H >= 120 and hsl.H < 180 then | ||
red, green, blue = 0, c, x | ||
elseif hsl.H >= 180 and hsl.H < 240 then | ||
red, green, blue = 0, x, c | ||
elseif hsl.H >= 240 and hsl.H < 300 then | ||
red, green, blue = x, 0, c | ||
elseif hsl.H >= 300 and hsl.H < 360 then | ||
red, green, blue = c, 0, x | ||
end | ||
|
||
red = min(floor((red + m) * 255), 255) | ||
green = min(floor((green + m) * 255), 255) | ||
blue = min(floor((blue + m) * 255), 255) | ||
|
||
return Color3.fromRGB(red, green, blue) | ||
end | ||
|
||
--[=[ | ||
@class HSL | ||
]=] | ||
return { | ||
fromHSL = FromHSL, | ||
toHSL = ToHSL, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) | ||
|
||
return function() | ||
local HSL = require(script.Parent) | ||
|
||
local TEST_COLOR3 = Color3.fromHex("#00a2ff") | ||
local TEST_HSL = { H = 202, S = 100, L = 50 } | ||
|
||
describe("toHSL", function() | ||
it("throws if argument is not a Color3", function() | ||
expect(function() | ||
HSL.toHSL(nil) | ||
end).to.throw() | ||
end) | ||
|
||
it("should convert to HSL", function() | ||
local hsl = HSL.toHSL(TEST_COLOR3) | ||
|
||
expect(hsl.H).to.equal(TEST_HSL.H) | ||
expect(hsl.S).to.equal(TEST_HSL.S) | ||
expect(hsl.L).to.equal(TEST_HSL.L) | ||
end) | ||
end) | ||
|
||
describe("fromHSL", function() | ||
it("throws if argument is not a HSL table", function() | ||
expect(function() | ||
HSL.fromHSL(nil) | ||
end).to.throw() | ||
|
||
expect(function() | ||
HSL.fromHSL({}) | ||
end).to.throw() | ||
end) | ||
|
||
it("should convert to Color3", function() | ||
local color3 = HSL.fromHSL(TEST_HSL) | ||
|
||
expect(BasicallyIdentical(color3, TEST_COLOR3)).to.equal(true) | ||
end) | ||
end) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--[=[ | ||
@interface LAB | ||
@within LAB | ||
.L number | ||
.A number | ||
.B number | ||
]=] | ||
export type LAB = { | ||
L: number, | ||
A: number, | ||
B: number, | ||
} | ||
|
||
return { | ||
Kn = 18, | ||
|
||
Xn = 0.950470, | ||
Yn = 1, | ||
Zn = 1.088830, | ||
|
||
t0 = 0.137931034, | ||
t1 = 0.206896552, | ||
t2 = 0.12841855, | ||
t3 = 0.008856452, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
local Assert = require(script.Parent.Parent._Util.Assert) | ||
local isNaN = require(script.Parent.Parent._Util.isNaN) | ||
|
||
local CONST = require(script.Parent.Constants) | ||
|
||
local function XYZ_RGB(value: number): number | ||
return 255 * (if value <= 0.00304 then 12.92 * value else 1.055 * value ^ (1 / 2.4) - 0.055) | ||
end | ||
|
||
local function LAB_XYZ(value: number): number | ||
return if value > CONST.t1 then value ^ 3 else CONST.t2 * (value - CONST.t0) | ||
end | ||
|
||
--[=[ | ||
@function fromLAB | ||
@within LAB | ||
@param lab LAB -- The colour to convert. | ||
@return Color3 -- The converted colour. | ||
]=] | ||
local function FromLAB(lab: CONST.LAB): Color3 | ||
Assert.typeOf("FromLAB", "lab", "table", lab) | ||
|
||
Assert.typeOf("FromLAB", "lab.L", "number", lab.L) | ||
Assert.typeOf("FromLAB", "lab.A", "number", lab.A) | ||
Assert.typeOf("FromLAB", "lab.B", "number", lab.B) | ||
|
||
local y = (lab.L + 16) / 116 | ||
local x = if isNaN(lab.A) then y else y + lab.A / 500 | ||
local z = if isNaN(lab.B) then y else y - lab.B / 200 | ||
|
||
y = CONST.Yn * LAB_XYZ(y) | ||
x = CONST.Xn * LAB_XYZ(x) | ||
z = CONST.Zn * LAB_XYZ(z) | ||
|
||
local red = XYZ_RGB(3.2404542 * x - 1.5371385 * y - 0.4985314 * z) | ||
local green = XYZ_RGB(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z) | ||
local blue = XYZ_RGB(0.0556434 * x - 0.2040259 * y + 1.0572252 * z) | ||
|
||
return Color3.fromRGB(red, green, blue) | ||
end | ||
|
||
return FromLAB |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
local BasicallyIdentical = require(script.Parent.Parent._Util.BasicallyIdentical) | ||
|
||
return function() | ||
local FromLab = require(script.Parent.FromLAB) | ||
|
||
local TEST_COLOR3 = Color3.fromHex("#00a2ff") | ||
local TEST_LAB = { L = 64.21, A = -1.67, B = -55.7 } | ||
|
||
it("converts a LAB colour to a Color3", function() | ||
local color3 = FromLab(TEST_LAB) | ||
|
||
expect(BasicallyIdentical(color3, TEST_COLOR3)).to.equal(true) | ||
end) | ||
|
||
it("throws if argument is not a LAB table", function() | ||
expect(function() | ||
FromLab(nil) | ||
end).to.throw() | ||
|
||
expect(function() | ||
FromLab({}) | ||
end).to.throw() | ||
end) | ||
end |
Oops, something went wrong.