Reading pixels from a TARGET texture

Hi

I’m using a texture with SDL_TEXTUREACCESS_TARGET flag and I blit onto
this one (with SDL_RenderCopy) a number of other textures to finally
get my image.

Then I would like to get the final pixel array of that texture in
order to do more image processing by hand.

What is the best way to obtain this pixel array ?

thx
S.

As far as I know, you need to change RenderReadPixels method of
SDL_Renderer. Below is my modified version.----------------------------------------------------------------------------

OpenGL(function GL_RenderReadPixels):
https://github.com/freeors/SDL/blob/master/SDL2-2.0.4/src/render/opengl/SDL_
render_gl.c
OpenGL ES2(function GLES2_RenderReadPixels):
https://github.com/freeors/SDL/blob/master/SDL2-2.0.4/src/render/opengles2/S
DL_render_gles2.c

Sanette wrote:

What is the best way to obtain this pixel array ?

You can use SDL_RenderReadPixels but there are a couple of problems with that approach:
The API is buggy. For example with some renderers it will return the image upside-down (https://bugzilla.libsdl.org/show_bug.cgi?id=2740)!

The API can be very slow, especially if the target texture is significantly larger than the window.

To work around the first issue, and to ameliorate the second, I use this slightly more complex method (when the rectangle you want to read is no larger than the window):

Code:
int RenderReadPixels (SDL_Renderer* renderer, const SDL_Rect* rect,
Uint32 format, void* pixels, int pitch)
{
int result ;
SDL_Rect dst = {0, 0, rect->w, rect->h} ;
SDL_Texture *tex = SDL_GetRenderTarget (renderer) ;
SDL_SetRenderTarget (renderer, NULL) ;
SDL_RenderCopy (renderer, tex, rect, &dst) ;
result = SDL_RenderReadPixels (renderer, &dst, format, pixels, pitch) ;
SDL_SetRenderTarget (renderer, tex) ;
return result ;
}

Richard.

thanks, I will try; this brings some questions:

  • do you means that the current GL_RenderReadPixels does not work ?

  • the doc says “WARNING: This is a very slow operation, and should not
    be used frequently.” Is this still the case with your version ?

  • Ideally I’d rather use an “official” method. Will these changes be
    included in the official SDL2 ?

S.

Le 05/08/2016 ? 12:25, ancientcc a ?crit :> As far as I know, you need to change RenderReadPixels method of > SDL_Renderer. Below is my modified version. >

------ > OpenGL(function GL_RenderReadPixels): >
https://github.com/freeors/SDL/blob/master/SDL2-2.0.4/src/render/opengl/SDL_
render_gl.c > OpenGL ES2(function GLES2_RenderReadPixels): >
https://github.com/freeors/SDL/blob/master/SDL2-2.0.4/src/render/opengles2/S
DL_render_gles2.c > > _______________________________________________
SDL mailing list > SDL at lists.libsdl.org >
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Le 05/08/2016 ? 13:41, rtrussell a ?crit :

To work around the first issue, and to ameliorate the second, I use this slightly more complex method (when the rectangle you want to read is no larger than the window): > > > > > > > > > Code: > int RenderReadPixels (SDL_Renderer*
renderer, const SDL_Rect* rect, > Uint32
format, void* pixels, int pitch) > { > int result ; > SDL_Rect dst
= {0, 0, rect->w, rect->h} ; > SDL_Texture *tex = SDL_GetRenderTarget
(renderer) ; > SDL_SetRenderTarget (renderer, NULL) ; >
SDL_RenderCopy (renderer, tex, rect, &dst) ; > result =
SDL_RenderReadPixels (renderer, &dst, format, pixels, pitch) ; >
SDL_SetRenderTarget (renderer, tex) ; > return result ; > } > > Richard.

this seems to be a nice trick for textures that fit the window. Thanks.

  • do you means that the current GL_RenderReadPixels does not work ?------------------

Yes, If you want to read pixels from SDL_TEXTUREACCESS_TARGET’s SDL_texture,
current GL_RenderReadPixels will work unsuccessfully. Of course,
GL_RenderReadPixels is corresponding to Open GL, for example Microsoft
Windows with SDL_WINDOW_OPENGL. If your app use OpenGL ES2, for example iOS
and Android, you require modify GLES2_RenderReadPixels. Their modification
are the same.

  • the doc says "WARNING: This is a very slow operation, and should not

    be used frequently." Is this still the case with your version ?


This still the case with my version, modify don’t touch that. You should
absolutely not use SDL_RenderReadPixels(), ever, for anything other than
screenshots and the like.

  • Ideally I’d rather use an “official” method. Will these changes be

    included in the official SDL2 ?


I think that next official SDL2 will fix this BUG. Of course, I hope to
patch code to official SDL2, especial BLE.

If you want read pixels from tex(it’s type must be
SDL_TEXTUREACCESS_TARGET), you can write below code.

int RenderReadPixels (SDL_Renderer* renderer, const SDL_Rect* rect,

                      Uint32 format, void* pixels, int pitch,

SDL_Texture* tex)

{

// assume current target is NULL.

int result ;

SDL_Rect dst = {0, 0, rect->w, rect->h} ;

// Since want to read from tex, should set it to target.

SDL_SetRenderTarget(renderer, tex) ;

// pitch = dst.w * byte of one pixel. not tex’width * byte of pixel.

result = SDL_RenderReadPixels(renderer, &dst, format, pixels, pitch);

// recover target to NULL.

SDL_SetRenderTarget (renderer, NULL) ;

return result ;

}

Le 05/08/2016 ? 14:57, Sanette a ?crit :

this seems to be a nice trick for textures that fit the window. Thanks.

I’ve just tested this, indeed it fixes the upside-down problem, and it’s
even slightly faster
(I get 350 FPS instead of 300 FPS for my test)

thx again