Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add saveFrame method #187

Closed
MacTuitui opened this issue Aug 2, 2018 · 6 comments · Fixed by #452
Closed

Add saveFrame method #187

MacTuitui opened this issue Aug 2, 2018 · 6 comments · Fixed by #452

Comments

@MacTuitui
Copy link
Contributor

MacTuitui commented Aug 2, 2018

Hello there,
I've been looking into switching to nannou for my daily generative animations (insta), but my usual workflow is to generate frames of the animation to encode later with ffmpeg. (I'm currently using a custom wrapper in Scala around the Processing libraries.)

I'm a complete beginner in Rust so of course in nannou as well, but I could not find any reference to a similar function. I guess I could directly read the pixels from the gl context but that sounds a bit scary now, and against the idea of having a beginner friendly environment.

Would it be possible to have this feature in the framework? Or any other way to export the rendered output to share online?

I'll be more than willing to contribute back once I get used to rust, but this is a key issue for me to switch to nannou at the moment.

@mitchmindtree
Copy link
Member

Hey @MacTuitui, really nice animations!

I think the method you're looking for is Window::read_front_buffer. You can get access to the window via app.window(window_id) or app.main_window() might be easier if you just have a single window. You might need to use it in combination with the image crate. Glium (the OpenGL library we're using at the moment) has a nice example of this here.

I like your idea of adding a save_frame method - it would be nice to have a simpler method that simplifies this! We should also add an example for this, as I'm sure there are more people who would find this useful!

Out of curiosity, what format do you encode your animations to?

@MacTuitui
Copy link
Contributor Author

Thanks! I think I can manage to figure out the details with this info.

I'll try to do the switch as soon as I get comfortable with rust and eventually I'll submit a PR with a save_frame method inspired by what Processing has, with automatic numbering / string formatting etc... Feel free to close this issue until then.

As for the encoding format, I usually encode to h.264/mp4 with pixel format yuv420 (as no online platform that I now of supports true colors) for instagram and when I think that the compression settings used by twitter will kill everything (and for what I do, I sometimes end up with very heavy videos - 80M for 10 seconds is not rare), I try to make a GIF... then it's a challenge to stay within the 15M limit of twitter!

@MacTuitui
Copy link
Contributor Author

Small update to tell you where I'm at with this issue.

I'm currently using the following code to automate the saving process.

if app.elapsed_frames() > START_FRAME {
  let image:  nannou::glium::texture::RawImage2d<u8> = app.main_window().read_front_buffer();
  let image = nannou::image::ImageBuffer::from_raw(image.width, image.height, image.data.into_owned()).unwrap();
  let image = nannou::image::DynamicImage::ImageRgba8(image).flipv();
  image.save(format!("frame-{:04}.png", app.elapsed_frames()-START_FRAME)).unwrap();
}
if app.elapsed_frames() > LENGTH_FRAMES-START_FRAME {
  exit(0)
}

Where START_FRAME and LENGTH_FRAMES are global constants to decide when to start and when to stop the sketch.

And it's... super slow. The first thing to note is that this will give you images twice the size of the sketch, and since I did not find a way to save as tiff in the image crate, I don't know if that's the conversion to png or getting the data in the right format that is slow. I know you are working on getting support for (complex) framebuffers, maybe there might be something to do to make this faster.

(In processing I was able to get the image data then spawn a new thread to save the data to disk, getting no huge overhead on the main thread by using all possible threads, usually not used in a sketch.)

@tpltnt
Copy link
Contributor

tpltnt commented Jun 28, 2019

see also 319

@jli
Copy link
Contributor

jli commented Apr 24, 2020

afaict, I think we're still missing a built-in saveFrame method, so could we reopen this?

I saw @MacTuitui had this screenshot example: https://github.com/MacTuitui/nannou-screenshot-example (apparently based on work by @freesig ).

I think it'd be nice if something like this was built in, wdyt?

@mitchmindtree
Copy link
Member

@jli I think this should be solved by Window::capture_frame and TextureCapturer now - check out the draw_capture.rs and draw_capture_hi_res.rs examples for their respective examples. Let me know your thoughts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants