I'm hoping this is a very straight forward question but I haven't been able to get to the bottom of it. I'm using a react-P5-wrapper to create my P5 canvas in react (https://github.com/slin12/react-p5-wrapper
) and I want to apply a filter to an image, which I normally would do in P5 like image.filter(GRAY)
, however I can't get it to work when P5 is an instance in React.
My sketch function looks like
function sketch(p5) {
let hair;
p5.setup = () => {
p5.createCanvas(600, 600);
hair = p5.loadImage(~/localpath/hairURL);
}
p5.draw = () => {
p5.image(hair, 0, 0);
};
}
I would have thought I could do something as easy as p5.image(hair,0,0).filter(p5.GRAY);
in my draw function, but that doesn't work. Gives me Uncaught TypeError: Cannot read properties of undefined (reading 'filter')
I could just use p5.filter(p5.GRAY);
as a separate line in draw() - which works - however that applies the filter over the whole canvas, whereas I want to just apply it over one of the images. I will have multiple images and want to apply different filters to each one.
p5.image(hair,0 ,0).p5.filter(p5.GRAY) doesn't work either (thought I would try even if it didn't make much sense)
Any help is appreciated! Thanks
CodePudding user response:
I don't think what you are trying to do will be possible with your current approach.
In the documentation for p5.filter(...)
it states the function "Applies a filter to the canvas" and there's no indication it can be constrained to an image or area of the canvas.
FYI, p5.image(...)
doesn't return anything, so calling any function on the result like p5.image(...).filter(...)
will always get the undefined error you are getting.
Edit
Actually the class p5.Image
has it's own filter
function.
So if you call
hair = loadImage(...)
//then
hair.filter(...)
And then later call image(hair, 0, 0)
, that should work.
CodePudding user response:
I think you've confused the function p5.image()
, which draws an image and returns undefined, and the p5.Image
class, which is an image and returns an object with methods such as p5.Image.filter()
. p5.Image.filter
is also a mutating mode setter that returns undefined, so it's not something you'd want to chain anywhere.
Also, the p5
prefix in instance mode only applies to global p5 functions, not methods called on local objects like vectors and images that aren't part of the global p5 API namespace.
Here's the correct usage:
new p5(p => {
let img1;
let img2;
p.preload = () => {
img1 = p.loadImage("http://placekitten.com/200/200");
img2 = p.loadImage("http://placekitten.com/200/202");
};
p.setup = () => {
p.createCanvas(700, 410);
p.background(0);
img1.filter(p.GRAY);
p.image(img1, 0, 0);
// should be unfiltered
p.image(img2, 200, 0);
p.noLoop();
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>