00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef CameraReadPixels_INCLUDE_ONCE
00033 #define CameraReadPixels_INCLUDE_ONCE
00034
00035 #include <vlGraphics/Camera.hpp>
00036 #include <vlCore/Say.hpp>
00037 #include <vlCore/Log.hpp>
00038 #include <vlGraphics/RenderEventCallback.hpp>
00039 #include <vlGraphics/GLBufferObject.hpp>
00040 #include <vlCore/Image.hpp>
00041
00042 namespace vl
00043 {
00044
00045
00046
00054 inline void readPixels(Image* image, int x, int y, int w, int h, EReadDrawBuffer read_buffer, bool store_in_pixel_buffer_object)
00055 {
00056
00057 glGetError();
00058
00059 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
00060
00061 glPixelStorei( GL_PACK_ALIGNMENT, 1);
00062 glPixelStorei( GL_PACK_ROW_LENGTH, w);
00063 glPixelStorei( GL_PACK_SKIP_PIXELS, 0);
00064 glPixelStorei( GL_PACK_SKIP_ROWS, 0);
00065 glPixelStorei( GL_PACK_SWAP_BYTES, 0);
00066 glPixelStorei( GL_PACK_LSB_FIRST, 0);
00067 if (GLEW_VERSION_1_2)
00068 {
00069 glPixelStorei( GL_PACK_IMAGE_HEIGHT, 0 );
00070 glPixelStorei( GL_PACK_SKIP_IMAGES, 0 );
00071 }
00072
00073 int prev = 0;
00074 glGetIntegerv( GL_READ_BUFFER, &prev ); VL_CHECK_OGL()
00075 glReadBuffer( read_buffer );
00076 #ifndef NDEBUG
00077 if (glGetError() != GL_NO_ERROR)
00078 {
00079 Log::print(Say("Image::readPixels() error: %s:%n\n"
00080 "You seem to have specified a wrong read buffer for the bound render target,\n"
00081 "for example you might have specified a RDB_BACK_LEFT but the active camera\n"
00082 "is bound to a FBO (Framebuffer Object) render target or the selected\n"
00083 "read buffer is FBO-specific (like RDB_COLOR_ATTACHMENT0_EXT) but the active\n"
00084 "camera is not bound to a FBO render target. \n") << __FILE__ << __LINE__
00085 );
00086 VL_TRAP()
00087 }
00088 #endif
00089
00090 bool supports_pbo = GLEW_ARB_pixel_buffer_object||GLEW_EXT_pixel_buffer_object||GLEW_VERSION_2_1;
00091 GLBufferObject* glbuf = dynamic_cast<GLBufferObject*>(image->imageBuffer());
00092
00093 if (store_in_pixel_buffer_object && supports_pbo)
00094 {
00095 int bytes = image->requiredMemory2D(w, h, 1, image->format(), image->type());
00096
00097 glbuf->setBufferData( bytes, NULL, glbuf->usage() );
00098
00099 VL_glBindBuffer( GL_PIXEL_PACK_BUFFER, glbuf->handle() );
00100
00101 glReadPixels( x, y, w, h, image->format(), image->type(), 0);
00102
00103 VL_glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 );
00104
00105
00106 image->reset(w, h, 0, 1, image->format(), image->type(), false);
00107
00108
00109
00110
00111
00112 }
00113 else
00114 {
00115 if (w != image->width() || h != image->height() || image->dimension() != ID_2D || image->pixels() == NULL)
00116 image->allocate2D( w, h, 1, image->format(), image->type() );
00117 glReadPixels( x, y, w, h, image->format(), image->type(), image->pixels() );
00118 }
00119
00120
00121 glReadBuffer( prev );
00122 glPopClientAttrib();
00123
00124 VL_CHECK_OGL()
00125 }
00126
00127
00128
00142 class ReadPixels: public RenderEventCallback
00143 {
00144 public:
00145 virtual const char* className() { return "vl::ReadPixels"; }
00146 ReadPixels():
00147 mX ( 0 ),
00148 mY ( 0 ),
00149 mWidth ( 0 ),
00150 mHeight ( 0 ),
00151 mReadBuffer ( RDB_BACK_LEFT ),
00152 mStoreInPixelBufferObject(false)
00153 {
00154 VL_DEBUG_SET_OBJECT_NAME()
00155 }
00156
00157 ReadPixels(int x, int y, int width, int height, EReadDrawBuffer read_buffer, Image* image, bool store_in_pbo):
00158 mX ( x ),
00159 mY ( y ),
00160 mWidth ( width ),
00161 mHeight ( height ),
00162 mReadBuffer ( read_buffer ),
00163 mImage ( image ),
00164 mStoreInPixelBufferObject( store_in_pbo )
00165 {
00166 VL_DEBUG_SET_OBJECT_NAME()
00167 }
00168
00169 virtual bool onRenderingStarted(const RenderingAbstract*)
00170 {
00171 readPixels();
00172 return true;
00173 }
00174
00175 virtual bool onRenderingFinished(const RenderingAbstract*)
00176 {
00177 readPixels();
00178 return true;
00179 }
00180
00181 virtual bool onRendererStarted(const RendererAbstract*)
00182 {
00183 readPixels();
00184 return true;
00185 }
00186
00187 virtual bool onRendererFinished(const RendererAbstract*)
00188 {
00189 readPixels();
00190 return true;
00191 }
00192
00193 void setup(int x, int y, int width, int height, EReadDrawBuffer read_buffer, bool store_in_pbo)
00194 {
00195 mX = x;
00196 mY = y;
00197 mWidth = width;
00198 mHeight = height;
00199 mReadBuffer = read_buffer;
00200 mStoreInPixelBufferObject = store_in_pbo;
00201 }
00202
00203 void setX(int x) { mX = x; }
00204 void setY(int y) { mY = y; }
00205 void setWidth(int width) { mWidth = width; }
00206 void setHeight(int height) { mHeight = height; }
00207 void setReadBuffer(EReadDrawBuffer buffer) { mReadBuffer = buffer; }
00208 void setImage(Image* image) { mImage = image; }
00209 void setSavePath(const String& path) { mSavePath = path; }
00210
00211 int x() const { return mX; }
00212 int y() const { return mY; }
00213 int width() const { return mWidth; }
00214 int height() const { return mHeight; }
00215 EReadDrawBuffer readBuffer() const { return mReadBuffer; }
00216 Image* image() { return mImage.get(); }
00217 const Image* image() const { return mImage.get(); }
00218 const String& savePath() const { return mSavePath; }
00219
00220 void setStoreInPixelBufferObject( bool use_pbo ) { mStoreInPixelBufferObject = use_pbo; }
00221 bool storeInPixelBufferObject() const { return mStoreInPixelBufferObject; }
00222
00223 protected:
00224 void readPixels()
00225 {
00226 if (mImage.get() == NULL)
00227 mImage = new Image;
00228 vl::readPixels(mImage.get(), mX, mY, mWidth, mHeight, mReadBuffer, storeInPixelBufferObject() );
00229 if ( savePath().length() )
00230 {
00231 if (!saveImage(mImage.get(), savePath()))
00232 Log::error( Say("ReadPixels: unknown format for file: '%s'\n") << savePath() );
00233 }
00234 }
00235
00236 protected:
00237 int mX;
00238 int mY;
00239 int mWidth;
00240 int mHeight;
00241 EReadDrawBuffer mReadBuffer;
00242 ref<Image> mImage;
00243 String mSavePath;
00244 bool mStoreInPixelBufferObject;
00245 };
00246 }
00247
00248 #endif