Problems with using filling bixels from bytes stored in file

edited November 2015 in Questions about Code

Hi,

I am trying to use PImage to set the pixels of an image from a series of bytes that I have stored in a .txt file which I am importing using readBytes, but I am a bit confused about the loops and I must be doing something wrong because the image does not update and the program does not get out of the loop.

Help would be much appriciated! Thanks!

Here is the relevant code:

    PImage finger;
    boolean photoRead = false;

    void setup(){
      size(600,600);
      finger = loadImage("fingerimage.png");
    }

    void draw(){
      if(photoRead == false){
        // Open a file and read its binary data 
        byte b[] = loadBytes("fingerprint.txt"); 
        // Print each value, from 0 to 255 
        for (int i = 0; i < b.length; i++) { 
          // Every 258th number, start a new line 
          if ((i % 258) == 0) { 
            println();
          } 
          // bytes are from -128 to 127, this converts to 0 to 255 
          int a = b[i] & 0xff; 
          int dimension = finger.width * finger.height;
          finger.loadPixels();
          for (int j = 0; j < dimension; j += 1) { 
            finger.pixels[j] = color(a);
          }
          // Print a blank line at the end 
          finger.updatePixels();
          photoRead = true;
        }
      }
   }

Answers

  • edited November 2015

    ctrl-t in the processing editor to indent your code. as you've posted it it's all over the place, makes it had to read.

    you also appear to be calling loadPixels and updatePixels for every pixel, which isn't good.

    and what's the value of finger.width on line 23?

  • edited November 2015

    "you also appear to be calling loadPixels and updatePixels for every pixel, which isn't good."

    Ok, so how should I do it to do it differently? I thought that I was only doing it once, like I said Im a bit confused about it as I am new to these things, but what I want to do is to make a dot on every pixel in a 258x258 grid which correspond to the color (grayscale) values that I am trying to read from the file.

    The way I am doing it now is I am importing a placeholder image to adjust but I could also just do it directly (if I knew how to do that) as what I want to achieve is to reconstruct an image that I have in byte format, according to the 0-255 color values that correspond to the -127 to 127 values I have in the file.

    the value of finger.width should be 258 as this is the dimensions of the placeholder image (and supposedly also of the byte image).

  • Ok ,first thing: You can just load the data and create the image in setup(), then you don't have to use the photoRead-boolean.

    You don't have to load a dummy-image, you can create one with createImage(). Then you call loadPixels(), iterate over the byteArray, add 128 to the values and put them in the pixels-array of the image. Then (after the loop) you call updatePixels() on the pixels-array.

    void setup() {
      size(600, 600);
    
      // assume you loaded a byte-array with 200*150 values
      // i create it manually with random values
      byte[] ba = new byte[200*150];
      for (int i =0; i<ba.length; i++) {
        ba[i] = (byte)random(-128, 127);
      }
    
      // create an image with the dimesions that fit to the image
      PImage img = createImage(200, 150, RGB);
    
      img.loadPixels();
      for (int i = 0; i< ba.length; i++) {
        img.pixels[i] = color(ba[i] + 128);
      }
      img.updatePixels();
      image(img, 0, 0);
    }
    
    void draw() {
    }
    

    I didn't understand what that println() was supposed to do, maybe for debugging?

  • Your loadPixels is inside your i loop, so it'll be called for every pixel. The load should be before, the update after.

    As for finger.width, where are you defining it? Nowhere. You define it as a pimage but that does nothing, there's no size or anything.

    Benja's code fixes all these things, and a few others. Study it well.

  • Oh, you are defining finger, sorry, I misread line 6

  • edited November 2015

    Thanks @benja and @koogs for the answers and the example! (and yes, the println was only for debugging)

    I am looking at your code now, but I am a bit unsure about how I should combine these two loops. and what goes where.

    Should I put the loop that makes the image inside the loop that reads the bytes from the file (similar to the order of my code) or the other way around? because if I put them separate from each other I cannot access the variable (right?).

    I cannot unfortunately do this in the setup as this is only a small part of the code, and this sketch is also the one handling the communication with the device that generates the text file(although I am trying it now in a separate sketch), so that file does not exist when the sketch is initialised (therefor the boolean).

    I tried this now which does not give me error but also does not draw anything:

    boolean photoRead = false;
    PImage img = createImage(256, 256, RGB); 
    
    void setup() {
    
      size(600, 600);
    
    }
    
    void draw() {
    
      background(0);
    
      if (photoRead == false) {
    
        img.loadPixels();
        byte ba[] = loadBytes("fingerprint.txt");
    
        for (int i =0; i<ba.length; i++) {
    
          int a = ba[i];
          for (int j = 0; j< ba.length; i++) {
    
            img.pixels[j] = color(a + 128);
    
          }    
        }
    
        img.updatePixels();
        photoRead = true;
    
      }
    
      image(img, 0, 0);
    
    }
    
  • edited November 2015

    There's no place to be found in your code at which photoRead becomes true.
    If "fingerprint.txt" is remotely updated, either reload it at some fixed time, preferably in another thread(), or establish some connection, be it Serial, OSC, network, etc.

    P.S.: Put some empty lines between sections of your code so it's much easier to study it. ;;)

  • edited November 2015

    But it should become trueafter update pixels no?

    But Ok, I will think about putting it in a thread(),

    But that doesn't answer my question about the loops :)

  • photoRead is false on start, and while it is false, it never reaches the part of your code where you set it to true.
    You should set it to true somewhere else ( i.e. in mousePressed() ) and then you set it to false again after loading the new data.
    And you only need one loop. The byte-aray and the pixels-array have the same length, so you can iterate over one of the arrays and just replace each pixel in the pixels[]-array with the manipulated value from your byte-array.
    In my example above i used a second loop at the top only to create a random byte-array, because i did not have your data to load it.

  • Regarding to the topic title, I think bixels is a awesome word :) Could mean a bulk of pixels or something :)

  • edited November 2015 Answer ✓

    Thank you both! I got it now.

Sign In or Register to comment.