How to build PImage objects to a buffer programatically?

edited March 2014 in How To...

I am building a sketch that uses data from a CSV file to plot points on a circular graph. The circle is made up of individual wedges that when combined create an entire circle. The number of data points inside of each wedge might be different depending on the data as might the total number of wedges.

I would like to draw the wedges to an off screen buffer as referenced in this article: http://wiki.processing.org/w/Draw_to_off-screen_buffer

So far I have a method that will create the individual wedges and store these objects in a list. How can I then display these objects? The number of PImage objects that would need to be created in the setup() would be changing based on the data as would the number of image(img, 0, 0) commands in the draw().

Any help is appreciated!

Answers

  • First question, why use an off-screen buffer?

    Second question: have you tried to draw on-screen? Converting then to off-screen is rather trivial.

    Third question: why would you create several PImage? BTW, off-screen buffers rather use PGraphics.

  • @PhiLho I chose to use the PImage to draw off-screen since I was drawing many shapes at once and I thought this would be a good alternative to drawing them continually. I have been struggling with how to draw these for a while and I am open to other ways of drawing. Right now I am making a PGraphic off-screen saving it into a PImage and then showing the image in the draw() with image(img, 0, 0).

    Right now I am drawing quads to get the shapes that I want. When I draw all of them on screen it slows down the framerate to a crawl so after reading the article mentioned earlier I tried the PImage. Here is what I am drawing at the moment:

    seeThru

    My goal is to interact with these wedges so that I could do things such as: hover-overs, selections and exploded views. Something like this:

    select

    So maybe I should rewind a little and ask do you have any recommendations about how to approach this problem? Maybe I am really off base with my approach. I am open to any suggestions. Thanks!

  • OK, looks like good reasons. I ask because sometime, people come up with convoluted solutions when one can use simpler ones.

    You should make an array list of PGraphics: this allows to have as many as you want, adding one if needed. Then you can iterate on this list to display all the shapes.

    Here a simple, quickly made illustration of my point:

    ArrayList<PGraphics> images = new ArrayList<PGraphics>();
    
    void setup()
    {
      size(800, 800);
    
      for (int i = 0; i < 10; i++)
      {
        PGraphics image = createGraphics(width, height, JAVA2D);
        drawOn(image);
        images.add(image);
      }
    }
    
    void draw()
    {
      background(255);
    
      for (PGraphics image : images)
      {
        image(image, 0, 0);
      }
    }
    
    void drawOn(PGraphics image)
    {
      image.beginDraw();
      image.fill(random(20, 100), random(150, 240), random(100, 200), 128);
      image.rect(random(10, width / 2), random(10, height / 2),
          random(10, width / 2 - 10), random(10, height / 2 - 10));
      image.endDraw();
    }
    
  • @PhiLho ok this looks like it will work! I have another question.....

    Is it possible to now interact with the PGraphics elements that are being stored in the list?

    I tried to modify them as they were being drawn from the loop like this:

    for (PGraphics image : images)
      {
        image.fill(255, 0, 0);
        image(image, 0, 0);
      }
    

    but this method doesn't seem to work.

  • edited March 2014

    In order for the modifications in the PGraphics object take effect, we gotta issue -> endDraw().
    In some cases, even beginDraw() is needed before even start them! But I guess it's very rare! :@)

  • @GoToLoop I tried adding both beginDraw() and endDraw() to that portion of the code and it doesn't seem to change the result. However I can add things to the PGraphics object but I can't modify the existing ones at least not with this method.

    This does work:

    for (PGraphics image : images)
      {
        image.ellipse(150, 150, 50, 50);
        image.endDraw();
        image(image, 0, 0);
      }
    

    This does not work:

    for (PGraphics image : images)
      {
        image.fill(255, 0, 0);
        image.endDraw();
        image(image, 0, 0);
      }
    

    Is it possible to modify the existing PGraphics objects?

  • Method fill() changes the filler color used for future drawings! 3:-O

  • @GoToLoop Is it possible to modify the objects dynamically as they are coming out of the list but haven't yet been drawn on the screen?

    I need to interact with the elements after their initial drawing to the screen.

  • clear the PGraphics and redraw on it?

  • edited March 2014

    @PhiLho I added this bit to the code (mousePressed) to clear the buffer and it works...kind of.

    I am probably missing something stupid but the only time that clearing the buffer with a mouse click (for this example) is when I try to clear the last element in the list. Do you know why this is the case?

    ArrayList<PGraphics> images = new ArrayList<PGraphics>();
    PGraphics img;
    
    void setup()
    {
      size(800, 800);
    
      for (int i = 0; i < 10; i++)
      {
        img = createGraphics(width, height, JAVA2D);
        drawOn(img);
        images.add(img);
      }
    }
    
    void draw()
    {
      background(255);
    
      for (PGraphics image : images)
      {
        image(image, 0, 0);
      }
    }
    
    void drawOn(PGraphics image)
    {
      image.beginDraw();
      image.fill(random(20, 100), random(150, 240), random(100, 200), 128);
      image.rect(random(10, width / 2), random(10, height / 2),
          random(10, width / 2 - 10), random(10, height / 2 - 10));
      image.endDraw();
    }
    
    void mousePressed()
    {
      images.get(9).clear();
      drawOn(img);
    }
    
  • Answer ✓

    Why img became global? It has no real meaning, it just hold the last image assigned to it. And don't use "magical" numbers like 9, it will be wrong if you change the size of the list!

    ArrayList<PGraphics> images = new ArrayList<PGraphics>();
    
    void setup()
    {
      size(800, 800);
    
      for (int i = 0; i < 10; i++)
      {
        PGraphics image = createGraphics(width, height, JAVA2D);
        drawOn(image);
        images.add(image);
      }
    }
    
    void draw()
    {
      background(255);
    
      for (PGraphics image : images)
      {
        image(image, 0, 0);
      }
    }
    
    void drawOn(PGraphics image)
    {
      image.beginDraw();
      image.fill(random(20, 100), random(150, 240), random(100, 200), 128);
      image.rect(random(10, width / 2), random(10, height / 2),
          random(10, width / 2 - 10), random(10, height / 2 - 10));
      image.endDraw();
    }
    
    void mousePressed()
    {
      for (int i = 0; i < images.size(); i++)
      {
        PGraphics image = images.get(i);
        image.clear();
        drawOn(image);
      }
    }
    
  • @PhiLho Yea it was global variable that was screwing it up the clear. Thanks!

    The reason that I was using a number rather than an iterator is because I want to make sure that I could access one PGraphics at a time and not affect the rest. I would rather not re-draw everything back to the screen after modifying one PGraphic in the list but I think that this will work! Thanks so much for your help!!

Sign In or Register to comment.