load Images on Thread

I made a class so i can load images on a thread. The idea is to display them without having a huge framedrop. If i comment: load(filenameIndex); in the get() method then it works. I only don't understand why it doesn't work without that commented. Since it should detect that a image is already loaded and therefor not load it.

Any help is welcome.

PImageSequence imgSec;

void setup() {

  size(800, 600);

  String[] filenames = new String[145-28];
  for (int i = 0; i < filenames.length; i++) {
    filenames[i] = (i+28)+".png";
  }

  // filenames, buffersize, threaded
  imgSec = new PImageSequence(filenames, 64, true);

  imgSec.fillBuffer();

}

// . . . . . . . . . . . . . . . . . . . . . .


void draw () {
  image(imgSec.getNext(), 0, 0);
  fill(0);
  text(frameRate, 20, 20);
}

the class:

    import java.util.Arrays;

class PImageSequence extends Thread {

  // for the Threading
  boolean running;
  int wait = 1;


  PImage[] imgBuffer;
  int bufferSize;

  String[] filenames;
  // be aware that is has the length of the buffer
  int[] loadedIndex;

  int filenameIndex;


  PImageSequence(String[] filenames) {
    createBuffer(64);
    setImages(filenames);
    // not Threaded!
  }

  PImageSequence(String[] filenames, int bufferSize) {
    createBuffer(bufferSize);
    setImages(filenames);
    // not Threaded!
  }

  PImageSequence(String[] filenames, int bufferSize, boolean threaded) {
    createBuffer(bufferSize);
    setImages(filenames);
    if (threaded) start();
  }

  // . . . . . . . . . . . . . . . . . . . . . .

  void start() {
    running = true;
    super.start();
  }  

  // . . . . . . . . . . . . . . . . . . . . . .

  void run() {
    while (running) {

      if (filenameIndex != -1) {

        // load ahead
        // never load more then half the buffersize ahead
        // this way going back won't cause a huge framedrop
        int h_bufferSize = bufferSize/2;

        // find the first occurence where preLoadIndex is not the correct fileIndex   
        for (int i = 0; i < h_bufferSize; i++) {
          int checkIndex = (filenameIndex + i) % filenames.length;
          println(filenameIndex, checkIndex);
          //println(filenameIndex);
          //println(filenames.length);
          if (load(checkIndex)) {
            println("load:", checkIndex);
            break;
          }
          //
        }
      }
      //  int preLoadIndex = filenameIndex + h_bufferSize;
      //  if (preLoadIndex >= filenames.length) preLoadIndex -= filenames.length;

      //boolean didLoad;

      //      for (int i = filenameIndex; i < min(preLoadIndex, filenames.length) ; i++) {
      //        if(loadedIndex[i] != filenames 
      //      }

      //load(preLoadIndex);

      // println(filenameIndex, preLoadIndex);

      try {
        sleep((long)(wait));
      } 
      catch (Exception e) {
      }
    }
  }  

  // . . . . . . . . . . . . . . . . . . . . . .

  void quit() {
    running = false;  // Setting running to false ends the loop in run()
    // IUn case the thread is waiting. . .
    interrupt();
  }

  // . . . . . . . . . . . . . . . . . . . . . .


  private void createBuffer(int bufferSize) {
    this.bufferSize = bufferSize;
    imgBuffer = new PImage[bufferSize];
    loadedIndex = new int[bufferSize]; 
    Arrays.fill(loadedIndex, -1);
  }  

  // . . . . . . . . . . . . . . . . . . . . . .


  public void setImages(String[] filenames) {
    if (this.filenames == null || this.filenames.length != filenames.length) {
      this.filenames = new String[filenames.length];
    }
    for (int i = 0; i < filenames.length; i++) {
      this.filenames[i] = filenames[i];
    }
    // 0 or -1?
    filenameIndex = -1;
    Arrays.fill(loadedIndex, -1);
  }

  // . . . . . . . . . . . . . . . . . . . . . .


  PImage get() {
    filenameIndex = max(filenameIndex, 0);
    if (filenameIndex == filenames.length) filenameIndex = 0;

    load(filenameIndex);

    //println(filenameIndex);
    //println();
    //println(loadedIndex);

    return imgBuffer[filenameIndex % bufferSize];
  }

  // . . . . . . . . . . . . . . . . . . . . . .


  PImage getNext() {
    filenameIndex++;
    return get();
  }


  // . . . . . . . . . . . . . . . . . . . . . .


  void fillBuffer() {
    for (int i = 0; i < min(bufferSize, filenames.length); i++) {
      load(i);
    }
  }

  // . . . . . . . . . . . . . . . . . . . . . .


  private boolean load(int filenameIndex) {
    int bufferIndex = filenameIndex % bufferSize; 

    if (loadedIndex[bufferIndex] == filenameIndex) return false;

    //println("load");
    println("load->:", filenameIndex);

    imgBuffer[bufferIndex] = loadImage(filenames[filenameIndex]);

    loadedIndex[bufferIndex] = filenameIndex;
    return true;
  } 


  // . . . . . . . . . . . . . . . . . . . . . .


  void clear() {
    imgBuffer = null;
    filenames = null;
    loadedIndex = null;
    filenameIndex = 0;
  }

  // . . . . . . . . . . . . . . . . . . . . . .
}
Tagged:

Answers

  • Since it should detect that a image is already loaded and therefor not load it.

    What makes you think this is the case? What are the values of every variable in this part of the code when it's loading when you think it shouldn't be? Print statements are your friend here.

  • I figured it out. It's not possible what i want. It takes often 2 frames time to load an image. So it's only one time the buffer size ahead, after that it has to catch up :(

  • Thanks, good to know. But also that won't help. Using images with less compression might help. But for now i just create a buffer the size equal to the amount of images i want.

Sign In or Register to comment.