Until recently I’ve just been saving all of my images out of Processing using a simple saveFrame command and throwing all of my images into one giant folder. Looking into this folder I see a few key problems. I’ve come up with a little system to help me keep better track of renderings of my generative works. Unfortunately it won’t work retroactively, but it’ll be useful for future work, and perhaps it can be helpful to some other Processors.

This very adding this very simple snipped to a Processing sketch will save out an png of the render window whenever the ‘s’ key is pressed. #### will be replaced by the current frame number.

void keyPressed() {
  if (key=='s') {
    saveFrame("name_of_sketch-####.png");
  }
}

This works out pretty nicely, but if you run the sketch twice and just happen to press ‘s’ on the same frame the first image will be overwritten. Another issue, which might not seem to bad until you have a huge library of images built up, is the order of the files. If the sketch is run many times, all the saved images will be mixed together. Ideally images saved from one run of the sketch should be named sequentially so all the images from one run can be seen together.

Adding an arbitrary value to the particular run and sticking it into the file name fixes these two issues. Many of my scripts include a function to reset the program so it can be run a few times without being completely restarted. In this case, incrementing this arbitrary global value maintains the order of a set of runs.

int G;

void setup() {
  G=floor(random(10000,90000));
  //noiseSeed(G);

}

void draw() {
}

void keyPressed() {
  if (key=='s') {
    saveFrame("name_of_sketch-"+G+"-####.png");
  } else
  if (keyCode==BACKSPACE || keyCode==DELETE) {
    // code to reset script
    G++;
  }
}

This system isn’t perfect, but is a vast organizational improvement for just a few extra lines of code

Another useful trick, if you have a script which utilizes a lot of Perlin Noise, is the set the noiseSeed to a random integer (like G in the script above), and include that in the file name. This way, if you want to rerun the script with the same parameters later, you can always set G to the integer in the file name of a particular saved image.


5 comments

  • Andreas Köberle
    08.25.09

    I use the timestamp to get unique filenames:

    Date dt = new Date();
    SimpleDateFormat df = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss.S”);
    saveFrame(“name_of_sketch-”+df.format(dt)+”.png”);


  • tony
    08.25.09

    Hey, that’s a great idea.

    Thanks!


  • Juego
    08.26.09

    I also use a timestamp but with Processing code only (as SimpleDateFormat is more Java. Thanks for the tip.). So for those not yet comfortable with Java:

    saveFrame(“”name_of_sketch-”+year()+month()+day()+hour()+minute()+second());


  • Juego
    08.26.09

    Oops. (forgot the file extension).

    saveFrame(””name_of_sketch-”+year()+month()+day()+hour()+minute()+second()+”.png”);


  • Bernhard H.
    09.02.09

    I’m saving the run number in a file:

    int runNo;
    void loadRunNo() {
      byte loadedRunNo[] = loadBytes(”runNo.dat”);
      runNo=(loadedRunNo[0] << 24)
        + ((loadedRunNo[1] & 0xFF) << 16)
        + ((loadedRunNo[2] & 0xFF) <>> 24),
      (byte)(runNo >>> 16),
      (byte)(runNo >>> 8),
      (byte)runNo};
      saveBytes(”runNo.dat”, toSaveRunNo);
      println(”run #”+runNo);
    }
    
    DecimalFormat df5E = new DecimalFormat(”00000?);
    void keyPressed() {
      if(key == ’s’ ){
        saveFrame(”shots/sketchname-run-”+df5E.format(runNo)+”-shot-######.png”);
      }
    }

    and in setup():
    loadRunNo();