Screen to PGraphic?

Hi!,

Is there a way of directing all drawing instructions to a PGraphics? I’ve already write a program that draw something to the screen and now I want it in a PGraphic. I know that it is not difficult to write the code again. But I was wondering if there was a way to say:" from now on all the commands that usually goes to the screen, go to this PGraphic". Thanks!

1 Like

I can think of three ways to do this. Method one has the least side effects and is perhaps the most relevant solution given your description.

1)
Override all Processing drawing functions (that are used in your program) and pass the call to your PGraphics object. Note that you may have to override multiple different method signatures for a given method.

Overriding one signature of background() for example:

@Override
public void background(float v1, float v2, float v3) {
    myPGraphics.background(v1, v2, v3);
}

From now on, calling background() will pass the call to your PGraphics object. What about calling the background() method normally (on your sketch)? You must call the non-overridden method: this is done by calling super.method() (ie. super.background()).

2)
Maintain all existing code and at end of the draw() loop, draw the current buffer into the PGraphics object. The screen could be cleared thereafter.

Code:

public void draw() {
    .
    .
    .
    myPGraphics.beginDraw();
	myPGraphics.loadPixels();
	myPGraphics.pixels = copy().pixels;
    myPGraphics.updatePixels();
	myPGraphics.endDraw();
    background(255); // optional
}

3)
Change any existing Processing method calls to call your PGraphics object rather than the default PApplet.

Example:

background(0, 0, 0) ---> myPGraphics.background(0, 0, 0)
fill(0, 0, 0)       ---> myPGraphics.fill(0, 0, 0)
2 Likes

Well, Processing already draws onto a PGraphics object – it is called g.

If you want this to be a programmatic method of changing a sketch by just adding a line, you could do this by creating a small library that registers methods for pre, post, and/or draw. This is for example how PeasyCam lets you import peasycam, add a cam, and then the contents of the sketch gets automatically wrapped in its rotation management without changing any of the sketch code.

Can explain what you want to do with the sketch content you are redirecting to a PGraphics?

Very interesting options. :grin:
Thank you very much.

Can explain what you want to do with the sketch content you are redirecting to a PGraphics?

I’m not really sure yet, but I think that some kind of mapping, or window. It’s not about a real project, just thinking.

The main problem in real applications is that, if you are drawing to the canvas every frame and then copying all the pixels off, then you are always wiping the destination buffer every frame, so you lose the potential flexibility of having a drawable graphics buffer in the first place.

So this is better for a snapshot – which you can do anytime with g.copy() or just copy(), giving you a PImage. If you want to make that PImage into a PGraphics for further drawing, then in addition to copying pixels you may want to also copy the pixel density properties. See this example of clonePImageAsPGraphics:

…but then you might want to convert it just-in-time for drawing if you aren’t actually drawing to it every frame.

2 Likes

Jeremey,

Thanks a lot. I really appreciate that you take your time to answer. I know that is the spirit of the group but I’m still in the stage of asking and not answering. :grinning:

Another question: Is it faster to draw to the screen rather than to already created PGraphic object? I know that it takes time and memory to create the PGraphic but if I declare it before?

Thanks again to everybody in the group.

Backup first

In word you can search/replace a line break with line break plus „pg.“

So either use ms word or write a sketch in processing to change your text

Note: computers are there to do repetitive tasks

When in doubt, test. However, faster for what?

If your end goal is to also display the pixels every frame, then line() is probably going to be faster than pg.line(); image(pg) because you will always have that extra copy operation that direct drawing doesn’t have – although you should test, as it might be a negligible difference depending on your image size.

If your goal is to, for example, render a billion circles as fast as possible in setup to create a static image, and you don’t care about screen updating and just want to know which is faster – one billion “line()” or “pg.line()” then just run some test loops with millis(). My guess (?) is that they are almost exactly the same – line() is actually a call to g.line(), so you are drawing to a PGraphics either way.

That’s what I’m seeing with a simple test sketch, anyway. Direct drawing of 100,000 randomly generated colored lines is the same speed using line(), g.line(), or pg.line().

/**
 * DrawToPGraphicsTest
 * 2019-08 Processing 3.4
 * Compare drawing speeds to canvas, to PGraphics, to canvas-PGraphics.
 * Example output:
 *    30048 : 354 , 30402
 *    29335 : 30405 , 59740
 *    29729 : 59742 , 89471
 */
PGraphics pg;
int reps = 100000;

void setup(){
  size(400,400);
  pg = createGraphics(400,400);
}

void draw(){
  if(frameCount==1) testCanvas(reps);
  if(frameCount==2) testGraphics(g, reps);
  if(frameCount==3) testGraphics(pg, reps);
  if(frameCount==4) noLoop();
}

void testCanvas(int reps){
  int startTime = millis();
  for(int i=0; i<reps; i++){
    stroke(random(255),random(255),random(255));
    line(0,random(height),width,random(height));
    line(random(width),0,random(width),height);
  }
  int endTime = millis();
  println(endTime-startTime, ":", startTime, ",", endTime);
}

void testGraphics(PGraphics pg, int reps){
  int startTime = millis();
  pg.beginDraw();
  for(int i=0; i<reps; i++){
    pg.stroke(random(255),random(255),random(255));
    pg.line(0,random(height),width,random(height));
    pg.line(random(width),0,random(width),height);
  }
  pg.endDraw();
  int endTime = millis();
  println(endTime-startTime, ":", startTime, ",", endTime);
}

Great test, thanks!
(as a matter of facts, it took more time for the screen than the PGraphic the first time I try it…:grinning:)