From f9592029b4831bd88d29ae74211eef0bf3903a5d Mon Sep 17 00:00:00 2001 From: regorxxx Date: Tue, 20 Feb 2024 18:14:51 +0100 Subject: [PATCH] * added chroma.stdDeviation() to retrieve the variance in an array of colors as an RGBA component. See [Issue 328] (https://github.com/gka/chroma.js/issues/328#issuecomment-1951628498) Signed-off-by: regorxxx --- src/utils/deviation.js | 19 +++++++++++++++++++ test/stddev.test.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/utils/deviation.js create mode 100644 test/stddev.test.js diff --git a/src/utils/deviation.js b/src/utils/deviation.js new file mode 100644 index 00000000..8b33047d --- /dev/null +++ b/src/utils/deviation.js @@ -0,0 +1,19 @@ +const Color = require('../Color'); + +module.exports = (colors) => { + colors = [...colors].map((color) => new Color(color).rgba()) + const colorNum = colors.length; + const results = Array.from(Array(colorNum), () => new Array(colorNum)); + const mean = [0, 0, 0, 0]; + for (let i = 0; i < colorNum; i++) { + colors[i].forEach((c, j) => mean[j] += (j === 3 ? c * 255 : c)); + } + mean.forEach((c, i) => mean[i] /= colorNum); + let stdDev = 0; + for (let i = 0; i < colorNum; i++) { + stdDev += colors[i].reduce((acc, curr, j) => acc + (curr - mean[j])**2, 0); + } + stdDev /= Math.max((colorNum - 1), 1) * 4; + stdDev = Math.round(stdDev**(1/2)); + return stdDev; +}; \ No newline at end of file diff --git a/test/stddev.test.js b/test/stddev.test.js new file mode 100644 index 00000000..08305206 --- /dev/null +++ b/test/stddev.test.js @@ -0,0 +1,28 @@ +const vows = require('vows') +const assert = require('assert'); +require('es6-shim'); + +const stdDeviation = require('../src/utils/deviation'); +const Color = require('../src/Color');; + +const tests = { + hex: {in: ['#D2691E', '#8B4513', '#A0522D','#0000FF', '#668B8B', '#FFC0CB'], out: 158}, + rgba: {in: [[210,105,30,1],[139,69,19,1],[160,82,45,1],[0,0,255,1],[102,139,139,1],[255,192,203,1]], out: 158}, + chromacolor: {in: ['#D2691E', '#8B4513', '#A0522D', '#0000FF', '#668B8B', '#FFC0CB'].map((color) => new Color(color)), out: 158}, +}; + +const batch = {}; + +Object.keys(tests).forEach(key => { + batch[`stdDeviation ${key}`] = { + topic: tests[key], + num(topic) { + assert.deepStrictEqual(stdDeviation(topic.in), topic.out); + }, + } +}) + +vows + .describe('Testing standard deviation') + .addBatch(batch) + .export(module);