Created
October 16, 2012 08:41
-
-
Save fieldOfView/3898078 to your computer and use it in GitHub Desktop.
A quick (and dirty?) image averager in Cinder. Uses a 32 bit (floating point) Fbo to accumulate frames.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cinder/Cinder.h" | |
#include "cinder/app/AppBasic.h" | |
#include "cinder/ImageIo.h" | |
#include "cinder/Utilities.h" | |
#include "cinder/gl/Texture.h" | |
#include "cinder/Capture.h" | |
#include "cinder/gl/Fbo.h" | |
using namespace ci; | |
using namespace ci::app; | |
class CaptureApp : public AppBasic { | |
public: | |
void setup(); | |
void keyDown( KeyEvent event ); | |
void update(); | |
void draw(); | |
void clearImage(); | |
void saveImage(); | |
void saveBuffer(); | |
Capture mCapture; | |
gl::Texture mTexture; | |
gl::Fbo mRenderBuffer; | |
unsigned int mFrames; | |
bool mLive; | |
bool mCapturing; | |
}; | |
void CaptureApp::setup() | |
{ | |
try { | |
mCapture = Capture( 1920, 1080 ); | |
mCapture.start(); | |
} | |
catch( ... ) { | |
console() << "Failed to initialize capture" << std::endl; | |
} | |
gl::Fbo::Format fmt; | |
fmt.setColorInternalFormat( GL_RGB32F_ARB ); | |
mRenderBuffer = gl::Fbo( mCapture.getWidth(), mCapture.getHeight(), fmt ); | |
mFrames = 0; | |
mLive = false; | |
mCapturing = true; | |
} | |
void CaptureApp::keyDown( KeyEvent event ) | |
{ | |
switch( event.getCode() ) { | |
case KeyEvent::KEY_f: | |
// toggle fullscreen | |
setFullScreen( ! isFullScreen() ); | |
break; | |
case KeyEvent::KEY_SPACE: | |
// pause/resume | |
mCapturing = !mCapturing; | |
break; | |
case KeyEvent::KEY_l: | |
// toggle live preview/accumulated result | |
mLive = !mLive; | |
break; | |
case KeyEvent::KEY_c: | |
// clear renderbuffer | |
clearImage(); | |
break; | |
case KeyEvent::KEY_s: | |
// save result | |
saveImage(); | |
break; | |
case KeyEvent::KEY_b: | |
// save buffer | |
saveBuffer(); | |
break; | |
} | |
} | |
void CaptureApp::update() | |
{ | |
if( mCapture && mCapture.checkNewFrame() ) { | |
mTexture = gl::Texture( mCapture.getSurface() ); | |
if( mCapturing ) { | |
// bind the FBO, so we can draw on it | |
mRenderBuffer.bindFramebuffer(); | |
// set the correct viewport and matrices | |
glPushAttrib( GL_VIEWPORT_BIT ); | |
gl::setViewport( mRenderBuffer.getBounds() ); | |
gl::pushMatrices(); | |
gl::setMatricesWindow( mRenderBuffer.getSize() ); | |
// enable additive blending | |
gl::enableAdditiveBlending(); | |
// draw Fbo upsidedown, because... | |
Rectf bufferRect = Rectf( 0, (float)mRenderBuffer.getHeight(), (float)mRenderBuffer.getWidth(), 0 ); | |
gl::draw( mTexture, mTexture.getBounds(), bufferRect ); | |
gl::disableAlphaBlending(); | |
// restore matrices and viewport | |
gl::popMatrices(); | |
glPopAttrib(); | |
// unbind the FBO to stop drawing on it | |
mRenderBuffer.unbindFramebuffer(); | |
// Increase frame count | |
mFrames++; | |
} | |
} | |
} | |
void CaptureApp::draw() | |
{ | |
gl::clear( Color( 0.0f, 0.0f, 0.0f )); | |
if( !mLive ) { | |
if( mFrames > 0 ) { | |
float factor = 1.0f / (float)mFrames; | |
gl::color( Color( factor, factor, factor )); | |
gl::draw( mRenderBuffer.getTexture(), Rectf( mRenderBuffer.getBounds() ).getCenteredFit( getWindowBounds(), true )); | |
gl::color( Color( 1.0f, 1.0f, 1.0f )); | |
} | |
} else { | |
gl::draw( mTexture, Rectf( mTexture.getBounds() ).getCenteredFit( getWindowBounds(), true )); | |
} | |
} | |
void CaptureApp::clearImage() | |
{ | |
mRenderBuffer.bindFramebuffer(); | |
gl::clear( Color( 0.0f, 0.0f, 0.0f ) ); | |
mRenderBuffer.unbindFramebuffer(); | |
mFrames = 0; | |
} | |
void CaptureApp::saveImage() | |
{ | |
fs::path pngPath = getSaveFilePath( getHomeDirectory() ); | |
if( pngPath.empty() ) { | |
return; | |
} | |
gl::Fbo exportBuffer; | |
exportBuffer = gl::Fbo( mCapture.getWidth(), mCapture.getHeight() ); | |
// bind the FBO, so we can draw on it | |
exportBuffer.bindFramebuffer(); | |
// set the correct viewport and matrices | |
glPushAttrib( GL_VIEWPORT_BIT ); | |
gl::setViewport( exportBuffer.getBounds() ); | |
gl::pushMatrices(); | |
gl::setMatricesWindow( exportBuffer.getSize() ); | |
// draw Fbo upsidedown, because... | |
Rectf bufferRect = Rectf( 0, (float)exportBuffer.getHeight(), (float)exportBuffer.getWidth(), 0 ); | |
if( mFrames > 0 ) { | |
float factor = 1.0f / (float)mFrames; | |
gl::color( Color( factor, factor, factor )); | |
gl::draw( mRenderBuffer.getTexture(), bufferRect ); | |
gl::color( Color( 1.0f, 1.0f, 1.0f )); | |
} | |
// restore matrices and viewport | |
gl::popMatrices(); | |
glPopAttrib(); | |
// unbind the FBO to stop drawing on it | |
mRenderBuffer.unbindFramebuffer(); | |
writeImage( pngPath, Surface32f( exportBuffer.getTexture() ), ImageTarget::Options(), "png" ); | |
} | |
void CaptureApp::saveBuffer() | |
{ | |
fs::path pngPath = getSaveFilePath( getHomeDirectory() ); | |
if( pngPath.empty() ) { | |
return; | |
} | |
writeImage( pngPath, Surface32f( mRenderBuffer.getTexture() ), ImageTarget::Options(), "png" ); | |
} | |
CINDER_APP_BASIC( CaptureApp, RendererGl ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment