How to make a passepartout/frame in p5js - p5.js

After I create my canvas in p5js with the following code:
function setup() {
createCanvas(800, 800);
How can I add a white passepartout either around the canvas or inside the canvas?

If you want a frame around the edge of the canvas, another technique would be to draw a wide line on each margin:
let _frameW = 50;
function setup() {
createCanvas(600, 720);
background(153);
strokeWeight(_frameW);
stroke(209);
line(0, _frameW/2, width, _frameW/2);
line(_frameW/2, 0, _frameW/2, height);
line(0, height - _frameW/2, width, height - _frameW/2);
line(width - _frameW/2, 0, width - _frameW/2, height);
}
function draw() {
}

Related

How to show permanent afterimage effect in P5.js?

I'm making a new painting app for an assignment.
What I want for result is that if a user pressed mouse buttons, then white cream is put on the background images and shapes as permanent afterimage effect, following the movement of the mouse.
However when I pressed the mouse buttons, the background images came out as I intended, but the ones with the white cream didn’t work at all.
My current code is:
function setup() {
createCanvas(600,600);
frameRate(100);
}
function draw() {
background(80,30,0);
var size1 = 500;
fill(255);
noStroke();
ellipse(300, 300, size1, size1);
var size2 = 450;
fill(255,217,102);
noStroke();
ellipse(300, 300, size2, size2);
if (mouseIsPressed) {
fill(255,255,255);
noStroke();
triangle(mouseX,mouseY-28,mouseX-24,mouseY+16,mouseX+24,mouseY+16);
fill(255,255,255);
stroke(121,67,21);
strokeWeight(0.1);
triangle(mouseX-24,mouseY-16,mouseX+24,mouseY-16,mouseX,mouseY+28);
}
}
I don’t know what the problem is, and how to solve it.
Could you help me out?
Thank you.
P5.js link of this app is here : https://editor.p5js.org/jwyoon100/full/Kd4JRk87f
You need to move all the background images code into the setup() function, like this:
function setup() {
createCanvas(600,600);
frameRate(100);
background(80,30,0);
var size1 = 500;
fill(255);
noStroke();
ellipse(300, 300, size1, size1);
var size2 = 450;
fill(255,217,102);
noStroke();
ellipse(300, 300, size2, size2);
}
function draw() {
if (mouseIsPressed) {
fill(255,255,255);
noStroke();
triangle(mouseX,mouseY-28,mouseX-24,mouseY+16,mouseX+24,mouseY+16);
fill(255,255,255);
stroke(121,67,21);
strokeWeight(0.1);
triangle(mouseX-24,mouseY-16,mouseX+24,mouseY-16,mouseX,mouseY+28);
}
}

Hide and show background image when keyboard pressed, preserving overlay elements

I would like to paint ellipses over an image when clicking the mouse, and when I press the keyboard, hide and show the underneath image alternatively, without cleaning the ellipses.
I'm using createGraphics() to store the image data, and remove() so when the keyboard is pressed I spect the image disappear but it doesn't work
Here is a sketch of what I trying to do:
let isMouseBeeingPressed = false;
let img;
let isShow = true
let bufferImg;
function preload() {
img = loadImage(
"https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
);
}
function setup() {
createCanvas(500, 500);
background(255);
loadImageBuffer();
}
function loadImageBuffer() {
bufferImg = createGraphics(400, 400);
bufferImg.image(img, 0, 0);
image(bufferImg, 0, 0);
}
function draw() {
if(isMouseBeeingPressed) {
stroke(0, 0, 0, 50);
fill(255);
ellipse(mouseX, mouseY, 20);
}
}
function keyPressed() {
if(isShow) {
bufferImg.remove();
} else {
image(bufferImg, 0, 0);
}
console.log('isShow:', isShow);
return isShow = !isShow;
}
function mousePressed() {
isMouseBeeingPressed = true;
}
function mouseReleased() {
isMouseBeeingPressed = false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Any idea of how to achieve this?
The best approach is probably to draw the ellipses to a separate buffer (p5.Graphics), and then draw that on top of the image or blank background as needed. An alternative approach would be to record the position of each ellipse in an array so that they can be redrawn. However, the latter approach will use more memory and switching the image on and off will have a noticeable delay after many ellipses have been drawn.
Approach #1 (render via p5.Graphics)
let img;
let graphics;
let isShow = true;
function preload() {
img = loadImage(
"https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
);
}
function setup() {
createCanvas(500, 500);
background(255);
image(img, 0, 0);
graphics = createGraphics(width, height);
}
function draw() {
if (mouseIsPressed) {
graphics.stroke(0, 0, 0, 50);
graphics.fill(255);
graphics.ellipse(mouseX, mouseY, 20);
background(255);
if (isShow) {
image(img, 0, 0);
}
image(graphics, 0, 0);
}
}
function keyPressed(e) {
isShow = !isShow;
background(255);
if (isShow) {
image(img, 0, 0);
}
image(graphics, 0, 0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Update: one thing to note about this approach is that whenever the mouse is pressed, the entire scene must be redrawn (white background, image if applicable, and foreground). The reason for this is antialiasing and transparency. When you draw an ellipse on the graphics buffer the edges will have some partially transparent pixels due to antialiasing. If you repeatedly draw the buffer as an overlay without redrawing what is behind it then the partially transparent pixels will become less and less transparent until they are sold black. This will cause your ellipses to have a slightly thicker and more pixelated outer edge.
Approach #2 (Array of ellipse positions)
let img;
let isShow = true
let positions = [];
function preload() {
img = loadImage(
"https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
);
}
function setup() {
createCanvas(500, 500);
background(255);
image(img, 0, 0);
}
function draw() {
if (mouseIsPressed) {
stroke(0, 0, 0, 50);
fill(255);
ellipse(mouseX, mouseY, 20);
positions.push([mouseX, mouseY]);
}
}
function keyPressed() {
isShow = !isShow;
background(255);
if (isShow) {
image(img, 0, 0);
}
stroke(0, 0, 0, 50);
fill(255);
for (const [x, y] of positions) {
ellipse(x, y, 20);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

How to have scalable image with viewport in p5js?

I'm making a website for my design studio and I would like to set image sizes with the p5js language.
Here, I made a function that allows each mouse click to display an image. The problem is that once the image is displayed, it appears at the indicated dimensions, adapt to the screen size but the ratio is not good. The image is either too wide or too extended.
so what do you need to do to display an image with the right original width/height ratio
All your feedback is appreciated.
Thanks in advance !
let works = []
function preload() {
for (let i = 0; i < 6; i++) {
works[i] = loadImage("img/work" + i + ".png")
}
}
function setup() {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '1');
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '1');
}
function draw() {
cursor(CROSS);
}
var counter = 0
function mouseClicked() {
imageMode(CENTER);
counter++
image(works[counter%6], mouseX, mouseY, windowWidth/2, windowHeight/2);
}
The image function can take 3, 5, 7, or 9 parameters, and in each case it has different behavior:
image(img, x, y) - Draw the entire image with it's original size at the specified location
image(img, x, y, width, height) - Draw the entire image, scaled to the specified width and height without preserving aspect ratio, at the specified position.
image(img, dx, dy, dWidth, dHeight, sx, sy, sWidth, sHeight) - Draw a specific part of the image, scaled to the specified width and height without preserving aspect ratio, at the specified position.
The function of the dx, dy, dWidth, dHeight, sx, sy, sWidth, sHeight parameters is explained by this diagram:
In order to draw an image scaled relative to the window size constrained to the aspect ratio of the window, you will need to determine how best to crop your images.
let works = []
function preload() {
works[0] = loadImage("https://www.paulwheeler.us/files/no_idea_why.jpg");
}
function setup() {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '1');
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '1');
}
function draw() {
cursor(CROSS);
}
var counter = 0
function mouseClicked() {
imageMode(CENTER);
counter++
let img = works[counter % works.length];
let windowAspect = width / height;
let imageAspect = img.width / img.height;
let w, h;
// This code naively crops the bottom or right edge of the image as necessary. Obviously there are other ways to limit the image size.
if (windowAspect >= imageAspect) {
// Our window is wider than our image, we need to constrain the height of the image
w = img.width;
h = w / windowAspect;
} else {
// Our window is narrower than or image, we need to constrain the width of the image
h = img.height;
w = h * windowAspect;
}
image(img, mouseX, mouseY, windowWidth / 2, windowHeight / 2, 0, 0, w, h);
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
</body>
</html>

p5 resize window without clearing the background

The following code makes use of the p5dom add-on to position the canvas in the centre of the window. To dynamically resize the canvas I'm using the windowResized() function. I want to keep the background function in setup. How do I prevent the background colour from clearing when I resize the window? Many thanks.
var cnv;
function centerCanvas() {
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
}
function setup() {
cnv = createCanvas(windowWidth,windowHeight);
centerCanvas();
background(255, 0, 200);
}
function draw(){
}
function windowResized() {
centerCanvas();
resizeCanvas(windowWidth,windowHeight)
}
One thing you might do is draw everything to a buffer instead of directly to the screen. The createGraphics() function is your friend here. From the P5.js reference:
var pg;
function setup() {
createCanvas(100, 100);
pg = createGraphics(100, 100);
}
function draw() {
background(200);
pg.background(100);
pg.noStroke();
pg.ellipse(pg.width/2, pg.height/2, 50, 50);
image(pg, 50, 50);
image(pg, 0, 0, 50, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script>
You would want to draw everything to a buffer, and then when the screen is resized, redraw that buffer.
Simply by adding the background function to the draw one too.
Try this:
var cnv;
function centerCanvas() {
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
}
function setup() {
cnv = createCanvas(windowWidth,windowHeight);
centerCanvas();
background(255, 0, 200);
}
function draw(){
//HERE:
background(255, 0, 200);
}
function windowResized() {
//(you can add it here too...)
centerCanvas();
resizeCanvas(windowWidth,windowHeight);
}
I would simply set the background in the windowResized function.
function windowResized() {
centerCanvas();
resizeCanvas(windowWidth,windowHeight)
background(255, 0, 200);
}
For an alternative method, you could use CSS to edit the dimensions using something similar to the following:
<style>
canvas {
width: 100%;
height: 100%;
}
</style>

Processing: transparent image over curves

Im new to Processing. I would like to put a .jpg or .png over curves and ellipses, so that they can see only where the image is transparent.
My code is below. The problem with it is that the transparent area is not fully transparent, but transparent white and the not-transparent parts have also decreased opacity.
PImage img;
void setup() {
size(300,500);
frameRate(30);
strokeWeight(4);
img = loadImage("sziluettmeret.jpg");
}
void draw() {
background(0, 50, 70);
stroke(0,70,90);
noFill();
beginShape();
curveVertex(-100, -100);
curveVertex(10, 10);
curveVertex(250, 250);
curveVertex(300, 300);
endShape();
fill(255);
ellipse(20 ,20,15,15);
noFill();
tint(255, 100);
image(img, 0, 0);
}
UPDATE:
I have this in my code:
loadPixels();
for(int i=0; i < img.pixels.length; i++) {
tmpColor = img.pixels[i];
tmpRed = red(tmpColor);
tmpGreen = blue(tmpColor);
tmpBlue = green(tmpColor);
tmpAlpha = 255 - ((tmpRed + tmpGreen + tmpBlue)/3);
img.pixels[i] = color(2*tmpRed,tmpGreen/2,tmpBlue,0);
if(0xFFFFFF == tmpColor)
}
updatePixels();
The picture does not become transparent. (But it becomes purple, so the loop runs on every pixel for sure)
tint() doesn't do greenscreening. It'll recolor your image (if you use a non-neutral colour), and set the mix transparancy, so with tint(255,100), you effective gave the image an opacity of (approximately) 0.39
If you want to do greenscreening (or in your case, whitescreening), you want to run through the image's pixels when you load the image, then set opacity to 0 whenever r/g/b are 255, effectively "removing" all your white pixels.

Resources