Skip to content

Instantly share code, notes, and snippets.

@mattdesl
Created May 22, 2024 08:24
Show Gist options
  • Save mattdesl/d8b1f5fa26d3410218f0f38077add2ed to your computer and use it in GitHub Desktop.
Save mattdesl/d8b1f5fa26d3410218f0f38077add2ed to your computer and use it in GitHub Desktop.
quickly create a linear gradient in software in JS
const worker = new Worker(new URL("./gradient.js", import.meta.url), {
type: "module",
});
worker.postMessage({
// image options
width: 128,
height: 256,
channels: 4,
depth: 8
});
worker.addEventListener("message", (ev) => {
// Get the typed array view of the resulting pixels
const pixels = ev.data;
console.log(pixels);
});
/**
This is a WebWorker that quickly generates a 2D linear gradient image from a set of input params.
It is useful for testing, and for creating high bit-depth linear gradients.
This uses copyWithin() to expand the gradient across the entire array.
*/
self.onmessage = async (msg) => {
const { width = 256, height = 256, depth = 8, channels = 4 } = msg.data;
const ArrType = depth === 16 ? Uint16Array : Uint8ClampedArray;
const maxValue = depth === 16 ? 0xffff : 0xff;
let data = new ArrType(width * height * channels).fill(maxValue);
const A = [1, 0, 0];
const B = [0, 0, 1];
for (let x = 0; x < width; x++) {
const u = width <= 1 ? 1 : x / (width - 1);
const [r, g, b] = lerpArray(A, B, u).map((n) => toByte(n));
data[x * channels + 0] = r;
data[x * channels + 1] = g;
data[x * channels + 2] = b;
}
// quickly generate an image of expected size
for (let y = 1; y < height; y++) {
const x = 0;
const idx = x + y * width;
data.copyWithin(idx * channels, 0, width * channels);
}
self.postMessage(data);
function lerp(min, max, t) {
return min * (1 - t) + max * t;
}
function lerpArray(min, max, t, out = []) {
for (var i = 0; i < min.length; i++) {
out[i] = lerp(min[i], max[i], t);
}
return out;
}
function toByte(v) {
return Math.max(0, Math.min(maxValue, Math.round(v * maxValue)));
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment