Friday 31 May 2019

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("");

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("");
}

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("");

No comments:

Post a Comment