p5.js
p5.js copied to clipboard
Graphics object used as mask results in image that is half the size of the original graphics object
Most appropriate sub-area of p5.js?
- [ ] Accessibility
- [ ] Color
- [X] Core/Environment/Rendering
- [ ] Data
- [ ] DOM
- [ ] Events
- [X] Image
- [ ] IO
- [ ] Math
- [ ] Typography
- [ ] Utilities
- [ ] WebGL
- [ ] Build process
- [X] Unit testing
- [ ] Internationalization
- [ ] Friendly errors
- [X] Other (specify if possible)
p5.js version
1.9.0
Web browser and version
Chrome 121.0.6167.139
Operating system
MacOSX
Steps to reproduce this
Steps:
- Create a p5.Graphics object the same size as canvas—I've called mine "maskGraphics"
- Draw something to the main canvas—in my case it's an image
- Use get() to save a the canvas as an image, then clear the canvas.
- Draw something to the new Graphics object that will be the mask—in my case it's an ellipse
- Use mask() to mask the main image using the newly drawn mask to the mask graphics object.
- When you draw both the display image and the mask graphics image, the masked image is half the size as the mask graphics object when they're both drawn at the same size.
My gut is that it might have something to do with the device pixel ratio or the pixel density, but I have no reason to believe that and haven't been able to prove that.
Snippet:
let sketch = function(p) {
let img, maskGraphics, cnv;
p.preload = function() {
img = p.loadImage("https://hips.hearstapps.com/hmg-prod/images/dog-puppy-on-garden-royalty-free-image-1586966191.jpg?crop=1xw:0.74975xh;center,top&resize=1200:*");
};
p.setup = () => {
cnv = p.createCanvas(p.windowWidth, p.windowHeight);
maskGraphics = p.createGraphics(p.windowWidth, p.windowHeight);
}
p.draw = () => {
// draw an image to the main canvas
p.image(img, 0,0,p.width, p.height);
// save the canvas as an image, then clear the canvas
let displayImage = p.get();
p.clear();
maskGraphics.clear();
maskGraphics.fill(0);
// Draw an ellipse to the mask graphics element in the center of the canvas
maskGraphics.ellipse(p.width/2,p.height/2,300,300)
// Apply the mask to displayImage
// Without this, the image will be full size without the circle mask
displayImage.mask(maskGraphics);
// Draw the masked image
// Without this, there will not be the masked image
p.image(displayImage, 0, 0, p.width, p.height);
// Draw the mask circle as an image to the main cnv to test its position on the canvas
p.image(maskGraphics, 0, 0, p.width, p.height);
};
}
new p5(sketch, 'container');
Thanks for filing this issue! I think this bug may be the same as https://github.com/processing/p5.js/issues/6770 -- @Papershine, maybe you can test this example on your PR to see if it fixes it too?
Thank you! Yes, I had actually tested adding pixelDensity(1) prior to contributing the issue, but then the quality of the sketch goes down significantly. If I add pixelDensity(2) it also fixes the issue, but on devices where the device pixel ratio is something else the sketch lags significantly because it's drawing at 2x the size. I tried pixelDensity(window.devicePixelRatio) but that didn't fix the issue.
Is there a solution that solves the misalignment without losing the quality of the sketch?
If it helps to debug, I just switched to version 1.4.1 per #6770, and that worked. However, not ideal for a long-term solution since I'd like to use the most recent version. Let's see if @Papershine's pull request solves it?
Yep I've tried it with the code in the PR and this is how it looks - this should be what it looks like right?
whee yes! <3
Hey awesome P5 team, do you have any tips for what I should do in the meantime regarding this bug while the pull request is being approved? Clients eager to see things right.
Hi! One option to use a shader to do the masking. Not sure if you can use webGL or not, but if you can it's a pretty short shader. Here's a quick example: https://editor.p5js.org/aferriss/sketches/qYWb4P49d
Another option, if your mask is shapes that you draw, is to use beginClip/endClip: https://p5js.org/reference/#/p5/beginClip
Awesome, thanks so much Dave. Will look into both of these.