Skip to content

Commit b46980d

Browse files
authored
Merge pull request #10 from smalruby/smalruby/add-read-pixels
fix: address review feedback for Renderer#read_pixels
2 parents 7a92616 + 7c6794b commit b46980d

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

video.c.m4

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,22 +1336,34 @@ static VALUE Renderer_present(VALUE self)
13361336
}
13371337

13381338
/*
1339-
* Read pixels from the current rendering target.
1339+
* @overload read_pixels(rect, format)
1340+
* Read pixels from the current rendering target.
13401341
*
1341-
* @param rect [SDL2::Rect,nil] the area to read (the entire target if nil)
1342-
* @param format [Integer] the desired pixel format (0 for ARGB8888)
1343-
* @return [String] raw pixel data as a binary string (ARGB8888 by default)
1342+
* This is a very slow operation and should not be used frequently.
1343+
* Call this after rendering but before {#present}.
13441344
*
1345-
* @example
1346-
* # Read the entire screen before presenting
1347-
* pixels = renderer.read_pixels(nil, 0)
1345+
* @param rect [SDL2::Rect, nil] the area to read (nil for the entire target)
1346+
* @param format [SDL2::PixelFormat, Integer] the desired pixel format
1347+
* (0 to use the format of the rendering target)
1348+
* @return [String] raw pixel data as a binary string
1349+
*
1350+
* @example Read the entire screen in the rendering target's native format
1351+
* pixels = renderer.read_pixels(nil, 0)
1352+
*
1353+
* @example Read a sub-region in ARGB8888
1354+
* rect = SDL2::Rect.new(10, 10, 100, 100)
1355+
* pixels = renderer.read_pixels(rect, SDL2::PixelFormat::ARGB8888)
1356+
*
1357+
* @raise [SDL2::Error] raised on failure
1358+
* @see https://wiki.libsdl.org/SDL2/SDL_RenderReadPixels SDL_RenderReadPixels
13481359
*/
13491360
static VALUE Renderer_read_pixels(VALUE self, VALUE rect, VALUE format)
13501361
{
13511362
SDL_Renderer* renderer = Get_SDL_Renderer(self);
13521363
SDL_Rect sdl_rect;
13531364
SDL_Rect* rect_ptr = NULL;
1354-
Uint32 fmt = NUM2UINT(format);
1365+
Uint32 fmt = uint32_for_format(format);
1366+
Uint32 pitch_fmt;
13551367
int w, h, pitch;
13561368
void* pixels;
13571369
VALUE result;
@@ -1365,10 +1377,18 @@ static VALUE Renderer_read_pixels(VALUE self, VALUE rect, VALUE format)
13651377
HANDLE_ERROR(SDL_GetRendererOutputSize(renderer, &w, &h));
13661378
}
13671379

1368-
if (fmt == 0)
1369-
fmt = SDL_PIXELFORMAT_ARGB8888;
1380+
/* When fmt is 0 SDL uses the rendering target's format, so we need
1381+
to query it to calculate the correct pitch and buffer size. */
1382+
if (fmt == 0) {
1383+
SDL_RendererInfo info;
1384+
HANDLE_ERROR(SDL_GetRendererInfo(renderer, &info));
1385+
pitch_fmt = (info.num_texture_formats > 0)
1386+
? info.texture_formats[0] : SDL_PIXELFORMAT_ARGB8888;
1387+
} else {
1388+
pitch_fmt = fmt;
1389+
}
13701390

1371-
pitch = w * SDL_BYTESPERPIXEL(fmt);
1391+
pitch = w * SDL_BYTESPERPIXEL(pitch_fmt);
13721392
pixels = ruby_xmalloc(pitch * h);
13731393

13741394
if (SDL_RenderReadPixels(renderer, rect_ptr, fmt, pixels, pitch) < 0) {

0 commit comments

Comments
 (0)