Last active
August 29, 2015 14:02
-
-
Save jorinvo/df70938d061b2b43c26d to your computer and use it in GitHub Desktop.
Demo for Basic Image Filtering Using a Canvas Element
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Demo for Basic Image Filtering Using a Canvas Element</title> | |
</head> | |
<body> | |
<div> | |
<input type="file" id="loader"> | |
<select id="filter"> | |
<option value="original">No Filter</option> | |
<option value="lowpass">Soft Focus</option> | |
<option value="highpass">Highpass</option> | |
<option value="edges">Sharp Edges</option> | |
</select> | |
<a href="//gist.github.com/jorin-vogel/df70938d061b2b43c26d">view source</a> | |
</div> | |
<canvas id="pic"></canvas> | |
<script> | |
!function() { | |
var width, height, i, x, y, r, g, b, xWithOffset, yWithOffset, pos, kernel, baseImageData; | |
var pic = document.getElementById('pic'); | |
var ctx = pic.getContext('2d'); | |
var selectedFilter = 'original'; | |
function applyFilter() { | |
var res = ctx.createImageData(baseImageData); | |
var pixels = baseImageData.data; | |
var filter = filters[selectedFilter]; | |
for (y = 0; y < height; y++) { | |
for (x = 0; x < width; x++) { | |
r = g = b = 0; | |
for (i = 0; i < kernelCoordinates.length; i += 2) { | |
// restrict to pixels inside image | |
xWithOffset = restrict( x + kernelCoordinates[i] , width ); | |
yWithOffset = restrict( y + kernelCoordinates[i+1] , height ); | |
pos = 4 * ( yWithOffset * width + xWithOffset ); | |
kernel = filter.kernel[i/2]; | |
r += pixels[pos] * kernel; | |
g += pixels[pos+1] * kernel; | |
b += pixels[pos+2] * kernel; | |
} | |
pos = 4 * ( y * width + x ); | |
res.data[pos] = transform(r, filter); | |
res.data[pos+1] = transform(g, filter); | |
res.data[pos+2] = transform(b, filter); | |
res.data[pos+3] = pixels[pos+3]; // don't manipulate alpha value | |
} | |
} | |
ctx.putImageData(res, 0, 0); | |
} | |
function loadImage(src) { | |
var img = new Image(); | |
img.onload = function() { | |
width = pic.width = img.width; | |
height = pic.height = img.height; | |
ctx.drawImage(img, 0, 0); | |
baseImageData = ctx.getImageData(0, 0, width, height); | |
applyFilter(); | |
}; | |
img.src = src; | |
} | |
// | |
// FILTERS | |
// | |
var filters = { | |
original: { | |
kernel: [ | |
0, 0, 0, | |
0, 1, 0, | |
0, 0, 0 | |
], | |
scale: 1, | |
offset: 0 | |
}, | |
lowpass: { | |
kernel: [ | |
1, 1, 1, | |
1, 1, 1, | |
1, 1, 1 | |
], | |
scale: 9, | |
offset: 0 | |
}, | |
highpass: { | |
kernel: [ | |
-1, -1, -1, | |
-1, 8, -1, | |
-1, -1, -1 | |
], | |
scale: 9, | |
offset: 128 | |
}, | |
edges: { | |
kernel: [ | |
-1, -1, -1, | |
-1, 17, -1, | |
-1, -1, -1 | |
], | |
scale: 9, | |
offset: 0 | |
} | |
}; | |
// | |
// HELPER | |
// | |
var kernelCoordinates = [ | |
-1, -1, | |
0, -1, | |
1, -1, | |
-1, 0, | |
0, 0, | |
1, 0, | |
-1, 1, | |
0, 1, | |
1, 1 | |
]; | |
function restrict(val, max) { | |
if (val < 0) return 0; | |
if (val > max) return max; | |
return val; | |
} | |
function transform(val, filter) { | |
return restrict(val / filter.scale + filter.offset, 255); | |
} | |
// | |
// USER EVENTS | |
// | |
document.getElementById('loader').addEventListener('change', function(changeEvent) { | |
var reader = new FileReader(); | |
reader.onload = function(loadEvent) { | |
loadImage(loadEvent.target.result); | |
}; | |
reader.readAsDataURL(changeEvent.target.files[0]); | |
}); | |
var filterElement = document.getElementById('filter'); | |
filterElement.addEventListener('change', function() { | |
selectedFilter = filterElement.value; | |
applyFilter(); | |
}); | |
// | |
// INIT | |
// | |
loadImage('test.jpg'); | |
}(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment