Published
Edited
Sep 2, 2022
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
imageData = getImageData(image)
Insert cell
Insert cell
chunkedImgData = _.chunk(imageData.data, 4) // convert Uint8ClampedArray into array of [RGBA]
Insert cell
Insert cell
import { reluminance } from "@sebastien/srgb-rgb-gamma"
Insert cell
pixelLuminance = chunkedImgData.map(([r, g, b, a]) => {
// transparent images seem to work - check the popcorn demo image
// if (a !== 255) throw "Convert transparent images to fully opaque";

// convert rgba to luminance
return reluminance([r, g, b]);
})
Insert cell
Insert cell
Insert cell
Insert cell
pixelContrast = {
const contrasts = pixelLuminance.map((thisLum, i, arr) => {
const vals = getAdjacentValues(i, arr, imageData.width);
const darkest = Math.min(...vals);
const lightest = Math.max(...vals);
const delta =
lightest - thisLum >= thisLum - darkest
? thisLum / lightest
: darkest / thisLum;

const contrastRatio = 1 / delta;

return contrastRatio;
});

// preserve the width parameter for use in thresholdImage
contrasts.width = imageData.width;
contrasts.height = imageData.height;

return contrasts;
}
Insert cell
// colorizedContrast = pixelContrast.map(contrastRatio => {
// if (contrastRatio < 3) {
// return [255, 255, 255, 255]; // white: no contrast
// } else if (contrastRatio < 4.5) {
// return [170, 170, 170, 255]; // ui contrast
// } else if (contrastRatio < 7) {
// return [85, 85, 85, 255]; // text contrast
// } else {
// return [0, 0, 0, 255]; // black: super contrast
// }
// })
Insert cell
Insert cell
thresholdImage = (pxContrast, filter) => {
const ctx = DOM.context2d(pxContrast.width, pxContrast.height, 1);
const mask = new ImageData(
new Uint8ClampedArray(pxContrast.map(filter).flat()),
pxContrast.width
);

return image2canvas(mask, pxContrast.width);
}
Insert cell
// viewof unsplash = {
// const i = FileAttachment("lance-anderson-NrDYqseeAxk-unsplash.jpg");
// const r = html`${await i.image()}Photo by <a href="https://unsplash.com/@lanceanderson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Lance Anderson</a> on <a href="https://unsplash.com/s/photos/boston?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>
// `;
// r.value = getImageData(await i.blob());
// return r;
// }
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// get placeholder data
import { viewof imageSelector, viewof image } from "@sgregson/a11y-utils"
Insert cell
image2canvas = (imageData, width) => {
const context = DOM.context2d(imageData.width, imageData.height, 1);
context.putImageData(imageData, 0, 0);
if (!width || imageData.width <= width) return context.canvas;

const height = (imageData.height * width) / imageData.width;
const contextr = DOM.context2d(width, height, 1);
contextr.drawImage(context.canvas, 0, 0, width, height);
return contextr.canvas;
}
Insert cell
formatPercent = d3.format(".2%")
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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