Skip to content

Instantly share code, notes, and snippets.

@VoxelPrismatic
Last active May 7, 2024 16:14
Show Gist options
  • Save VoxelPrismatic/1c79001ff0a3ae0dc8d976ab0caf1ed1 to your computer and use it in GitHub Desktop.
Save VoxelPrismatic/1c79001ff0a3ae0dc8d976ab0caf1ed1 to your computer and use it in GitHub Desktop.
hexToRgba, using lots of bitwise operations
function hexToRgba(st) {
if(st.startsWith("#"))
st = st.slice(1);
const len = st.length; // I don't know how JS works, I suspect this is recalculated
const has_alpha = !(len % 4);
if(len % 3 && !has_alpha)
throw new Error("invalid hex code");
var val = Number.parseInt(st, 16); // Only parsing the string once is faster than slicing constantly
const depth = Math.ceil(len / 4) << 2; // Depth will be multiple of 4 bits
const mask = (1 << depth) - 1; // Will mask bottom color
let A = (val | (mask * !has_alpha)) & mask; // In case there is no alpha, alpha will be 100%
let B = (val >>= (depth * has_alpha)) & mask; // Only shift when there is alpha
let G = (val >>= depth) & mask; // Always shift for green and blue (red is always first)
let R = (val >> depth) & mask; // Val is no longer needed; no need to store new value
// 4bit to 8bit depth
const four_bit = (depth == 4) << 2; // Will not shift if depth > 4
B |= B << four_bit;
G |= G << four_bit;
R |= R << four_bit;
A |= A << four_bit;
return [R, G, B, A];
}
module.exports = hexToRgba;

Note

This package is officially published under @voxelprismatic/hextorgba on NPM.

Don't use this gist, as it uses Number, which conveniently breaks down at 12bit wide color channels with alpha channel (#RRRGGGBBBaaa). The NPM package uses BigInt, which goes up and beyond 20bit wide color channels.

The NPM package also supports returning array (default), object, percentages as array, and CSS rgb(...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment