I'm not sure what the case you're imagining is, but reading your desired output, what is wrong with simply scaling up so the maximum value becomes 255?
function scaleUp(rgb) {
let max = Math.max(rgb.r, rgb.g, rgb.b);
if (!max) { // 0 or NaN
return {r: 255, g: 255, b: 255};
}
let factor = 255 / max;
return {
r: factor * rgb.r,
g: factor * rgb.g,
b: factor * rgb.b,
};
}
So you would get results like
scaleUp({r: 0, g: 0, b: 0}); // {r: 255, g: 255, b: 255}
scaleUp({r: 255, g: 0, b: 0}); // {r: 255, g: 0, b: 0}
scaleUp({r: 50, g: 80, b: 66}); // {r: 159.375, g: 255, b: 210.375}
Notice this collapses all {x, 0, 0}
to {255, 0, 0}
, meaning {1, 0, 0}
is vastly different to {1, 1, 1}
. If this is not desirable you'd need to consider special handling of such cases
More RGB hints; you get smoother "more natural" light transitions etc if you square and root around your op, e.g. rather than x + y
, do sqrt(x*x + y*y)
This leads to a different idea of how to solve the problem; adding white and scaling down
function scaleDown(rgb) {
let whiteAdded = {
r: Math.sqrt(255 * 255 + rgb.r * rgb.r),
g: Math.sqrt(255 * 255 + rgb.g * rgb.g),
b: Math.sqrt(255 * 255 + rgb.b * rgb.b)
};
return scaleUp(whiteAdded);
}
This time
scaleDown({r: 0, g: 0, b: 0}); // {r: 255, g: 255, b: 255}
scaleDown({r: 255, g: 0, b: 0}); // {r: 255, g: 180.3122292025696, b: 180.3122292025696}
scaleDown({r: 50, g: 80, b: 66}); // {r: 247.94043129928136, g: 255, b: 251.32479296236951}
and have less of a jump around edge points, e.g.
scaleDown({r: 1, g: 0, b: 0}); // {r: 255, g: 254.99803923830171, b: 254.99803923830171}
Finally, notice this maps rgb onto the the range 180..255
, so you could transform this to 0..255
if you want to preserve your "true red"s etc
function solution(rgb) {
let high = scaleDown(rgb);
return {
r: 3.4 * (high.r - 180),
g: 3.4 * (high.g - 180),
b: 3.4 * (high.b - 180),
};
}
So
solution({r: 255, g: 0, b: 0}); // {r: 255, g: 1.0615792887366295, b: 1.0615792887366295}
solution({r: 1, g: 0, b: 0}); // {r: 255, g: 254.99333341022583, b: 254.99333341022583}
solution({r: 50, g: 80, b: 66}); // {r: 230.9974664175566, g: 255, b: 242.50429607205635}