Saving frame to file without rendering in processing - processing

In Processing, how can I modify an existing sketch which saves each frame to an image file so that it does not render to the screen?
I saw in https://forum.processing.org/one/topic/how-can-i-save-calculate-frame-without-displaying-them-in-real-time.html that you can use PGraphics to draw graphics into an offline buffer, which seems like it would be what I am after, but I am not sure how I can easily modify my existing sketch to use the PGraphics class in that way.
On top of this, I would like the option to render to screen as well if needed by setting a toggle variable.
Is there an easy way of "retrofitting" an existing sketch so that it can use PGraphics instead of the default rendering method (say, in the setup method) so I don't have to go into my sketch and change every single draw command?

You can use a PGraphics object and draw on it just like you would with a canvas. Here's an example sketch with no draw loop which outputs an image file:
void setup() {
PGraphics pg = createGraphics(150, 150);
pg.beginDraw();
pg.background(255);
pg.stroke(0);
pg.fill(color(0, 0, 200));
pg.rect(50, 50, 50, 50);
pg.endDraw();
pg.save("fileName.png");
}
In my sketch's folder, it created this file:
About the other question: I don't think that you can retrofit a written draw loop into a similar output without rendering it in the sketch's window without heavily modifying the code, BUT... if your goal is yo be able to choose between drawing to the sketch window or to a file, you can draw in PGraphics every frame and choose whether if you want to show the PGraphics or not depending on your business rules. You'll still have a lot of refactoring to do, but it's unavoidable.
Here's the same example than before, but implementing this idea:
boolean showFrame = true;
boolean saveFrame = false;
void setup() {
size(150, 150);
}
void draw() {
PGraphics pg = createGraphics(150, 150);
pg.beginDraw();
pg.background(255);
pg.stroke(0);
pg.fill(color(0, 0, 200));
pg.rect(50, 50, 50, 50);
pg.endDraw();
if (showFrame) {image(pg, 0, 0);}
if (saveFrame) {pg.save("fileName.png");}
}
Hope this helps. Have fun!

Related

Pick up a color from canvas

I want to pick up a color from drawn canvas.
I found get() function, but it can get color only from image.
Is there some way to get color from current canvas?
You can get() colour from your current canvas: just address the PGraphics instance you need (even the global one) and be sure to call loadPixels() first.
Here's tweaked version of Processing > Examples > Basics > Image > LoadDisplayImage:
/**
* Load and Display
*
* Images can be loaded and displayed to the screen at their actual size
* or any other size.
*/
PImage img; // Declare variable "a" of type PImage
void setup() {
size(640, 360);
// The image file must be in the data folder of the current sketch
// to load successfully
img = loadImage("https://processing.org/examples/moonwalk.jpg"); // Load the image into the program
}
void draw() {
// Displays the image at its actual size at point (0,0)
image(img, 0, 0);
// Displays the image at point (0, height/2) at half of its size
image(img, 0, height/2, img.width/2, img.height/2);
//load pixels so they can be read via get()
loadPixels();
// colour pick
int pickedColor = get(mouseX,mouseY);
// display for demo purposes
fill(pickedColor);
ellipse(mouseX,mouseY,30,30);
fill(brightness(pickedColor) > 127 ? color(0) : color(255));
text(hex(pickedColor),mouseX+21,mouseY+6);
}
It boils down to calling loadPixels(); before get().
Above we're reading pixels from the sketch's global PGraphics buffer.
You can apply the same logic but reference a different PGraphics buffer depending on your setup.

Can code be called outside of draw() in processing, other than in setup()

According to Processing's translation reference page reference page, "If translate() is called within draw(), the transformation is reset when the loop begins again." Is there any way to call code outside of draw(), other than setup()?
I'm new to Processing, please forgive me if I've overlooked something obvious.
Yes, there are a couple ways you can call translate() and other Processing functions outside of the draw() function.
You could use a static sketch that just draws a single frame without looping:
size(200, 200);
translate(width/2, height/2);
ellipse(0, 0, 100, 100);
This is a full program and will draw a circle in the center of the window.
Or you could put your drawing code inside an event function:
void setup(){
size(200, 200);
}
void draw(){
translate(0, 100);
}
void mousePressed(){
translate(100, 0);
background(32);
ellipse(0, 0, 100, 100);
}
This program draws a circle in the center of the window when the user presses the mouse. But note that the calls to translate() stack: the translate(0, 100) call in draw() and the translate(100, 0) call in mousePressed() are added together so the circle shows up at 100,100. The draw() function is called first, and then the event functions are called.
The reference is just telling you that translation is reset the next time draw() is called.
No, there cannot be called something outside the draw()-function. When you want to use translate() with variable values, then use variables, that define the translation. When you want to translate to the same point each time, then call translate() with constant values at the beginning of each loop...

How do I resize a p5.Graphic object?

In p5.js resizeCanvas(x, y) is a function for p5 objects but if I made a p5.Graphics object, can I resize it with a similar function?
Interestingly, p5.Graphics objects can run resizeGraphics() but nothing happens (including no error) and the height and width remain the same in the console.
g = createGraphics(50, 50); //creates p5.Graphics
g.resizeCanvas(100, 100); //fails: silently without error
g.resize(100, 100); //fails: resize has not been defined
Is there another function or would I need to actually extract the cooresponding graphics canvas and call a native javascript function instead?
Thanks!
If you want to resize a P5.Graphics, you can just create a new one, then draw the old one to the new one.
Here is an example:
var pg;
function setup() {
createCanvas(1000, 1000);
pg = createGraphics(100, 100);
pg.background(100);
pg.noStroke();
pg.ellipse(pg.width/2, pg.height/2, pg.width, pg.height);
}
function draw() {
background(200);
image(pg, 0, 0);
}
function mouseClicked(){
var newPG = createGraphics(mouseX, mouseY);
newPG.image(pg, 0, 0, newPG.width, newPG.height);
pg = newPG;
}
Using resizeCanvas on a graphics object created with "createGraphics" seems to stretch the graphics rather than resize the buffer.
Right now the best way to resize a graphics object is to simply set the width and height properties directly.
// Some graphics object
let graphics = createGraphics(w,h);
// Now simply resize like this
graphics.width = gWidth;
graphics.height = gHeight;
As suggested here:
https://github.com/processing/p5.js/issues/2064#issuecomment-315503533

changing center of rotation for a shape in processing

I am trying to rotate a vector I have created in illustrator using processing. I would like it to rotate this vector from it's center so it appears to be spinning as oppose to moving around an invisible point. Below is my attempt:
PShape WOE;
void setup(){
WOE = loadShape("WOE.svg");
size (500, 500);
smooth();
}
void draw(){
background(20);
shape(WOE, width/2, height/2, WOE.width, WOE.height); //draw shape in "center" of canvas (250, 250)
translate(-WOE.width/2, -WOE.height/2); //move shape so that center of shape is aligned with 250, 250
WOE.rotate(0.01);
}
From a strictly logical point of view this should work, however this results in the vector rotating around the center of the canvas, but approximately 100px away. I have tried using shapeMode(CENTER); but this unfortunately causes no improvement. Hope someone can help, thanks!
For Reference
Here is WOE.svg: https://www.dropbox.com/s/jp02yyfcrrnep93/WOE.svg?dl=0
I think part of your problem is that you're mixing rotating the shape and translating the entire sketch. I would try to stick with one or the other: either translate and rotate the entire sketch, or only translate and rotate the shape.
That being said, I'm not surprised this gave you trouble.
I would expect this to work:
PShape WOE;
void setup() {
size (500, 500);
WOE = loadShape("WOE.svg");
WOE.translate(-WOE.width/2, -WOE.height/2);
}
void draw() {
background(20);
WOE.rotate(.01);
shape(WOE, width/2, height/2);
}
However, this exhibits the same off-center behavior you're noticing. But if I switch to the P2D renderer, it works fine!
size (500, 500, P2D);
Now the shape is centered in the window and rotates around the shape's center. The difference between renderers seems buggy, but I can't find an open bug on GitHub. Edit: I found this SO question, which lead to this GitHub issue.
In any case, it might be easier to rotate the entire sketch instead of the shape:
PShape WOE;
float rotation = 0;
void setup() {
size (500, 500);
WOE = loadShape("WOE.svg");
shapeMode(CENTER);
}
void draw() {
background(20);
translate(width/2, height/2);
rotate(rotation);
shape(WOE);
rotation += .01;
}
This code works by translating the entire sketch to the center of the window, then rotating the entire sketch, then drawing the shape. Think of this like moving the camera instead of moving the shape. If you have other stuff to draw, then you can use the pushMatrix() and popMatrix() functions to isolate the transformation. This works the same in the default renderer and the P2D renderer.

image quality loss when scaling down

My image is 200px x 200px size. When I'm trying to draw it as 100px x 100px the image is being rendered awfull and unacceptable.
#Override
public void render(SpriteBactch batch){
batch.begin();
batch.draw(img, 0, 0,100,100);
batch.end();
}
When I'm drawin it like this:
#Override
public void render(SpriteBactch batch){
batch.begin();
batch.draw(img, 0, 0);
batch.end();
}
it has acceptable quality. Can i fix this and how? Below you can find screenshot from image rendering:
try to apply your Texture Linear TextureFilter
Texture texture = new Texture(... //creating your texture
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear); //add this line
Sprite img = new Sprite(texture);
Please notice that when you are scaling picture down there is always quality loose risk so you can still can be not satisfied with the result.
To get some information about TextureFilter and how to deal with them just read:
http://www.badlogicgames.com/wordpress/?p=1403

Resources