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/BufferObject.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 #if defined(VL_OPENGL)
00060 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
00061 #endif
00062
00063 glPixelStorei( GL_PACK_ALIGNMENT, 1);
00064 #if defined(VL_OPENGL)
00065 glPixelStorei( GL_PACK_ROW_LENGTH, w);
00066 glPixelStorei( GL_PACK_SKIP_PIXELS, 0);
00067 glPixelStorei( GL_PACK_SKIP_ROWS, 0);
00068 glPixelStorei( GL_PACK_SWAP_BYTES, 0);
00069 glPixelStorei( GL_PACK_LSB_FIRST, 0);
00070 if (Has_GL_Version_1_2||Has_GL_Version_3_0||Has_GL_Version_4_0)
00071 {
00072 glPixelStorei( GL_PACK_IMAGE_HEIGHT, 0 );
00073 glPixelStorei( GL_PACK_SKIP_IMAGES, 0 );
00074 }
00075
00076 int prev = 0;
00077 glGetIntegerv( GL_READ_BUFFER, &prev ); VL_CHECK_OGL()
00078 glReadBuffer( read_buffer );
00079 #endif
00080
00081 #ifndef NDEBUG
00082 if (glGetError() != GL_NO_ERROR)
00083 {
00084 Log::print(Say("Image::readPixels() error: %s:%n\n"
00085 "You seem to have specified a wrong read buffer for the bound render target,\n"
00086 "for example you might have specified a RDB_BACK_LEFT but the active camera\n"
00087 "is bound to a FBO (Framebuffer Object) render target or the selected\n"
00088 "read buffer is FBO-specific (like RDB_COLOR_ATTACHMENT0_EXT) but the active\n"
00089 "camera is not bound to a FBO render target. \n") << __FILE__ << __LINE__
00090 );
00091 VL_TRAP()
00092 }
00093 #endif
00094
00095 bool supports_pbo = Has_GL_ARB_pixel_buffer_object||Has_GL_EXT_pixel_buffer_object||Has_GL_Version_2_1;
00096
00097 if (store_in_pixel_buffer_object && supports_pbo)
00098 {
00099
00100 BufferObject* glbuf = cast<BufferObject>(image->imageBuffer()); VL_CHECK(glbuf);
00101
00102 int bytes = image->requiredMemory2D(w, h, 1, image->format(), image->type());
00103
00104 glbuf->setBufferData( bytes, NULL, glbuf->usage() );
00105
00106 VL_glBindBuffer( GL_PIXEL_PACK_BUFFER, glbuf->handle() );
00107
00108 glReadPixels( x, y, w, h, image->format(), image->type(), 0);
00109
00110 VL_glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 );
00111
00112
00113 image->reset(w, h, 0, 1, image->format(), image->type(), false);
00114
00115
00116
00117
00118
00119 }
00120 else
00121 {
00122 if (w != image->width() || h != image->height() || image->dimension() != ID_2D || image->pixels() == NULL)
00123 image->allocate2D( w, h, 1, image->format(), image->type() );
00124 glReadPixels( x, y, w, h, image->format(), image->type(), image->pixels() );
00125 }
00126
00127 #if defined(VL_OPENGL)
00128
00129 glReadBuffer( prev );
00130
00131 glPopClientAttrib();
00132 #endif
00133
00134 VL_CHECK_OGL()
00135 }
00136
00137
00138
00152 class ReadPixels: public RenderEventCallback
00153 {
00154 VL_INSTRUMENT_CLASS(vl::ReadPixels, RenderEventCallback)
00155
00156 public:
00157 ReadPixels():
00158 mX ( 0 ),
00159 mY ( 0 ),
00160 mWidth ( 0 ),
00161 mHeight ( 0 ),
00162 mReadBuffer ( RDB_BACK_LEFT ),
00163 mStoreInPixelBufferObject(false)
00164 {
00165 VL_DEBUG_SET_OBJECT_NAME()
00166 }
00167
00168 ReadPixels(int x, int y, int width, int height, EReadDrawBuffer read_buffer, Image* image, bool store_in_pbo):
00169 mX ( x ),
00170 mY ( y ),
00171 mWidth ( width ),
00172 mHeight ( height ),
00173 mReadBuffer ( read_buffer ),
00174 mImage ( image ),
00175 mStoreInPixelBufferObject( store_in_pbo )
00176 {
00177 VL_DEBUG_SET_OBJECT_NAME()
00178 }
00179
00180 virtual bool onRenderingStarted(const RenderingAbstract*)
00181 {
00182 readPixels();
00183 return true;
00184 }
00185
00186 virtual bool onRenderingFinished(const RenderingAbstract*)
00187 {
00188 readPixels();
00189 return true;
00190 }
00191
00192 virtual bool onRendererStarted(const RendererAbstract*)
00193 {
00194 readPixels();
00195 return true;
00196 }
00197
00198 virtual bool onRendererFinished(const RendererAbstract*)
00199 {
00200 readPixels();
00201 return true;
00202 }
00203
00204 void setup(int x, int y, int width, int height, EReadDrawBuffer read_buffer, bool store_in_pbo)
00205 {
00206 mX = x;
00207 mY = y;
00208 mWidth = width;
00209 mHeight = height;
00210 mReadBuffer = read_buffer;
00211 mStoreInPixelBufferObject = store_in_pbo;
00212 }
00213
00214 void setX(int x) { mX = x; }
00215 void setY(int y) { mY = y; }
00216 void setWidth(int width) { mWidth = width; }
00217 void setHeight(int height) { mHeight = height; }
00218 void setReadBuffer(EReadDrawBuffer buffer) { mReadBuffer = buffer; }
00219 void setImage(Image* image) { mImage = image; }
00220 void setSavePath(const String& path) { mSavePath = path; }
00221
00222 int x() const { return mX; }
00223 int y() const { return mY; }
00224 int width() const { return mWidth; }
00225 int height() const { return mHeight; }
00226 EReadDrawBuffer readBuffer() const { return mReadBuffer; }
00227 Image* image() { return mImage.get(); }
00228 const Image* image() const { return mImage.get(); }
00229 const String& savePath() const { return mSavePath; }
00230
00231 void setStoreInPixelBufferObject( bool use_pbo ) { mStoreInPixelBufferObject = use_pbo; }
00232 bool storeInPixelBufferObject() const { return mStoreInPixelBufferObject; }
00233
00234 protected:
00235 void readPixels()
00236 {
00237 if (mImage.get() == NULL)
00238 mImage = new Image;
00239 vl::readPixels(mImage.get(), mX, mY, mWidth, mHeight, mReadBuffer, storeInPixelBufferObject() );
00240 if ( savePath().length() )
00241 {
00242 if (!saveImage(mImage.get(), savePath()))
00243 Log::error( Say("ReadPixels: unknown format for file: '%s'\n") << savePath() );
00244 }
00245 }
00246
00247 protected:
00248 int mX;
00249 int mY;
00250 int mWidth;
00251 int mHeight;
00252 EReadDrawBuffer mReadBuffer;
00253 ref<Image> mImage;
00254 String mSavePath;
00255 bool mStoreInPixelBufferObject;
00256 };
00257 }
00258
00259 #endif