Unlisted
Edited
Feb 11, 2023
Importers
Insert cell
Insert cell
blue = hdr_rgba_0_256
Insert cell
hdr_rgba_0_256 = blueNoiseFrom(FileAttachment("HDR_RGBA_0_256.png").image())
Insert cell
gradient(hdr_rgba_0_256)
Insert cell
Plot.rectY(
{ length: 256 * 256 * 100 },
Plot.binX(
{ y: "count", interval: 1 / 256 / 256 / 8 },
{
x: (d, i) => {
const s = ldr_rgba_0_1024(i % 1024, Math.floor(i / 1024));
return 0 <= s && s < 1 / 256 / 16 ? s : NaN;
}
}
)
).plot()
Insert cell
hdr_l_0_16 = blueNoiseFrom(FileAttachment("HDR_L_0_16.png").image())
Insert cell
gradient(hdr_l_0_16)
Insert cell
hdr_l_0_32 = blueNoiseFrom(FileAttachment("HDR_L_0_32.png").image())
Insert cell
gradient(hdr_l_0_32)
Insert cell
hdr_l_0_64 = blueNoiseFrom(FileAttachment("HDR_L_0_64.png").image())
Insert cell
gradient(hdr_l_0_64)
Insert cell
hdr_l_0_128 = blueNoiseFrom(FileAttachment("HDR_L_0_128.png").image())
Insert cell
gradient(hdr_l_0_128)
Insert cell
ldr_llll1_0_512 = blueNoiseFrom(FileAttachment("LDR_LLL1_0_512.png").image())
Insert cell
gradient(ldr_llll1_0_512)
Insert cell
ldr_rgba_0_1024 = blueNoiseFrom(FileAttachment("LDR_RGBA_0_1024.png").image())
Insert cell
gradient(ldr_rgba_0_1024)
Insert cell
sorted_1024 = blueNoiseFrom(FileAttachment("sorted-1024.png").image(), {sorted: true})
Insert cell
gradient(sorted_1024)
Insert cell
async function blueNoiseFrom(image, { sorted } = {}) {
image = await image;
const w = image.naturalWidth,
h = image.naturalHeight;
const context = DOM.context2d(w, h, 1);
context.drawImage(image, 0, 0, w, h);
let data = new Uint32Array(context.getImageData(0, 0, w, h).data.buffer);
if (sorted) data = data.map((d) => d & 0x00ffffff);
else data = d3.rank(data, (i, j) => j - i || 1);
const r = 1 / data.length;
return (x, y) => r * data[(x % w | 0) + w * (y % w | 0)];
}
Insert cell
async function sortImage(image) {
image = await image;
const w = image.naturalWidth,
h = image.naturalHeight;
const context = DOM.context2d(w, h, 1);
context.drawImage(image, 0, 0, w, h);
const imData = context.getImageData(0, 0, w, h);
const uint32 = new Uint32Array(imData.data.buffer);
const data = d3.rank(uint32, (i, j) => j - i || 1);
for (let i = 0; i < data.length; ++i) uint32[i] = data[i] | 0xff000000;
context.putImageData(imData, 0, 0);
return context.canvas;
}
Insert cell
sortImage(FileAttachment("LDR_RGBA_0_1024.png").image())
Insert cell
import { pseudoblue } from "@fil/pseudoblue"
Insert cell
function gradient(noise) {
const height = 240;
const context = DOM.context2d(width, height, 1);
const data = context.createImageData(width, height);
for (let y = 0, k = 0; y < height; ++y) {
for (let x = 0; x < width; ++x, k += 4) {
if (noise(x, y) * width < x) data.data[k + 3] = 255;
if (y > height - 10) data.data[k + 3] = (255 * x) / width;
}
}
context.putImageData(data, 0, 0);
return Object.assign(context.canvas, { style: "image-rendering: pixelated" });
}
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