const gpu = new GPU(); const image = document.getElementById('img'); function lum(r, g, b) { return 0.2126 * r + 0.7152 * g + 0.0722 * b; } gpu.addFunction(lum); function verticalLine(x) { return x; } gpu.addFunction(verticalLine); function diagonalLine(x, y) { return x + y; } gpu.addFunction(diagonalLine); function reverseDiagonalLine(x, y) { return y - x; } gpu.addFunction(reverseDiagonalLine); function circleLine(x, y) { return Math.round(Math.sqrt(x * x + y * y)); } gpu.addFunction(circleLine); function waveLine(x, y) { return Math.round(y / this.constants.k * Math.cos(x / this.constants.k)); } gpu.addFunction(waveLine); function shade(img) { // Get position const x = this.thread.x; const y = this.thread.y; // Get pixel const p = img[y][x]; // Get luminace const l = lum(p[0], p[1], p[2]) // Threshold color const space = l * this.constants.spaces; // Exponentially space out lines const lineSpacing = Math.round(Math.pow(space, this.constants.exp)); // Default color this.color(1, 1, 1); // Apply function let f = 1; if (this.constants.func === 1) { f = verticalLine(x); } else if (this.constants.func === 2) { f = diagonalLine(x, y); } else if (this.constants.func === 3) { f = circleLine(x, y); } else { f = waveLine(x, y); } if (f % lineSpacing === 0) { this.color(0, 0, 0); } } let first = true; function update() { const render = gpu.createKernel(shade) .setGraphical(true) .setOutput([image.width, image.height]) .setConstants({ spaces: parseInt(document.getElementById('spaces').value), exp: parseFloat(document.getElementById('exp').value), k: parseFloat(document.getElementById('k').value), func: parseFloat(document.getElementById('function').value), }) document.getElementById('spaces-value').innerHTML = document.getElementById('spaces').value document.getElementById('exp-value').innerHTML = document.getElementById('exp').value document.getElementById('k-value').innerHTML = document.getElementById('k').value render(image) if (first) { const canvas = render.getCanvas(); document.getElementsByClassName('images')[0].appendChild(canvas); first = false; } } document.getElementById('exp').oninput = () => { update(); } document.getElementById('spaces').oninput = () => { update(); } document.getElementById('k').oninput = () => { update(); } document.getElementById('function').onchange = () => { update(); } document.getElementById('pic').onchange = function(evt) { var tgt = evt.target || window.event.srcElement, files = tgt.files; // FileReader support if (FileReader && files && files.length) { var fr = new FileReader(); fr.onload = function() { document.getElementById('img').src = fr.result; setTimeout(update, 0); } fr.readAsDataURL(files[0]); } // Not supported else { // fallback -- perhaps submit the input to an iframe and temporarily store // them on the server until the user's session ends. } } update();