Using knowledge of OP's answer that the middle value has
new_mid = max / (r + 1) * sat + max * (1 - sat)
r = (max - mid) / (mid - min)
Can simplify...
new_mid = max / (((max - mid) / (mid - min)) + 1) * sat + max * (1 - sat)
= max * (sat / (((max - mid) / (mid - min)) + 1) + (1 - sat))
= max * ((1 - sat) + sat / (((max - mid) / (mid - min)) + ((mid - min) / (mid - min))))
= max * ((1 - sat) + sat / (((max - mid) + (mid - min)) / (mid - min)))
= max * ((1 - sat) + sat * (mid - min) / ((max - mid) + (mid - min)))
= max * ((1 - sat) + sat * (mid - min) / (max - min))
let
a = max - min
b = mid - min
=>
new_mid = max * ((1 - sat) + sat * b / a)
I've re-written the method to not use jQuery, do division less and accept more inputs
// Inputs
// Array rgb colour data, s new hsl saturation
// Outputs
// Array rgb colour data
function saturation(rgb, s) {
var min = rgb.indexOf(Math.min.apply(null, rgb)), // index of min
max = rgb.indexOf(Math.max.apply(null, rgb)), // index of max
mid = [0, 1, 2].filter(function (i) {return i !== min && i !== max;})[0],
a = rgb[max] - rgb[min],
b = rgb[mid] - rgb[min],
x = rgb[max],
arr = [x, x, x];
if (min === max) {
min = 2; // both max = min = 0, => mid = 1, so set min = 2
a = 1; // also means a = b = 0, don't want division by 0 in `b / a`
}
arr[max] = x;
arr[min] = Math.round(x * (1 - s));
arr[mid] = Math.round(x * ((1 - s) + s * b / a));
return arr;
}
Now same as before,
saturation([52, 132, 220], 0.5); // [ 110, 162, 220 ]
saturation([52, 132, 220], 0); // [ 220, 220, 220 ]
saturation([52, 132, 220], 1); // [ 0, 105, 220 ]
But also works for values which have equal sections
saturation([80, 80, 80], 0.5); // [80, 40, 40] vs []
Changing value is a lot easier
// Inputs
// Array rgb colour data, v new hsl value
// Outputs
// Array rgb colour data
function nvalue(rgb, v) {
var x = Math.max.apply(null, rgb);
if (x === 0)
return [
Math.round(255 * v),
Math.round(255 * v),
Math.round(255 * v)
];
x = 255 * v / x;
return [
Math.round(rgb[0] * x),
Math.round(rgb[1] * x),
Math.round(rgb[2] * x)
];
}