From 134d182d76950913055d3bb8942e75645bcb26ea Mon Sep 17 00:00:00 2001 From: Thibaud Date: Tue, 1 Oct 2024 17:55:58 +0200 Subject: [PATCH] image test --- image.html | 12 ++++++ image.js | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ rose.png | Bin 0 -> 20351 bytes 3 files changed, 117 insertions(+) create mode 100644 image.html create mode 100644 image.js create mode 100644 rose.png diff --git a/image.html b/image.html new file mode 100644 index 0000000..52c7f0b --- /dev/null +++ b/image.html @@ -0,0 +1,12 @@ + + + + + + Document + + + + + + diff --git a/image.js b/image.js new file mode 100644 index 0000000..acf1365 --- /dev/null +++ b/image.js @@ -0,0 +1,105 @@ +const canvas = document.getElementById("canvas"); +const ctx = canvas.getContext("2d"); + +const img = new Image(); +img.crossOrigin = "anonymous"; +img.src = "/rose.png"; +img.onload = () => { + /*canvas.offscreenCanvas = document.createElement("canvas"); + canvas.offscreenCanvas.height = img.height; + canvas.offscreenCanvas.width = img.width; + canvas.offscreenCanvas.getContext("2d").drawImage(img, 0, 0); + */ + ctx.drawImage(img, 0, 0); +}; + +function invert(imgData) { + const data = imgData.data; + for (let i = 0; i < data.length; i += 4) { + //const avg = (data[i] + data[i + 1] + data[i + 2]) / 3; + data[i] = 255 - data[i]; + data[i+1] = 255 - data[i+1]; + data[i+2] = 255 - data[i+2]; + } +} + +function greyscale(imgData) { + const data = imgData.data; + for (let i = 0; i < data.length; i += 4) { + const avg = (data[i] + data[i + 1] + data[i + 2]) / 3; + data[i] = avg; + data[i+1] = avg; + data[i+2] = avg; + } +} + +function clamp(x, min, max) { + return Math.min(Math.max(x, min), max); +} + +function convolve(imageData, kernel) { + const width = imageData.width; + const height = imageData.height; + const data = imageData.data; + const out = new ImageData(width, height); + const kernelSize = Math.sqrt(kernel.length); // Assuming kernel is square + const halfKernel = Math.floor(kernelSize / 2); + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let r = 0, g = 0, b = 0; + + for (let ky = -halfKernel; ky <= halfKernel; ky++) { + for (let kx = -halfKernel; kx <= halfKernel; kx++) { + const px = x + kx; + const py = y + ky; + if (px >= 0 && px < width && py >= 0 && py < height) { + const idx = (py * width + px) * 4; + const kernelValue = kernel[(ky + halfKernel) * kernelSize + (kx + halfKernel)]; + r += data[idx] * kernelValue; + g += data[idx + 1] * kernelValue; + b += data[idx + 2] * kernelValue; + } + } + } + + out.data[(y*width+x)*4] = r; + out.data[(y*width+x)*4 + 1] = g; + out.data[(y*width+x)*4 + 2] = b; + out.data[(y*width+x)*4 + 3] = data[(y*width+x) * 4 + 3]; // preserve original alpha + } + } + + return out; +} + +// multiply two 3x3 matrices +function matMult(a, b) { + const result = new Array(9).fill(0); + for (let j = 0; j < 3; ++j){ + for (let i = 0; i < 3; ++i) { + for (let k = 0; k < 3; ++k) { + result[j*3+i] += a[j*3+k] * b[k*3+i]; + } + } + } + return result; +} + +canvas.onclick = () => { + const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); + ctx.clearRect(0, 0, canvas.height, canvas.width); + //invert(imgData); + //greyscale(imgData); + //const identityKernel = [0, 0, 0, 0, 1, 0, 0, 0, 0]; + const gaussianKernel = [0.075, 0.124, 0.075, 0.124, 0.204, 0.124, 0.075, 0.124, 0.075] + const convolved = convolve(imgData, gaussianKernel); + ctx.putImageData(convolved, 0, 0); +}; + + +const matrixA = [1, 2, 3, 4, 5, 6, 7, 8, 9]; +const matrixB = [9, 8, 7, 6, 5, 4, 3, 2, 1]; + +const result = matMult(matrixA, matrixB); +console.log(result); diff --git a/rose.png b/rose.png new file mode 100644 index 0000000000000000000000000000000000000000..fc1341307a8e020d00573a12d4e1e6c7d117b44f GIT binary patch literal 20351 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 iWN%_+AW3auXJt}lVPtu6$z?nM0000 literal 0 HcmV?d00001