I’m trying to apply filter using the filter() ( eg: filter(GRAY) ), the problem I have is that it applies the filter to the whole Canvas instead of only the “selected” element.
So what I’m doing exactly is capturing the webcam image and drawing 2 images in front of each other ( using image() ), I would like to be able to apply a filter or multiple filters to the first image (in the background) and apply one or multiple filters to the foreground image. I know (I think) it’s doable when using loadImage() or createImage() but what in the case of capturing the webcam image.
I’m also confused about the blendMode(), I’m not really sure if it’s applying the blendMode to the whole items created or only the following items, so my second question is how to apply a different blend mode to each item, something like push() and pop() but for BlendMode and filter(), in my case I want my background image to be blended with the background color (let say MULTIPLY), and the foreground image to be blended with anything beneath with another blend mode.
Side questions: how to add contrast and brightness (like all the filters in css) to the whole canvas and to separate elements (in my case : image()), is there something like filter(CONTRAST, 1.2) and or filter(BRIGHTNESS, 2). Or could it be done using canvas stuff instead of P5?
You can use; capture.style('filter', 'brightness(50%)'); capture.style('filter', 'contrast(120%)');
However, CSS features works for only capture element itself. If you comment capture.hide(), you will get the effect. But this time, you cannot use the blendMode functions.
Another option can be using shaders to process the image like this.
@DevaPan’s answer is the most appropriate one for you, I think. But it can be expensive for the CPU.
Another trick can be playing around tint function before drawing the images.
Hi @TiborUdvari, That’s probably one of the solution, gonna try that, I need to learn a bit how createGraphics works, but I think I understand how stuff are going to work.
@DevaPan yes that would be perfect, but as explain in the first thread, it only work if the image is brought to the canvas using loadImage() or createImage(), which is not ideal because in my case the image comes from the webcam using capture.
so :
function setup() {
createCanvas(window.innerWidth, window.innerHeight);
capture = createCapture(VIDEO,{ flipped:true });
capture.size(390, 240);
// capture.filter(GRAY); // Not Working either
capture.hide();
frameRate(30);
}
function draw() {
frontImg = image(capture, 0, 0, window.innerWidth, window.innerHeight);
frontImg.filter(GRAY); //Not Working cause frontImg is not coming from loadImage() or createImage()
}
I made a library (p5.FIP) for p5.js that does these kind of filters (including grayscale, blend, contrast and brightness) on the GPU for better performance. Using these filters with framebuffers (tutorial) should suit your use case. To use it in your sketch you’d just have to import the library in your index.html file:
<head>
<!-- other head stuff -->
<script src="https://prontopablo.github.io/p5.FIP/assets/javascripts/p5.FIP.js"></script>
<!-- ...-->
</head>
Then in sketch.js load the shaders you want to use and create some framebuffers and apply the shaders to just the framebuffers:
function preload() {
grayscale = createShader(fip.defaultVert, fip.grayscale); // Load the grayscale shader
blend = createShader(fip.defaultVert, fip.blend); // Load the blend shader
contrast = createShader(fip.defaultVert, fip.contrast); // Load the contrast shader
brightness = createShader(fip.defaultVert, fip.brightness); // Load the brightness shader
}
function setup() {
createCanvas(600, 600, WEBGL); // Use WEBGL mode to use the shader
// Create framebuffers to draw onto (faster p5.js version of createGraphics())
layer1 = createFramebuffer();
layer2 = createFramebuffer();
}
Many thanks for all the solutions you gave me, gonna rework on the project this week and try the different paths. I’ll let you know what’s the working solution as soon as I put my hand on it again.