A quick question about screenshots

Is it possible to take automatic screenshots or does it have to be manual with keyPressed, mousePressed, etceteras?

Answers

  • you can call saveFrame() anyhow you want. say on a timer or other condition.

  • edited December 2014
    // forum.processing.org/two/discussion/8467/
    // a-quick-question-about-screenshots
    
    static final int FPS = 60, INTERVAL = 5 * 1000; // 5 seconds
    
    void setup() {
      size(300, 200, JAVA2D);
      frameRate(FPS);
      thread("timedShots");
    }
    
    void draw() {
      background((color) random(#000000));
    }
    
    void timedShots() {
      for (;; delay(INTERVAL))  saveFrame(dataPath("####.jpg"));
    }
    
  • Thank you, koogs and GoToLoop for the responses!

    GoToLoop, I'm new to Processing so your code is a bit confusing.

    However, I was able to implement a timer that would go off every minute, however whenever it screenshots, it takes a picture every time the program redraws (and it adds up to being thousands of photos).

    I tried to put saveFrame into setup but the way my program is setup, it makes it glitch out.

    I see that there is a void timedShots, should I use that in order to make it take one photo every minute?

  • edited December 2014

    I'm new to Processing so your code is a bit confusing.

    Feel free to ask what you didn't get! :-c

    I see that there is a void timedShots, should I use that in order to make it take one photo every minute?

    In order to use timedShots() in your own code, you should understand how it works!
    You gotta adjust INTERVAL for your needs, and invoke it via thread("") within setup(). :-B

    I wonder if you had run it the way it is and checked out it indeed screenshots each 5 seconds? :-?

  • Thank you!

    I ran your program, looked in the sketchbook and it would screenshot every five seconds.

    I understand the part where INTERVAL needs to be modified to fit my needs, however I'm wondering what thread and delay does.

    I'm guessing delay makes it so it doesn't happen exactly at 5? I'm not sure if that's correct.

  • delay is that bit that introduces the delay between shots.

    however, if you had it in the main thread then EVERYTHING would stop. so he's put it in another thread so it doesn't interfere with the drawing.

    the for (;; delay(INTERVAL)) is just a wanky way of looping forever.

  • So to clarify, a thread is like a section of code, for example, forwould be considered a thread?

  • edited December 2014
    • A Java Thread is synonym of program execution.
    • When a Java program starts, it creates a Thread which starts running it.
    • However, we can make more Thread instances in order to run some part at the same time as the others!
    • Processing's undocumented function thread("") allows us to conveniently call some function by its String name running it under a new Thread!
    • That invoked function will execute async w/ main "Animation" Thread's draw() at the same time.

    Read more about it here: https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html

  • That was very helpful, and I appreciate the time you took to explain it, as well as adding additional information to help me understand it further.

    I understand the delay, the interval, and now the thread. I also understand dataPath as well as the for statement.

    The thing I don't understand is why my code isn't screenshotting haha. When I isolate the screenshot/timer code, it will put screenshots in the sketchfolder however, when I integrate it into my main code as a class, it doesn't work. I figure it's because it doesn't have a data folder, so I added one and restarted processing. It still doesn't work. :(

  • edited December 2014

    ... when I integrate it into my main code as a class,...

    Functions thread("") & method(""), can't call methods from other classes. Only sketch's functions! [-X
    Most you can do is invoke the foreign method from within sketch's function invoked by thread("").

    And just found out thread("") is now "official" API. Although neither delay() nor dataPath("") aren't yet: :-$
    https://processing.org/reference/thread_.html

  • So I can't use this code as a class? Or I can't use thread in a class?

    Is the timedShots not being called by thread? Isn't it being called inside the setup method inside of Timer?

    This is starting to make some sense! Although I can't say I'll be able to make my code work the way I want it to! :p

  • edited December 2014
    • As mentioned, thread("") is a "convenient" function which not so long ago was undocumented & unofficial!
    • In short, it's not Java's "correct" way of doing threads:
      https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
    • Its String argument can only be the name of a sketch's method. Not some other class' method!
    • When thread("") fails, it displays a red warning message in the console! Check that out!
    • We can use thread("") from inside a class as long as it invokes a sketch's function!
  • edited December 2014 Answer ✓

    Here's my original example adapted to use Java's Thread inside a class:

    /**
     * ThreadedShots (v2.0)
     * by GoToLoop (2014/Dec/10)
     *
     * forum.processing.org/two/discussion/8467/
     * a-quick-question-about-screenshots
     */
    
    void setup() {
      size(300, 200, JAVA2D);
      frameRate(60);
      new ShotClass(5*1000); // 5 seconds interval.
    }
    
    void draw() {
      background((color) random(#000000));
    }
    
    final class ShotClass {
      final String path = dataPath("####.jpg");
      final int interval;
    
      final Runnable timedShots = new Runnable() {
        void run() {
          for (;; delay(interval))  saveFrame(path);
        }
      };
    
      ShotClass(int waiting) {
        interval = waiting;
        new Thread(timedShots).start();
      }
    }
    

    Notice I've declared a Runnable variable called timedShots and initialized it w/ a Runnable object.
    Then used it as argument for instantiating a new Thread inside class' constructor.
    And finally kicked that all off via start(): :D

  • for (;; delay(INTERVAL))

    <3

  • edited December 2014

    @clankill3r, since you liked my infinite for () loop... how about this 1?: :P
    for (;; delay(interval), saveFrame(path));

    Or heavens forbid it: >:)
    for (String path = dataPath("####.jpg");; delay(interval), saveFrame(path));

    1 more: \m/

    for ( println("Starting TimedShots Infinite Loop...")
      , println("@ Java Thread:", Thread.currentThread())
      , println("w/ Interval: ", interval/1000, "seconds.\n")
      ;; delay(interval), saveFrame(path), println(frameCount) );
    
  • :) you deserve a processing t-shirt :)

  • edited December 2014

    I understand the most recent code you just posted however, it doesn't seem to like my code haha.

    I have a countdown timer that I am trying to implement that appears for the last three seconds. When I tried to integrate it with your code, I keep getting null and unreachable code.

    I hate to say it but I don't think I'll be able to use your code due to my lack of knowledge in code. :/

  • Thank you for everyone's contribution, especially GoToLoop!

    I really appreciate it. This thread has definitely beefed up my Processing vocabulary and all the possible ways there are to do one thing.

  • I have a countdown timer that I am trying to implement that appears for the last three seconds.

    My thread("") snippet already got its own countdown as delay(INTERVAL)!
    Problem is that this whole time you haven't posted any code of yours! (~~)

  • This is what I have so far. (It's usually in a class)

    //TfGuy44 
    
    int resetAt;
    
    
        void setup(){
          //background(0);
          noStroke();
          smooth();
          reset();
    
        }
    
    
        void reset(){
          resetAt = millis() + 10000;
        }
    
        void draw(){
          fill(0);
          textSize(12);
          int timeLeft = resetAt - millis();
          text(timeLeft, 20, 20);
         if (timeLeft<4000){
            saveFrame();
            println("screencapped");
        }
    
    
          if(timeLeft<3000){
            fill(0);
            noStroke();
            rectMode(CENTER);
            rect(width/2, height/2, 40,40);
            textSize(30);
            fill(255);
            textAlign(CENTER, CENTER);
            int countDown = 1 + (timeLeft / 1000);
            text( countDown, width/2, height/2);
          }
          if( millis() >= resetAt ){
            reset();
            background(0);
          }
    
    
        }
    
  • I fixed the problem!

    I took the timer out of a class and used the (;; delay(INTERVAL)).

    Thank you so much for your help and patience, GoToLoop!

Sign In or Register to comment.