From b0929c8f2b61fd51a0f4f24baffb2f62d62cee3e Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Sun, 8 Oct 2023 00:31:06 +0530 Subject: [PATCH 1/6] feat: add RGB to HSL color format conversion algorithm --- Conversions/RgbHslConversion.js | 94 +++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Conversions/RgbHslConversion.js diff --git a/Conversions/RgbHslConversion.js b/Conversions/RgbHslConversion.js new file mode 100644 index 0000000000..191080c43d --- /dev/null +++ b/Conversions/RgbHslConversion.js @@ -0,0 +1,94 @@ +/** + * 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) => { + if (colorRgb[0] <= 255 && colorRgb[0] >= 0) { + if (colorRgb[1] <= 255 && colorRgb[1] >= 0) { + if (colorRgb[2] <= 255 && colorRgb[2] >= 0) { + return true + } + } + } + return false +} + +const rgbToHsl = (colorRgb) => { + if (checkRgbFormat(colorRgb) === false) { + return '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 } From 722884d781b2deb839ad42f656f7954cb3eccb16 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Sun, 8 Oct 2023 00:33:19 +0530 Subject: [PATCH 2/6] test: add self-tests for rgb to hsl conversion algorithm --- Conversions/test/RgbHslConversion.test.js | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Conversions/test/RgbHslConversion.test.js diff --git a/Conversions/test/RgbHslConversion.test.js b/Conversions/test/RgbHslConversion.test.js new file mode 100644 index 0000000000..7011b463ce --- /dev/null +++ b/Conversions/test/RgbHslConversion.test.js @@ -0,0 +1,43 @@ +import { rgbToHsl } from '../RgbHslConversion' +describe('RgbHslConversion', () => { + const testCases = [ + [ + [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] + ], + [[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.'] + ] + + test.each(testCases)( + 'Should return the color in HSL format.', + (colorRgb, expected) => { + expect(rgbToHsl(colorRgb)).toEqual(expected) + } + ) +}) From ac3033625cfc168299eeba8faa64a0910819d6b7 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Tue, 10 Oct 2023 02:30:10 +0530 Subject: [PATCH 3/6] fix: change function code to concise format --- Conversions/RgbHslConversion.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Conversions/RgbHslConversion.js b/Conversions/RgbHslConversion.js index 191080c43d..dcc0a43376 100644 --- a/Conversions/RgbHslConversion.js +++ b/Conversions/RgbHslConversion.js @@ -15,16 +15,7 @@ * // result = [193, 66, 28] */ -const checkRgbFormat = (colorRgb) => { - if (colorRgb[0] <= 255 && colorRgb[0] >= 0) { - if (colorRgb[1] <= 255 && colorRgb[1] >= 0) { - if (colorRgb[2] <= 255 && colorRgb[2] >= 0) { - return true - } - } - } - return false -} +const checkRgbFormat = (colorRgb) => colorRgb.every(c => c >= 0 && c <= 255); const rgbToHsl = (colorRgb) => { if (checkRgbFormat(colorRgb) === false) { @@ -91,4 +82,4 @@ const rgbToHsl = (colorRgb) => { return colorHsl } -export { rgbToHsl } +export { rgbToHsl } \ No newline at end of file From 622bf1bde7e76e324bac1ead7856ea3a094b47d0 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Tue, 10 Oct 2023 02:54:51 +0530 Subject: [PATCH 4/6] fix: use throw and segregate the test cases --- Conversions/RgbHslConversion.js | 6 +++--- Conversions/test/RgbHslConversion.test.js | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Conversions/RgbHslConversion.js b/Conversions/RgbHslConversion.js index dcc0a43376..aa531964d3 100644 --- a/Conversions/RgbHslConversion.js +++ b/Conversions/RgbHslConversion.js @@ -18,9 +18,9 @@ const checkRgbFormat = (colorRgb) => colorRgb.every(c => c >= 0 && c <= 255); const rgbToHsl = (colorRgb) => { - if (checkRgbFormat(colorRgb) === false) { - return 'Input is not a valid RGB color.' - } + if (!checkRgbFormat(colorRgb)) { + throw new Error('Input is not a valid RGB color.'); + } let colorHsl = colorRgb diff --git a/Conversions/test/RgbHslConversion.test.js b/Conversions/test/RgbHslConversion.test.js index 7011b463ce..595f4a0f55 100644 --- a/Conversions/test/RgbHslConversion.test.js +++ b/Conversions/test/RgbHslConversion.test.js @@ -1,6 +1,6 @@ import { rgbToHsl } from '../RgbHslConversion' describe('RgbHslConversion', () => { - const testCases = [ + const validTestCases = [ [ [215, 19, 180], [311, 84, 46] @@ -28,16 +28,27 @@ describe('RgbHslConversion', () => { [ [255, 255, 255], [0, 0, 100] - ], + ] + ] + + const errorTestCases = [ [[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.'] ] - test.each(testCases)( + + test.each(validTestCases)( 'Should return the color in HSL format.', (colorRgb, expected) => { expect(rgbToHsl(colorRgb)).toEqual(expected) } ) + + test.each(errorTestCases)( + 'Should return the error message.', + (colorRgb, expected) => { + expect(() => rgbToHsl(colorRgb)).toThrowError(expected) + } + ) }) From df22d5c41bcf168760ac647f5176a9dea621bfe3 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Tue, 10 Oct 2023 03:09:30 +0530 Subject: [PATCH 5/6] chore: clean up the test format --- Conversions/test/RgbHslConversion.test.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Conversions/test/RgbHslConversion.test.js b/Conversions/test/RgbHslConversion.test.js index 595f4a0f55..e32e22a6df 100644 --- a/Conversions/test/RgbHslConversion.test.js +++ b/Conversions/test/RgbHslConversion.test.js @@ -1,6 +1,6 @@ import { rgbToHsl } from '../RgbHslConversion' describe('RgbHslConversion', () => { - const validTestCases = [ + test.each([ [ [215, 19, 180], [311, 84, 46] @@ -29,23 +29,18 @@ describe('RgbHslConversion', () => { [255, 255, 255], [0, 0, 100] ] - ] - - const errorTestCases = [ - [[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.'] - ] - - - test.each(validTestCases)( + ])( 'Should return the color in HSL format.', (colorRgb, expected) => { expect(rgbToHsl(colorRgb)).toEqual(expected) } ) - test.each(errorTestCases)( + 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) From a46ab86791bcf5c3a738c1da4195dd6e317e8d7e Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Tue, 10 Oct 2023 03:12:29 +0530 Subject: [PATCH 6/6] chore: use correct styling --- Conversions/RgbHslConversion.js | 8 ++++---- Conversions/test/RgbHslConversion.test.js | 18 ++++++------------ 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/Conversions/RgbHslConversion.js b/Conversions/RgbHslConversion.js index aa531964d3..7e014f1318 100644 --- a/Conversions/RgbHslConversion.js +++ b/Conversions/RgbHslConversion.js @@ -15,12 +15,12 @@ * // result = [193, 66, 28] */ -const checkRgbFormat = (colorRgb) => colorRgb.every(c => c >= 0 && c <= 255); +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.'); - } + throw new Error('Input is not a valid RGB color.') + } let colorHsl = colorRgb @@ -82,4 +82,4 @@ const rgbToHsl = (colorRgb) => { return colorHsl } -export { rgbToHsl } \ No newline at end of file +export { rgbToHsl } diff --git a/Conversions/test/RgbHslConversion.test.js b/Conversions/test/RgbHslConversion.test.js index e32e22a6df..5dec4835cd 100644 --- a/Conversions/test/RgbHslConversion.test.js +++ b/Conversions/test/RgbHslConversion.test.js @@ -29,21 +29,15 @@ describe('RgbHslConversion', () => { [255, 255, 255], [0, 0, 100] ] - ])( - 'Should return the color in HSL format.', - (colorRgb, expected) => { - expect(rgbToHsl(colorRgb)).toEqual(expected) - } - ) + ])('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) - } - ) + ])('Should return the error message.', (colorRgb, expected) => { + expect(() => rgbToHsl(colorRgb)).toThrowError(expected) + }) })