Skip to content

Instantly share code, notes, and snippets.

@greggman
Last active May 18, 2023 09:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greggman/9620c2ab126b82acd9c09aa1064a0ef0 to your computer and use it in GitHub Desktop.
Save greggman/9620c2ab126b82acd9c09aa1064a0ef0 to your computer and use it in GitHub Desktop.
Canvas2D: Grain
body {
}
div {
position: relative;
}
img {
display: block;
}
canvas {
position: absolute;
left: 0;
top: 0;
mix-blend-mode: multiply;
display: block;
}
<div>
<img>
<canvas></canvas>
</div>
function noise(u, v) {
const dot = u * 12.9898 * 2.0 + v * 78.233 * 2.0;
const s = Math.sin(dot) * 43758.5453 % 1;
return Math.abs(s % 1);
}
function grain(ctx) {
const {width, height} = ctx.canvas;
const imgData = new ImageData(width, height);
const pixels = new Uint32Array(imgData.data.buffer);
let offset = 0;
for (let y = 0; y < height; ++y) {
for (let x = 0; x < width; ++x) {
const n = noise(x / width, y / height) * 255 | 0;
pixels[offset++] = n << 24 | n << 16 | n << 8 | n;
}
}
ctx.putImageData(imgData, 0, 0);
}
async function main() {
// https://live.staticflickr.com/65535/52834380994_6fd5e4b7a2_h.jpg
const url = 'https://live.staticflickr.com/65535/52834380994_6fd5e4b7a2_h.jpg';
const img = document.querySelector('img');
//const img = new Image();
img.src = url;
await img.decode();
const ctx = document.querySelector('canvas').getContext('2d');
ctx.canvas.width = img.naturalWidth;
ctx.canvas.height = img.naturalHeight;
grain(ctx);
}
main();
{"name":"Canvas2D: Grain","settings":{},"filenames":["index.html","index.css","index.js"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment