DEV Community

Dominic Myers
Dominic Myers

Posted on • Originally published at drmsite.blogspot.com on

rgba2rgb

I had a lovely little challenge a couple of days ago which, in conjunction with my invite to the First Alpha Testing of Empire of Code, got me excited. It led me to generate the following chunk of code:

const rgba2rgb = rgba => "#" + rgba.match(/.{1,2}/g)
  .map((c, i, a) => (i !== a.length -1)
    ? parseInt(c, 16)
    : parseInt(c, 16) / 255)
  .map((c, i, a) => (i !== a.length -1)
    ? ~~((1 - a[3]) * 255 + a[3] * c)
    : null)
  .reverse()
  .slice(1)
  .reverse()
  .map(c => c.toString(16))
  .join("");
Enter fullscreen mode Exit fullscreen mode

We needed to convert an RGBA colour to RGB, with the assumption that the original colour was atop a white background. The maths and colour theory are a little confusing, and I went through any number of iterations. The result made me feel a bit smug though as it is teeny - I'm guessing it could be improved though.

Have at it!

EDIT

So I clocked that the above wasn't quite as brilliant as I thought so I've updated it after simplifying it:

const rgba2rgb = function(rgba){
  const coloursAsBase16 = rgba.match(/.{1,2}/g); 
  console.log("coloursAsBase16", coloursAsBase16);
  const coloursAsBase10 = coloursAsBase16.map(function(c, i, a){
    if(i !== a.length - 1) {
      return parseInt(c, 16) // Value between 1 - 255
    } else {
      return parseInt(c, 16) / 255 // Value between 0 - 1}
    }); 
  console.log("coloursAsBase10", coloursAsBase10);
  const coloursWithAlpha = coloursAsBase10.reduce(function(t, c, i, a) {
    if(i !== a.length - 1) {
      return t.concat([parseInt(((1 - a[3]) * 255 + a[3] * c), 10)]);
    } else {
      return t;
    }
  }, []) 
  console.log("coloursWithAlpha", coloursWithAlpha);
  const coloursChangedToBase16 = coloursWithAlpha.map(function(c){
    return c.toString(16)
  }); 
  console.log("coloursChangedToBase16", coloursChangedToBase16);
  return "#" + coloursChangedToBase16.join("");
}
Enter fullscreen mode Exit fullscreen mode

Which led to this one-liner:

const rgba2rgb = rgba => "#" + rgba.match(/.{1,2}/g)
  .map((c, i, a) => (i !== a.length - 1)
    ? parseInt(c, 16)
    : parseInt(c, 16) / 255)
  .reduce((t, c, i, a) => (i !== a.length - 1)
    ? t.concat([parseInt(((1 - a[3]) * 255 + a[3] * c), 10)])
    : t, [])
  .map(c => c.toString(16))
  .join("");
Enter fullscreen mode Exit fullscreen mode

Top comments (0)