save frame to different folder

hello all. I want to save a frame to a folder different than the sketch folder. I have looked online how to do this but I have found no clear answers. If the code is necessary, I will post it, but i feel as though it is too long to merit posting right now. Thanks for your help.

Answers

  • if you want it to be a sub-folder of the sketch folder then

    save("subFolder/file.jpg")
    

    if you want to same it somewhere completely different use the full path name:

    save("/full/path/name/file.jpg");
    

    (linux paths used in examples)

  • I tried doing what you said, and it turn it only saves one image, and creates a new group of folders in my sketch folder, with the file inside another folder labeled documents inside one labeled name inside one labeled Users. The image never changes and no new files are ever added.

      frame = str(savefrnum);
      saveFrame(frame);
      save("Users/Kiran/Documents/Processing/GA3_Graphs/frame.jpg");
      savefrnum ++;
    
  • https://forum.processing.org/two/discussion/14595/simple-file-operations/p1

    https://processing.org/reference/save_.html

    These files are saved to the sketch's folder, which may be opened by selecting "Show sketch folder" from the "Sketch" menu. Alternatively, the files can be saved to any location on the computer by using an absolute path (something that starts with / on Unix and Linux, or a drive letter on Windows).

    Give it a try using the info in the first link. The second link is a reference. Post all your code as well as it will help to tackle your issue.

    Kf

  • Line 3 is relative pathname, you need an absolute one, so add a drive letter if you're using windows, a leading / on other systems.

    SaveFrame uses # symbols in the filename and replaces them with numbers. We can't see what you are using in the snippet you posted.

  • edited August 2016

    Here is all the code. The save in question is at 347 (Right before the Ball class and at the end of the checkMove() function.

    ArrayList<Ball> balls = new ArrayList(); // arraylist for ball objects
    ArrayList<Point> points = new ArrayList();
    ArrayList<BPoint> bpoints = new ArrayList();
    float gcorX, gcorY; // goal coords
    int timeIter = 300; //time step- internal clock
    float bscore; //best score
    String[] str_a;   //one copy of scorelist (use to copies to determine best and worst)
    String[] str_b;   //one copy of scorelist (use to copies to determine best and worst)
    float[] scores;   //scorelist
    final int pop = 10; //population size- final bc it shouldnt be changed in the program
    int cur_sub;      //current iteration- OLD METHOD, but still in just in case
    public int gen_num = 0; //count generation number
    int countDone; // count how many balls in the population finished their run in that generation
    float diameter = 30;
    float globmin = 1000; //base var
    float [] generations; // array of generations
    float topgoal;
    Ball globalBall = new Ball(-1, "0"); // starter/ global best ball
    int movCounter = 0;
    
    int margin = 300;
    
    float stepCounter = 0;
    float totalCounter = 0;
    int totalFailCounter = 0;
    char savefrnum = 'a';
    String frame;
    
    //String userHome = System.getProperty("user.home");
    
    //Start Setup_______________________________________________________________________________________________________________________________________
    void setup() {
      size(1600, 1000);
      surface.setResizable(true);
      background(0);
      frameRate(60);
    
      generations = new float[gen_num]; // init generations with size
    
      bscore = dist(0, 0, width, height); // calc score
      gcorX= random(0, (width-margin));
      gcorY= random(height);
    
      ellipseMode(CENTER);
    
      //begin init scorestrings
      str_a = new String[pop];
      str_b = new String[pop];
      scores = new float[pop];
      for (int j = 0; j<pop; j++) {
        str_a[j] = starterString();
        scores[j] = 0;
      }
      //end init scorestrings
    
      //for every done ball, add a new one/replace it
      cur_sub = -1;
      countDone = 0;
      for ( int i=0; i < pop; i++ ) balls.add( new Ball( i, str_a[i] ) );
    }
    //End Setup_________________________________________________________________________________________________________________________________________
    
    
    //begin init of starter string( Initial) so that the mutation has a place to begin
    String starterString() {
      String mut = "" + char( '0' + int( random(4) ) ); //  + "00000000" ;
      return( mut );
    }
    
    
    //end init
    
    //begin init instructions and strings of values- cr and hr refer to the textlines explaining each movement. r is a placeholder string so that the strings return a value to it based on the results of the cr loop
    
    
    String hr( String cr ) {
      String r = "";
      for ( int t = 0; t < cr.length(); t++) {
        if ( cr.charAt(t) == '0' ) r+= 'N';
        if ( cr.charAt(t) == '1' ) r+= 'L';
        if ( cr.charAt(t) == '2' ) r+= 'R';
        if ( cr.charAt(t) == '3' ) r+= 'A';
      }
      return( r );
    }
    //end init instructions and cr/hr
    
    //Begin Draw_______________________________________________________________________________________________________________________________________
    void draw() {
      background(0); //layer 2
      fill(255, 0, 0); //red
      //starting pad
      pushMatrix();
      stroke(255, 200);
      fill(0, 255, 0, 200);
      ellipse(width/2, height/2, 25, 25);
      popMatrix();
      //end starting pad
    
    
      //String extra = ""; //message
      //if ( bscore < 20 ) extra = "That's close enough! Click the mouse to move the goal."; //message
    
      //text inits and placements
      pushMatrix();
      fill(255, 0, 0);
      text("| Best ever: (" + hr(globalBall.genome) + ") = " + int(bscore) + " |", 50, 20 );
      popMatrix();
    
      pushMatrix();
      fill(255, 200);
      text("| key: A = accelerate, R = right, L = left, N = do nothing | ", 500, height-20);
      popMatrix();
    
      pushMatrix();
      fill(0, 0, 255);
      text("| minimum of gen:" + (min(scores))+ " |", 400, 20);
      popMatrix();
    
      //pushMatrix();
      //fill(255, 255, 0);
      //text("| Diagnostics and System |", width-margin +20, 20);
      //text("| Iteration time (internal): " + (stepCounter)+ " |", width-margin +20, 45);
      //text("| Iteration time (seconds): " + (stepCounter/60)+ " |", width-margin +20, 60);
      //text("| Iteration time (minutes): " + (stepCounter/3600)+ " |", width-margin +20, 75);
      //text("| Total time (internal): " + (totalCounter)+ " |", width-margin +20, 100);
      //text("| Total time (seconds): " + (totalCounter/60)+ " |", width-margin +20, 115);
      //text("| Total time (minutes): " + (totalCounter/3600)+ " |", width-margin +20, 130);
      //popMatrix();
    
      pushMatrix();
      fill(255, 255, 0, 150);
      stroke(255, 150);
      text("Diagnostics and System", width-margin +20, 20);
    
      line(width-margin, 30, width, 30);
    
      text("Iteration time (internal): " + (stepCounter), width-margin +20, 50);
      text("Iteration time (seconds): " + (stepCounter/60), width-margin +20, 65);
      text("Iteration time (minutes): " + (stepCounter/3600), width-margin +20, 80);
      text("Total time (internal): " + (totalCounter), width-margin +20, 105);
      text("Total time (seconds): " + (totalCounter/60), width-margin +20, 120);
      text("Total time (minutes): " + (totalCounter/3600), width-margin +20, 135);
      text("Time before iteration fail: 10 minutes", width-margin +20, 160);
      text("Total completed iterations: " + movCounter, width-margin +20, 175);
      text("Total failed iterations: " + totalFailCounter, width-margin +20, 190);
      line(width-margin, 200, width, 200);
    
      popMatrix();
    
    
      pushMatrix();
      fill(0, 0, 255);
      //text(extra, 30, height -20);
      fill(#FF932E);
      text("| Generation " + gen_num+ " |", 280, 20 );
      text("| best:" + (bscore)+ " |", 600, 20);
      text("| Times moved: " + movCounter + " |", 750, 20);
      popMatrix();
      //end text inits and placements
    
      //globmin = min(globmin, min(scores));
      //text("globmin: " + globmin, 250, 34);
    
    
      //text for genome (hr/cr);
      for ( int tt=0; tt< pop; tt++) {
        fill (balls.get(tt).col);
        text( "(" + hr( balls.get(tt).genome ) + ")", 10, 48 + 14 * tt);
      }
      //text for genome (hr/cr);
    
      // If no ball, last ball is done, simulate next one.
      // If all balls done, simulate next generation.
      if ( countDone == pop ) { // balls.size() == 0 ) {
        while ( balls.size() > 0 ) balls.remove(0); 
        //cur_sub++;
        // If all balls in this generation simulated, create next generation.
        //if ( cur_sub == gen_size ) {
        countDone = 0; // cur_sub = 0;
        //println( "Making next generation..." );
    
    
        // Always keep the best one, and toss the worse.
        arrayCopy( str_a, str_b ); //copy for scrambling later
        int bestIndex = 0;
        // int secondbestIndex = 0;
        int worstIndex = 0;
        // int secondworstIndex = 0;
        for ( int j = 0; j < pop; j++ ) {
          if ( scores[bestIndex] > scores[j] ) {
            bestIndex = j;
          } //getting best score for index
    
          if ( scores[worstIndex] < scores[j] ) {
            worstIndex = j;
          }
          //getting worst score for index
        }  
    
        //for ( int k = 0; k < pop; k++ ) {
        //  if ( scores[secondbestIndex] > scores[k] && scores[secondbestIndex] != bestIndex) {
        //    bestIndex = k;
        //  } //getting second best score for index
    
        //  if ( scores[secondworstIndex] < scores[k] && scores[secondworstIndex] != worstIndex) {
        //    secondworstIndex = k;
        //  }
        //  //getting second worst score for index
        //}
    
        str_b[worstIndex] = str_b[bestIndex]; // Replace the worst with a copy of the best for breeding.
        //str_b[secondworstIndex] = str_b[secondbestIndex];
    
        // Scramble.
        for ( int j = 0; j < pop; j++ ) {
          str_a[j] = scramble( j, str_b[int(random(pop))], str_b[int(random(pop))] ); //scrambles initial a(stored in b) and replaces old a with new values
        }
        str_a[0] = str_b[bestIndex]; // Always keep the best.
        //Add all the balls to simulate.
    
        for ( int j = 0; j < pop; j++ ) {
          balls.add( new Ball( j, str_a[j] ) );
        }
    
        gen_num++; //increment generation counter
    
        Point p = new Point((gen_num*4), (min(scores)+292.89)); //the 292 is the difference between the furthest away and 1000, bc height goes from top left down increasing
        points.add(p);
        BPoint q = new BPoint((gen_num*4), (bscore+292.89));
        bpoints.add(q);
      }
    
      globalBall.render(); // draw best as red(see coloring above in beginning of draw)
    
      for ( int i=0; i < balls.size(); i++ ) balls.get(i).move(); //init move function for balls
    
      //begin goal init
    
      stroke(255);
      fill(255, 140);
      ellipseMode(CENTER);
      ellipse(gcorX, gcorY, diameter, diameter);
    
    
      pushMatrix(); 
      strokeWeight(1);
      stroke(0, 0, 255, 20);
      noFill();
      beginShape();
      for (Point pt : points) pt.displaypt();
      endShape();
      popMatrix();
    
    
      pushMatrix(); 
      strokeWeight(1);
      stroke(255, 0, 0, 20);
      noFill();
      beginShape();
      for (BPoint bpt : bpoints) bpt.displayBpt();
      endShape();
      popMatrix();
    
    
      if (mousePressed ==true) {
        for (int i = points.size(); i-- != 0; points.remove(i));
        for (int i = bpoints.size(); i-- != 0; bpoints.remove(i));
        //saveFrame(str(savefrnum));
        //savefrnum ++;
      }
    
      //topgoal =  dist(width/2, height/2, gcorX, gcorY);
      //pushMatrix();
      //stroke(0, 255, 0, 50);
      //strokeWeight(2);
      //line(0, topgoal, width, topgoal); 
      //popMatrix();
    
      if (bscore<30 || stepCounter>36000) {
    
        if (stepCounter>36000) {
          println("This iteration ("+movCounter+") failed");
          totalFailCounter++;
          saveFrame(str(savefrnum));
          savefrnum ++;
        }
        println("moving, score: "+ bscore);
        checkMove(); 
        for (int i = points.size(); i-- != 0; points.remove(i));
        for (int i = bpoints.size(); i-- != 0; bpoints.remove(i));
        stepCounter = 0;
        //saveFrame(str(savefrnum));
        //savefrnum ++;
      }
    
      pushMatrix();
      strokeWeight(1);
      stroke(255, 150);
      line(width-margin, 0, width-margin, height);
      popMatrix();
      stepCounter ++;
      totalCounter++;
    }
    //End draw_________________________________________________________________________________________________________________________________________
    
    
    String scramble( int which, String a, String b ) { // begin switching random values with substring r as the intermediate
      String r;
      int pos = int(random(min(a.length(), b.length())));
      r = a.substring(0, pos) + b.substring(pos, b.length());
    
      // Mutation! //change or add a random value between position 0 and length of r
      if ( random(1) < .5 ) {
        pos = int(random(r.length()));
        if ( random(1) < .5 ) { 
          String mut = "" + char( '0' + int( random(4) ) );
          //println( "New Ball #" + which + ": Mutation! Adding a char: '" + mut + "' at position " + pos );
          r = r.substring(0, pos) + mut + r.substring(pos, r.length());
        } else {
          if ( r.length() > 0 ) {
            pos = int(random(r.length()-1));
            //println( "New Ball #" + which + ": Mutation! Losing the char at position " + pos );
            r = r.substring(0, pos) + r.substring(pos+1, r.length());
          }
        }
      }
      return( r ); //return the value to change the initial strings, reset w/change basically
    }
    
    
    //begin goal changing 
    void mousePressed() {
      if (mouseButton == LEFT) {
        checkMove();
      }
    }
    
    void checkMove() {
      gcorX = random(0, width-margin);
      gcorY = random(height);
      bscore = dist(0, 0, width, height);
      gen_num=0;
      movCounter++;
      frame = str(savefrnum);
      saveFrame(frame);
      save("C:/Users/Kiran/Documents/Processing/GA3_Graphs/frame.jpg");
      savefrnum ++;
    }
    //end goal changing
    
    
    
    class Ball {
      float x, y, z, v; //position related
      color col; //color of balls
      int current_inst;//current instruction
      int inst_time;//time between instructions
      int[] instructions; //array of instructions
      boolean dis = false; //disable ball
      int num; 
      String genome; //GENOME
      int checknum; //check number for genome val to ensure smooth transition
    
      boolean inst_a, inst_b, inst_c; //instructions
    
      Ball(int cknum, String input) {
        //x = width/2;
        //y = height-20;
        x = width/2;
        y = height/2;
        if (cknum == -1) {  
          x = -20;
          y = -20;
        }
        z =0;
        v = 0;
    
        col=color(random(40, 255), random(40, 255), random(40, 255), 200);
        inst_a = inst_b = inst_c = false; 
        checknum = cknum; //making sure the numbers are the same to avoid glitches
        current_inst = 0;
        checkString( input );
        inst_time = millis() + timeIter;
        dis = false; //not disabled
        genome = input; //read input (parse/checkstring) and input it into the genome
      }
    
      void checkString(String in) {    //parsing function
        instructions = new int[in.length()];
        for ( int j = 0; j < in.length(); j++ ) {
          instructions[j] = int( in.charAt(j) - '0' );
        }
        //reads each character in the input string and puts it into instructions to be enacted
      }
    
      //begin scoreReport- uses an array to store the scores of the generation so that a best and a worst can be calculated
    
      void scoreRep() {
        scores[checknum] = dist(x, y, gcorX, gcorY) + genome.length()*2; //uses the distance between the translated ball(at x, y) and the goal at the gcords. //also, just added a penalty for length of genome, to try and promote a more direct route
        if ( scores[checknum] < bscore ) { // if the score is not the best score, change the scores to be recalculated by the next generation
          bscore = scores[checknum];
          globalBall.x = x;
          globalBall.y = y;
          globalBall.z = z;
          globalBall.col = col;
          globalBall.genome = genome; //checks the best aspects and records the genome, moves the values for position
        }
        countDone++;
        //if ( scores[checknum] < 20 ) {
        //  gcorX = random(width);
        //  gcorY = random(height);
        //}
        //balls.remove(0);
      }
    
      void move() {
        if ( millis() > inst_time && !dis) { // if the millisecond function (internal clock) is greater than the instance time and not disabled, 
          inst_time = millis() + timeIter; //time between things
          if ( current_inst < instructions.length ) { //for every instruction in the instruction array 
            int i = instructions[current_inst++]; //i is used to represent the value of the instruction at the current instruction value
            switch( i ) { //switches between actions for instruction. For example, if the value "i" is 2, it would enact instruction case 2. it reads and enacts on the instructions based on their value and reads them in sequence based on their position in the array
            case 0:
              // Do nothing.
              break;
            case 1:
              inst_a = !inst_a;
              break;
            case 2:
              inst_b = !inst_b;
              break;
            case 3:
              inst_c = !inst_c;
              break;
            default:
              //println( "Bum instruction: " + i )//instruction does not exist
              break;
            }
          } else { // Terminate run.
            inst_a=inst_b=inst_c=false;
            v=0;
            dis = true; // disable is true, end run, set v to 0, set instructions to false, and statify the scoreReport
            scoreRep();
          }
        }
        // movement systems follow.
        z+=(inst_a?-.1:0)+(inst_b?.1:0); //conditional operator/ternary operator. I dont want to explain it here, it is a shorthand. Go here for more: http://stackoverflow.com/questions/798545/what-is-the-java-operator-called-and-what-does-it-do
        v+=(inst_c?.1:0); //conditional
        //x=(x+width+v*cos(z))%width;
        //y=(y+height+v*sin(z))%height;
        x=x+v*cos(z); //math for x based on angle of movement (v is basically serving as a hypotenuse here)
        y=y+v*sin(z); //math for y based on angle of movement (v is basically serving as a hypotenuse here)
        v*=.99;
        render(); //calls a display function
      }
      void render() {
        pushMatrix(); //layer 4
        translate(x, y); //move the thing by the x and y calculated in move
        rotate(z); //rotate by z
        noStroke();
        fill(col); //fill with color 
    
        if ( checknum==-1) fill(255, 0, 0); //if it is the best ball, color it red
        ellipseMode(CENTER); //put measurements in center
        ellipse(0, 0, 25, 25); //ball size
        stroke(0);//black edge
        strokeWeight(1);
    
        noFill(); //triangle no fill
        triangle(-6, -5, 8, 0, -6, 5); //  triangle(-5, -8.66, 0, 10, 5, -8.66);
        popMatrix();
      }
    }
    
    
    class Point {
      float xpos, ypos;
      float size = 2;
    
      Point(float x, float y) {
    
        xpos = x;
        ypos = y;
      }
    
      void displaypt() {
        pushMatrix();
    
        strokeWeight(2);
        stroke(0, 0, 255); 
        //fill(0, 0, 255, 10);
        //point(xpos, ypos);
        vertex(xpos, ypos);
        popMatrix();
      }
    }
    
    class BPoint {
      float xpos, ypos;
      float size = 2;
    
      BPoint(float x, float y) {
    
        xpos = x;
        ypos = y;
      }
    
      void displayBpt() {
        pushMatrix();
        strokeWeight(2);
        stroke(255, 0, 0);
        //fill(255, 0, 0, 10);
        vertex(xpos, ypos); //ellipse at pos, size)
        popMatrix();
      }
    }
    
  • You are calling save with the same name every time. It is obviously going to overwrite itself.

    You are calling save frame using a single letter, relative filename, which does increment but doesn't have an extension. Maybe it doesn't know what file format to use (I think it defaults to TIFF). These files will be in your sketch folder.

  • while ( balls.size() > 0 ) balls.remove(0);
    
    for (int i = points.size(); i-- != 0; points.remove(i));
    for (int i = bpoints.size(); i-- != 0; bpoints.remove(i));
    

    ArrayLists have a clear () method that deletes all the entries.

  • edited August 2016

    I've also mentioned many times about clear() in 1 of his old posts: :-@
    https://forum.Processing.org/two/discussion/17806/remove-clear-objects-from-an-arraylist#Item_3

  • Haha, yeah. I meant to change that but I guess I forgot; anyways, it doesn't really matter anymore. If it isn't broken...Anyways, is there any way I can change it so that it doesn't overwrite the existing files? And the program still does not save to the desired folder at all.

  • Answer ✓

    This should work based on the documentation:

      frame = str(savefrnum);
      saveFrame("C:/Users/Kiran/Documents/Processing/GA3_Graphs/"+frame+"-####.png");
      save("C:/Users/Kiran/Documents/Processing/GA3_Graphs/frame"+savefrnum +".jpg");
      savefrnum ++;
    

    You have to make sure the entire folder path exist and that you have permission to write there.Otherwise you have to create the folders before saving the files.

    I would suggest creating a small sample code to ensure it works as you want it before using it in your main code. It will make things a bit easier to debug.

    Kf

  • That works like a charm. Thanks for all the help!

Sign In or Register to comment.