A Pen by Jake Brown on CodePen.
Created
April 15, 2023 01:45
-
-
Save jake-sl/17cda01d80024db1fe4c489bc181f06b to your computer and use it in GitHub Desktop.
vYVGyyo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<body> | |
<input type="file" id="image-input" accept="image/*"> | |
<input type="range" id="hue-range" min="0" max="360" value="0"> | |
<input type="color" id="bg-color" value="#ffffff"> | |
<canvas id="image-canvas"></canvas> | |
<script src="main.js"></script> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const imageInput = document.getElementById('image-input'); | |
const hueRange = document.getElementById('hue-range'); | |
const bgColor = document.getElementById('bg-color'); | |
const canvas = document.getElementById('image-canvas'); | |
const ctx = canvas.getContext('2d'); | |
let img = new Image(); | |
imageInput.addEventListener('change', (e) => { | |
const reader = new FileReader(); | |
reader.onload = (event) => { | |
img.src = event.target.result; | |
img.onload = () => { | |
canvas.width = img.width; | |
canvas.height = img.height; | |
updateImage(); | |
}; | |
}; | |
reader.readAsDataURL(e.target.files[0]); | |
}); | |
hueRange.addEventListener('input', updateImage); | |
bgColor.addEventListener('input', updateBackground); | |
function createHueRotationMatrix(angle) { | |
const cosA = Math.cos(angle); | |
const sinA = Math.sin(angle); | |
const lumR = 0.213; | |
const lumG = 0.715; | |
const lumB = 0.072; | |
return [ | |
lumR + cosA * (1 - lumR) + sinA * (-lumR), | |
lumG + cosA * (-lumG) + sinA * (-lumG), | |
lumB + cosA * (-lumB) + sinA * (1 - lumB), | |
0, | |
0, | |
lumR + cosA * (-lumR) + sinA * (0.143), | |
lumG + cosA * (1 - lumG) + sinA * (0.14), | |
lumB + cosA * (-lumB) + sinA * (-0.283), | |
0, | |
0, | |
lumR + cosA * (-lumR) + sinA * (-(1 - lumR)), | |
lumG + cosA * (-lumG) + sinA * (lumG), | |
lumB + cosA * (1 - lumB) + sinA * (lumB), | |
0, | |
0, | |
0, | |
0, | |
0, | |
1, | |
0, | |
]; | |
} | |
function updateImage() { | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
// Draw the image in grayscale | |
ctx.filter = 'grayscale(100%)'; | |
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); | |
ctx.filter = 'none'; | |
// Apply the hue rotation color matrix | |
const angle = (hueRange.value / 360) * 2 * Math.PI; | |
const matrix = createHueRotationMatrix(angle); | |
const matrixStr = `matrix(${matrix.join(', ')})`; | |
ctx.filter = matrixStr; | |
// Draw the colorized image onto the main canvas | |
ctx.drawImage(canvas, 0, 0, canvas.width, canvas.height); | |
ctx.filter = 'none'; | |
} | |
function hslToRgb(h, s, l) { | |
let r, g, b; | |
if (s === 0) { | |
r = g = b = l; // achromatic | |
} else { | |
const hue2rgb = (p, q, t) => { | |
if (t < 0) t += 1; | |
if (t > 1) t -= 1; | |
if (t < 1 / 6) return p + (q - p) * 6 * t; | |
if (t < 1 / 2) return q; | |
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; | |
return p; | |
}; | |
const q = l < 0.5 ? l * (1 + s) : l + s - l * s; | |
const p = 2 * l - q; | |
r = hue2rgb(p, q, h + 1 / 3); | |
g = hue2rgb(p, q, h); | |
b = hue2rgb(p, q, h - 1 / 3); | |
} | |
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; | |
} | |
function rgbToHsl(r, g, b) { | |
r /= 255, g /= 255, b /= 255; | |
const max = Math.max(r, g, b), min = Math.min(r, g, b); | |
let h, s, l = (max + min) / 2; | |
if (max === min) { | |
h = s = 0; // achromatic | |
} else { | |
const d = max - min; | |
s = l > 0.5 ? d / (2 - max - min) : d / (max + min); | |
switch (max) { | |
case r: h = (g - b) / d + (g < b ? 6 : 0); break; | |
case g: h = (b - r) / d + 2; break; | |
case b: h = (r - g) / d + 4; break; | |
} | |
h /= 6; | |
} | |
return [h, s, l]; | |
} | |
function updateBackground() { | |
canvas.style.backgroundColor = bgColor.value; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment