You can add various effects to your images by placing them in a canvas element and adjusting the image pixel by pixel. I cam up with a couple different patterns simply by altering the opacity of the image in different places. First off there is a great tutorial over here, if you are new to the canvas element. I’ll recap:
Canvas Basics…
- Find the canvas element on the page
- Get the context of the element
- Get the image you will be loading into canvas
- Display the image on the canvas
// get the canvas
var mikeCodeCanvas = document.getElementById("mike-code-canvas");
// get the context
var mikeCodeContext = mikeCodeCanvas.getContext("2d");
// get the image
var mikeCodeImage = document.getElementById("mike-code-img");
// draw the image
mikeCodeContext.drawImage(mikeCodeImage, 0, 0);
More advanced…
- Get the image data
- Alter the image data
- Display the new data
// get the image data
var mikeCodeImgData = mikeCodeContext.getImageData(0, 0, 485, 223);
// manipulate the image data
var mikeCodePix = mikeCodeImgData.data;
for (var i = 0, n = mikeCodePix.length; i < n; i += 4) {
mikeCodePix[i] = color; // red
mikeCodePix[i + 1] = color; // green
mikeCodePix[i + 2] = color; // blue
// mikeCodePix[i + 3] = color; // alpha
}
// write the new data to the image
mikeCodeContext.putImageData(mikeCodeImgData, 0, 0);
Now that we have the basics its time to start altering our image data. A simple way to do this is to take the negative of the image. Simply replace the code inside the “for loop” with this and you will end up with a negative of the original image.
mikeCodePix[i] = 255 - mikeCodePix[i];
mikeCodePix[i + 1] = 255 - mikeCodePix[i + 1];
mikeCodePix[i + 2] = 255 - mikeCodePix[i + 2];
It takes the maximum possible value in RGBa colors and subtracts the value it was currently at, reversing the color.
Next clear the orginial and write the data to the canvas again.
mikeCodeContext.clearRect(0, 0, mikeCodeCanvas.width, mikeCodeCanvas.height);
mikeCodeContext.putImageData(mikeCodeImgData, 0, 0);
You should see the image negative pop up.
Patterns…
So far we haven’t dealt with the alpha value much. Basically, the way the canvas pixel array work is it stores all pixel color information in a single array. It stores for values for every pixel (red, green, blue and alpha). That means you must travers every other set of 4 pixels in your for loop. It also means in the example above that alpha would be located at:
mikeCodePix[i + 3] = color;
So we can play around with the alpha values in our for loop as well. It also means we can skip over pixels and give them random values if we want. So lets try it out, lets give the alpha value a random number. Try this…
mikeCodePix[i + 3] = Math.floor(Math.random()*256);
This will loop through all the pixels and randomly assign an opacity to each pixel in the image. This makes it look like a bunch of noise on the image. From here you can check out the code and see what other patterns I’m giving the images.
function changePattern(pattern) {
pattern = pattern || "jeans";
var mikeCodeCanvas = document.getElementById("mike-code-canvas");
// remember to reset the canvas before placing a new effect on the image
mikeCodeCanvas.width = mikeCodeCanvas.width;
var mikeCodeContext = mikeCodeCanvas.getContext("2d");
var mikeCodeImage = document.getElementById("mike-code-img");
// draw the image
mikeCodeContext.drawImage(mikeCodeImage, 0, 0);
var mikeCodeImgData = mikeCodeContext.getImageData(0, 0, 485, 223);
var mikeCodePix = mikeCodeImgData.data;
for (var i = 0, n = mikeCodePix.length; i < n; i += 4) {
var color = 255;
if(mikeCodePix[i] > 0) {
color = 0;
}
/*
mikeCodePix[i] = color; // red
mikeCodePix[i+1] = color; // green
mikeCodePix[i+2] = color; // blue
*/
mikeCodePix[i] = 255 - mikeCodePix[i];
mikeCodePix[i + 1] = 255 - mikeCodePix[i + 1];
mikeCodePix[i + 2] = 255 - mikeCodePix[i + 2];
// jeans
if(pattern == "jeans") {
mikeCodePix[i * 4 + 3] = Math.floor(Math.random()*256);
}
// stripes
if(pattern == "stripes") {
mikeCodePix[i * 4 + 3] = 90;
}
//
// noise
if(pattern == "noise") {
mikeCodePix[i * Math.floor(Math.random()*4) + 3] = Math.floor(Math.random()*256);
}
//
// dots
if(pattern == "dots") {
mikeCodePix[i * 2 + 3] = 90;
}
//
// straight opacity
if(pattern == "opacity") {
mikeCodePix[i + 3] = 90;
}
if(pattern == "random") {
mikeCodePix[i + 3] = Math.floor(Math.random()*256);
}
}
mikeCodeContext.clearRect(0, 0, mikeCodeCanvas.width, mikeCodeCanvas.height);
mikeCodeContext.putImageData(mikeCodeImgData, 0, 0);
console.debug("end");
}
$(document).ready(function () {
$("li").click(function (event) {
//console.debug($(event.currentTarget.childNodes).data().pattern);
//console.dir($(event.currentTarget).find("a").data());
if($(event.currentTarget).find("a").data().pattern) {
var pattern = $(event.currentTarget).find("a").data().pattern
changePattern(pattern);
}
if($(event.currentTarget).find("a").data().color) {
var color = $(event.currentTarget).find("a").data().color;
$("body").css({"background-color" : color});
if(color == "white") {
color = "black";
} else {
color = "white";
}
$("a").data("color", color);
}
});
});
$(window).load(function () {
changePattern("jeans");
});
On document read we listen for a click even on one of the pattern links, if we find one, we search through html5’s new data attribute until we find the right pattern and pass the value to the function “changePattern()”. This function takes a pattern finds all the canvas elements, reset’s the canvas and loops through the pixels according to the pattern it was passed. Then we print out the image. On window.load we set the default pattern to “jeans”.