Public
Edited
Apr 23, 2023
Insert cell
Insert cell
Insert cell
Insert cell
// update view data when backing colors update
view.data('colors', colors).runAsync(), md`${colors.length} colors!`
Insert cell
colors = {
const inGamut = (v) => 0 <= v && v <= 255;
const inGamutBox = ([y, cb, cr]) =>
0 <= y && y <= 255 && 0 <= cb && cb <= 255 && 0 <= cr && cr <= 255;

const data = [];

// generate full grid of Cb-Cr coordinates
d3.cross(d3.range(0, 255, 1), d3.range(0, 255, 1)).forEach(([cb, cr]) => {
// generate YCbCRLAB color, keep those within RGB gamut
const c = d3.rgb(...yCbCr2RGBunclamped([Y, cb, cr]));
if (inGamut(c.r) && inGamut(c.g) && inGamut(c.b)) {
data.push([cb, cr, c + ""]);
}
});

return data;
}
Insert cell
Insert cell
Insert cell
function yCbCr2RGBunclamped(yCbCr) {
const y = parseFloat(yCbCr[0]);
const cb = parseFloat(yCbCr[1] - 128);
const cr = parseFloat(yCbCr[2] - 128);
return [
Math.round(y + 1.402 * cr),
Math.round(y - 0.3441 * cb - 0.7141 * cr),
Math.round(y + 1.772 * cb)
];
}
Insert cell
function rgb2YCbCr(rgb) {
const r = parseFloat(rgb[0]);
const g = parseFloat(rgb[1]);
const b = parseFloat(rgb[2]);

const y = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
const cb = Math.round(-0.1687 * r - 0.3313 * g + 0.5 * b + 128);
const cr = Math.round(0.5 * r - 0.4187 * g - 0.0813 * b + 128);

return new Uint8ClampedArray([y, cb, cr]);
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more