Making Filters Using p5.js!
Black & White
In the RGBA color system, we get greys whenever the red, green, and blue values are the same. Having that in mind, the most basic (but not exactly accurate) way of creating a greyscale filter, is to get the average rgb value of each pixel, and setting the variables r, g, and b to that number. Lets create a variable called bw and set it to the average of rgb:
var bw = ( r + g + b ) / 3;
function draw(){
image(img, 0, 0, img.width, img.height);
loadPixels();
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (x + y * width)*4;
var r = pixels[index+0];
var g = pixels[index+1];
var b = pixels[index+2];
var a = pixels[index+3];
var bw = (r + g + b)/3;
pixels[index+0] = bw;
pixels[index+1] = bw;
pixels[index+2] = bw;
}
}
updatePixels();
}
Awesome, you did it! You made a black and white filter. But if my previous statement saying that this method is not very accurate sparked your curiosity, I'll ellaborate. The human eye does not process all colors the same way. It actually prioritizes some colors over others. To create an accurate "average" of rgb values, we need to follow the luma formula, which give us the weights red, green, and blue actually have.
var luma = r*0.299 + g*0.587 + b*0.0114;
function draw(){
image(img, 0, 0, img.width, img.height);
loadPixels();
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (x + y * width)*4;
var r = pixels[index+0];
var g = pixels[index+1];
var b = pixels[index+2];
var a = pixels[index+3];
var luma = r *.299 + g *.587 + b *.0114;
pixels[index+0] = luma;
pixels[index+1] = luma;
pixels[index+2] = luma;
}
}
updatePixels();
}
Sepia
Just like different colors have different weights in order to create a black and white filter, we need to prioritize certain colors to create a Sepia filter. However, unlike the Black & White filter, we don't have one formula we can use for all three colors (r,g,b). We need three different formulas: one for red, one for green, and one for blue. Sepia is a reddish brown color and to get effect, these are the values Microsoft recomends:
var tr = (r * 0.393) + (g * 0.769) + (b * 0.189);
var tg = (r * 0.349) + (g * 0.686) + (b * 0.168);
var tb = (r * 0.272) + (g * 0.534) + (b * 0.131);
Now we need to set our canva's r, g, b values to the values we just calculated:
r = tr;
g = tg;
b = tb;
function draw(){
image(img, 0, 0, img.width, img.height);
loadPixels();
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (x + y * width)*4;
var r = pixels[index+0];
var g = pixels[index+1];
var b = pixels[index+2];
var a = pixels[index+3];
//sepia
var tr = r *.393 + g *.769 + b *.189;
var tr = r *.349 + g *.686 + b *.168;
var tr = r *.272 + g *.534 + b *.131;
pixels[index+0] = tr;
pixels[index+1] = tg;
pixels[index+2] = tb;
}
}
updatePixels();
}
Negative
Creating a negative filter is going to be the easiest one so far! All you have to do is subtract the pixels, r, g, b values from white to reverse it. This sounds harder than it actually is, so we'll just show it to you:
function draw(){
image(img, 0, 0, img.width, img.height);
loadPixels();
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (x + y * width)*4;
var r = pixels[index+0];
var g = pixels[index+1];
var b = pixels[index+2];
var a = pixels[index+3];
pixels[index+0] = 255 - r;
pixels[index+1] = 255 - g;
pixels[index+2] = 255 - b;
}
}
updatePixels();
}
Just by playing around with which colors you reserse, you can create a full set of filters! Here are a couple more of examples:
function draw(){
image(img, 0, 0, img.width, img.height);
loadPixels();
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (x + y * width)*4;
var r = pixels[index+0];
var g = pixels[index+1];
var b = pixels[index+2];
var a = pixels[index+3];
pixels[index+0] = 255 - r;
pixels[index+1] = g;
pixels[index+2] = b;
}
}
updatePixels();
}
function draw(){
image(img, 0, 0, img.width, img.height);
loadPixels();
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (x + y * width)*4;
var r = pixels[index+0];
var g = pixels[index+1];
var b = pixels[index+2];
var a = pixels[index+3];
pixels[index+0] = r;
pixels[index+1] = 255 - g;
pixels[index+2] = b;
}
}
updatePixels();
}