mirror of
https://github.com/TheAlgorithms/JavaScript.git
synced 2025-07-05 00:01:37 +08:00
feat: add RGB to HSL color format conversion algorithm (#1475)
* feat: add RGB to HSL color format conversion algorithm * test: add self-tests for rgb to hsl conversion algorithm * fix: change function code to concise format * fix: use throw and segregate the test cases * chore: clean up the test format * chore: use correct styling
This commit is contained in:
85
Conversions/RgbHslConversion.js
Normal file
85
Conversions/RgbHslConversion.js
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Given a color in RGB format, convert it to HSL format.
|
||||
*
|
||||
* For more info: https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
|
||||
*
|
||||
* @param {number[]} colorRgb - One dimensional array of integers (RGB color format).
|
||||
* @returns {number[]} - One dimensional array of integers (HSL color format).
|
||||
*
|
||||
* @example
|
||||
* const colorRgb = [24, 98, 118]
|
||||
*
|
||||
* const result = rgbToHsl(colorRgb)
|
||||
*
|
||||
* // The function returns the corresponding color in HSL format:
|
||||
* // result = [193, 66, 28]
|
||||
*/
|
||||
|
||||
const checkRgbFormat = (colorRgb) => colorRgb.every((c) => c >= 0 && c <= 255)
|
||||
|
||||
const rgbToHsl = (colorRgb) => {
|
||||
if (!checkRgbFormat(colorRgb)) {
|
||||
throw new Error('Input is not a valid RGB color.')
|
||||
}
|
||||
|
||||
let colorHsl = colorRgb
|
||||
|
||||
let red = Math.round(colorRgb[0])
|
||||
let green = Math.round(colorRgb[1])
|
||||
let blue = Math.round(colorRgb[2])
|
||||
|
||||
const limit = 255
|
||||
|
||||
colorHsl[0] = red / limit
|
||||
colorHsl[1] = green / limit
|
||||
colorHsl[2] = blue / limit
|
||||
|
||||
let minValue = Math.min(...colorHsl)
|
||||
let maxValue = Math.max(...colorHsl)
|
||||
|
||||
let channel = 0
|
||||
|
||||
if (maxValue === colorHsl[1]) {
|
||||
channel = 1
|
||||
} else if (maxValue === colorHsl[2]) {
|
||||
channel = 2
|
||||
}
|
||||
|
||||
let luminance = (minValue + maxValue) / 2
|
||||
|
||||
let saturation = 0
|
||||
|
||||
if (minValue !== maxValue) {
|
||||
if (luminance <= 0.5) {
|
||||
saturation = (maxValue - minValue) / (maxValue + minValue)
|
||||
} else {
|
||||
saturation = (maxValue - minValue) / (2 - maxValue - minValue)
|
||||
}
|
||||
}
|
||||
|
||||
let hue = 0
|
||||
|
||||
if (saturation !== 0) {
|
||||
if (channel === 0) {
|
||||
hue = (colorHsl[1] - colorHsl[2]) / (maxValue - minValue)
|
||||
} else if (channel === 1) {
|
||||
hue = 2 + (colorHsl[2] - colorHsl[0]) / (maxValue - minValue)
|
||||
} else {
|
||||
hue = 4 + (colorHsl[0] - colorHsl[1]) / (maxValue - minValue)
|
||||
}
|
||||
}
|
||||
|
||||
hue *= 60
|
||||
|
||||
if (hue < 0) {
|
||||
hue += 360
|
||||
}
|
||||
|
||||
colorHsl[0] = Math.round(hue)
|
||||
colorHsl[1] = Math.round(saturation * 100)
|
||||
colorHsl[2] = Math.round(luminance * 100)
|
||||
|
||||
return colorHsl
|
||||
}
|
||||
|
||||
export { rgbToHsl }
|
43
Conversions/test/RgbHslConversion.test.js
Normal file
43
Conversions/test/RgbHslConversion.test.js
Normal file
@ -0,0 +1,43 @@
|
||||
import { rgbToHsl } from '../RgbHslConversion'
|
||||
describe('RgbHslConversion', () => {
|
||||
test.each([
|
||||
[
|
||||
[215, 19, 180],
|
||||
[311, 84, 46]
|
||||
],
|
||||
[
|
||||
[21, 190, 18],
|
||||
[119, 83, 41]
|
||||
],
|
||||
[
|
||||
[80, 100, 160],
|
||||
[225, 33, 47]
|
||||
],
|
||||
[
|
||||
[80, 1, 16],
|
||||
[349, 98, 16]
|
||||
],
|
||||
[
|
||||
[8, 20, 0],
|
||||
[96, 100, 4]
|
||||
],
|
||||
[
|
||||
[0, 0, 0],
|
||||
[0, 0, 0]
|
||||
],
|
||||
[
|
||||
[255, 255, 255],
|
||||
[0, 0, 100]
|
||||
]
|
||||
])('Should return the color in HSL format.', (colorRgb, expected) => {
|
||||
expect(rgbToHsl(colorRgb)).toEqual(expected)
|
||||
})
|
||||
|
||||
test.each([
|
||||
[[256, 180, 9], 'Input is not a valid RGB color.'],
|
||||
[[-90, 46, 8], 'Input is not a valid RGB color.'],
|
||||
[[1, 39, 900], 'Input is not a valid RGB color.']
|
||||
])('Should return the error message.', (colorRgb, expected) => {
|
||||
expect(() => rgbToHsl(colorRgb)).toThrowError(expected)
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user