Fast way to get a pixel color

If I have lets say 100 PGraphics and I want to get only 1 pixel at (x,y) every frame, what is the fastest and optional way by knowing that

get(x,y);

is slow

pixels[I]

too

and using a java robot .getPixel() is perfect for the speed but only gets the final image after draw is executed

here is a exemple

PGraphics[] pgs = new PGraphics[100];

Robot robot;

void setup() {
  size(500,500);

  //
  for(int i=0; i<100; i++) {
  pgs = createGraphics(width, height);
  }

  try { robot = new Robot(); } catch(Exception e) {}
}

void draw() {
  background(0);

  for(int i=0; i<100; i++) {
    image(pgs,0,0);
    int pix = robot.getPixelColor(width/2,height/2).getRGB;
    println(pix);
  }

  background(255);
}

what is the fastest solution to get a pixel at every frame ?

Tagged:

Answers

  • get(x,y), loadPixels(), etc... are all rather slow, but it also depends on the used renderer (OpenGL or Java).

    one trick is to render all the pixels you want to to another pgraphics (pg_read in this example), and then read the pixels of that buffer at once.

    
      PGraphics[] pg_list = new PGraphics[255];
      
      PGraphics pg_one;
      PGraphics pg_read;
      
      public void settings() {
        size(500, 500);
      }
      
      public void setup() {
    
        int count = pg_list.length;
       
        // set a different background for each PGraphics
        for(int i = 0; i < count; i++) {
          PGraphics pg  = createGraphics(width, height);
          pg.beginDraw();
          pg.background(i);
          pg.endDraw();
          pg_list[i] = pg;
        }
        
        // our buffers for reading pixels
        pg_read = createGraphics(count, 1);
        pg_one = createGraphics(1, 1);
    
        // read pixel values
        int[] argb = getPixelColors(width/2, height/2);
        // print pixel values
        printPixelColors(argb);
        
        frameRate(1000);
      }
       
      public void draw() {
        background(0);
        
        int[] argb = getPixelColors(mouseX, mouseY);
        // printPixelColors(argb);
        
        surface.setTitle(""+frameRate);
      }
      
      
      
      public void printPixelColors(int[] argb){
        for(int i = 0; i < argb.length; i++){
          int r = (argb[i] >> 16) & 0xFF;
          int g = (argb[i] >>  8) & 0xFF;
          int b = (argb[i] >>  0) & 0xFF;
          System.out.printf("rgb = %d,%d,%d\n", r,g,b);  
        }
      }
      
      
      public int[] getPixelColors(int px, int py){
        // note: it would be more efficient to use a stencil buffer here and
        //       draw directly, like: pg_read.image(pg_list[i], i -px, -py);
        for(int i = 0; i < pg_list.length; i++) {
          pg_one.beginDraw();
          pg_one.blendMode(REPLACE);
          pg_one.image(pg_list[i], -px, -py);
          pg_one.endDraw();
          
          pg_read.beginDraw();
          pg_read.blendMode(REPLACE);
          pg_read.image(pg_one, i, 0);
          pg_read.endDraw();
        }
    
        pg_read.loadPixels();
        return pg_read.pixels;
      }
    
  • T_DT_D
    edited July 2017 Answer ✓

    the above example can be improved by using the clip() function:

    
      PGraphics[] pg_list = new PGraphics[255]; 
      PGraphics pg_read;
      
      public void settings() {
        size(500, 500);
      }
      
      public void setup() {
    
        int count = pg_list.length;
       
        // set a different color for each PGraphics, for debugging
        for(int i = 0; i < count; i++) {
          PGraphics pg  = createGraphics(width, height);
          pg.beginDraw();
          pg.noStroke();
          pg.fill(i);
          pg.rect(width/2, height/2, 1, 1);
          pg.endDraw();
          pg_list[i] = pg;
        }
        
        // buffer for reading pixels
        pg_read = createGraphics(count, 1);
    
        // read pixel values
        int[] argb = getPixelColors(width/2, height/2);
        // print pixel values
        printPixelColors(argb);
        
        frameRate(1000);
      }
       
      
      public void draw() {
        background(0);
        
        int[] argb = getPixelColors(width/2, height/2);
        // printPixelColors(argb);
        
        surface.setTitle(""+frameRate);
      }
      
      
      public void printPixelColors(int[] argb){
        for(int i = 0; i < argb.length; i++){
          int r = (argb[i] >> 16) & 0xFF;
          int g = (argb[i] >>  8) & 0xFF;
          int b = (argb[i] >>  0) & 0xFF;
          System.out.printf("rgb = %d,%d,%d\n", r,g,b);  
        }
      }
      
      
      public int[] getPixelColors(int px, int py){
        pg_read.beginDraw();
        pg_read.blendMode(REPLACE);
        for(int i = 0; i < pg_list.length; i++) {
          pg_read.clip(i, 0, 1, 1);
          pg_read.image(pg_list[i], i -px, -py);
        }
        pg_read.endDraw();
        pg_read.loadPixels();
        return pg_read.pixels;
      }
    
    
  • The original code doesn't use the array, just keeps overwriting one image. Line 10.

    It also copies that image to the screen 100 times when it can access the pixels without doing that.

    In short, no wonder it is slow.

  • As koogs said:

    It also copies that image to the screen 100 times when it can access the pixels without doing that.

    That one line:

    image(pgs,0,0);
    

    is probably very time consuming, and accomplishes nothing in the loop (or ever after you blank it out).

  • edited July 2017

    thank you for introducing me to the clip() function and for you examples, now that I have this technic that works perfectly.

    PROBLEM + SOLUTION

    How could I replace all the pixels color in all of these 100 graphics by a X color if the currently checking pixel color is not equal to a color Y in a fast way ? Because in my main sketch I want to know if the pixel at (x,y) is == to a color, so if the color is alpha = 0, then it would be considered as not a color, and because we merge every pgraphics in 1 graphics, we would need to replace all these alpha != 0 color by a "Color representing this Graphics" so I would need a system to store the current (i) variable from the for loop in 3 channels and 255 * 255 * 255 = 16581375, its limited but it is too high to go higher than that number in my case.

    WHAT I NEED

    Why I need to do all this is basically to know if pixel at (x,y) is on a graphics and if yes which one.

    sorry for my errors I speak French

  • okay ! never mind for the theory I had, thank you again T_D, the clip() function all arranged and I have a fully functional 60 fps sketch :D

Sign In or Register to comment.