JSFiddle - React, Tailwind, and code Playground
by mikola
HTML
<script src="http://www.numericjs.com/lib/numeric-1.2.3.min.js"></script>
<canvas id="c" width="128" height="128"></canvas>
<img id="eyeball_pic" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAEV0lEQVR4Xu2ZyyquYRiGn89ethGyyWaCMsWIQ3AOMhCKgRNwDDI0oUQ2U0pkSImZbCJ7ZSL7/eZb//Ou1lrHsL77+usL/Qye977++76fVzQwMBBnZGRYc3Oz5ebmWklJib29vdnOzo7V19dbZWWlXVxc2OPjo728vFgcx1ZYWGjDw8PG6/8/gai/vz9ubGy0j48PKy4utvLy8jDV8fFxEP/r68uurq7s5+cnPNnZ2QGUoaGh/396JrBobGwszszMtOfn5yBubW1t+JR/f3/b5eWlHR0dWX5+fvjUZ2Vlmf+uf+3r6+P4EnAC0cTEROyfaBf7TxS4yJubm7a2thYcwN/39zweGhoagjP09vYmYHxGiBYWFuK0tDTb29uzpqYmKyoqso2NDTs7OwvfR1FkT09PdnBwYNfX18ElPDJSf8fpJeAEopWVlfj8/DwIXVFRYYuLi3ZychIs319eCGtqasx/5/PzM5TB9/d3297eTsD4jBAAuL+/D+JOTU0FJ3C7d+G9GHoX8Ehw4evq6qylpcXS09NtZmaG00vACUSrq6vx7e2tjY+P29bWVhjJS6C/HAAXvaOjw9bX121/fz+si21tbZbqDgkYnxGi5eXleHJyMpS+m5ubkPFe8h4eHgIAVVVVNjIyEn4eHR2119dXq66utqWlJU4vAScQDQ4Oxqenp6ED+IWPF73W1lbzWHBn6OzstO7u7gDD7Ozs34hIgZOA8Rkh6urqigsKCqy0tDTk/uHhYcj8srKycDHU3t4e3nMH2N3dDZB4CZybm+P0EnACUU9PT7gI+vN4GfS17+7uLlz4+O7vdwFu+w6KO4RvBPPz8wkYnxGi1I1enJeXFwDwxu9R4Hbvjwufk5MTHr8N9HLo/w/wS6Pp6WlOLwEnkNI7+l35eUmeAABIyv5vaAAAACJAmQEcQFn91OwAAABEgDIDOICy+kSAuPoAAABEgDgDAAAAbAHKDOAAyupTAsXVBwAAIALEGQAAAGALUGYAB1BWnxIorj4AAAARIM4AAAAAW4AyAziAsvqUQHH1AQAAiABxBgAAANgClBnAAZTVpwSKqw8AAEAEiDMAAADAFqDMAA6grD4lUFx9AAAAIkCcAQAAALYAZQZwAGX1KYHi6gMAABAB4gwAAACwBSgzgAMoq08JFFcfAACACBBnAAAAgC1AmQEcQFl9SqC4+gAAAESAOAMAAABsAcoM4ADK6lMCxdUHAAAgAsQZAAAAYAtQZgAHUFafEiiuPgAAABEgzgAAAABbgDIDOICy+pRAcfUBAACIAHEGAAAA2AKUGcABlNWnBIqrDwAAQASIMwAAAMAWoMwADqCsPiVQXH0AAAAiQJwBAAAAtgBlBnAAZfUpgeLqAwAAEAHiDAAAALAFKDOAAyirTwkUVx8AAIAIEGcAAACALUCZARxAWX1KoLj6AAAARIA4AwAAAGwBygzgAMrqUwLF1QcAACACxBkAAABgC1Bm4Be7haeQK+qcAwAAAABJRU5ErkJggg==" style="display: none;">
<img id="lena_pic"...
CSS
#c {
width: 500px;
height: 500px;
}
JavaScript
var kernel_dims = [2, 3, 3];
var kernel = [
[ [ 0.0, 0.5, 0.0 ],
[ 0.5, 0.0, 0.5 ],
[ 0.0, 0.5, 0 ] ],
[ [ 0.0, 0.0, 0.0 ],
[ 0.0,-1.0, 0.0 ],
[ 0.0, 0.0, 0.0 ] ] ];
//Add a damping factor
for(var i=0; i<kernel_dims[0]; ++i)
for(var j=0; j<kernel_dims[1]; ++j)
for(var k=0; k<kernel_dims[2]; ++k) {
kernel[i][j][k] *= 0.99;
}
//Coloring stuff
var color_shift = [128, 128, 128];
var color_scale = [1.0, 1.0, 1.0];
//Canvas elements
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
//Buffers
var field_dims = [ canvas.width, canvas.height ];
var fields = new Array(kernel_dims[0] + 1);
for(var i=0; i<fields.length; ++i) {
fields[i] = numeric.rep(field_dims, 0.0);
}
var current_field = 0;
//Applies the kernel to the image
function apply_kernel() {
//Read in fields
current_field = (current_field + 1) % fields.length;
var next_field = fields[current_field];
// 1/2 kernel dims
var half_kernel = [kernel_dims[1]>>1, kernel_dims[2]>>1];
//For each time segment
for(var t=0; t<kernel_dims[0]; ++t) {
var K = kernel[t];
var cur_field = fields[(current_field - 1 - t + fields.length) % fields.length];
//For every pixel in the image
for(var i=0; i<field_dims[0]; ++i) {
for(var j=0; j<field_dims[1]; ++j) {
//For sum up weighted average of neighbors
var s = 0.0;
for(var k=0; k<kernel_dims[1]; ++k) {
for(var l=0; l<kernel_dims[2]; ++l) {
var u = (field_dims[0] + i + k - half_kernel[0]) % field_dims[0];
var v = (field_dims[1] + j + l - half_kernel[1]) % field_dims[1];
s += K[l][k] * cur_field[u][v];
}
...