Skip to content

Commit 6f153fc

Browse files
takaokoujiclaude
andcommitted
feat: add SDL2::Renderer#read_pixels
Wraps SDL_RenderReadPixels to read pixel data from the current rendering target. Returns raw pixel data as a binary string. Default format is ARGB8888. Pass nil for rect to read the entire target. Refs: ohai#28 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e92eee2 commit 6f153fc

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

video.c.m4

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,52 @@ static VALUE Renderer_present(VALUE self)
13401340
return Qnil;
13411341
}
13421342

1343+
/*
1344+
* Read pixels from the current rendering target.
1345+
*
1346+
* @param rect [SDL2::Rect,nil] the area to read (the entire target if nil)
1347+
* @param format [Integer] the desired pixel format (0 for ARGB8888)
1348+
* @return [String] raw pixel data as a binary string (ARGB8888 by default)
1349+
*
1350+
* @example
1351+
* # Read the entire screen before presenting
1352+
* pixels = renderer.read_pixels(nil, 0)
1353+
*/
1354+
static VALUE Renderer_read_pixels(VALUE self, VALUE rect, VALUE format)
1355+
{
1356+
SDL_Renderer* renderer = Get_SDL_Renderer(self);
1357+
SDL_Rect sdl_rect;
1358+
SDL_Rect* rect_ptr = NULL;
1359+
Uint32 fmt = NUM2UINT(format);
1360+
int w, h, pitch;
1361+
void* pixels;
1362+
VALUE result;
1363+
1364+
if (rect != Qnil) {
1365+
sdl_rect = *Get_SDL_Rect(rect);
1366+
rect_ptr = &sdl_rect;
1367+
w = sdl_rect.w;
1368+
h = sdl_rect.h;
1369+
} else {
1370+
HANDLE_ERROR(SDL_GetRendererOutputSize(renderer, &w, &h));
1371+
}
1372+
1373+
if (fmt == 0)
1374+
fmt = SDL_PIXELFORMAT_ARGB8888;
1375+
1376+
pitch = w * SDL_BYTESPERPIXEL(fmt);
1377+
pixels = ruby_xmalloc(pitch * h);
1378+
1379+
if (SDL_RenderReadPixels(renderer, rect_ptr, fmt, pixels, pitch) < 0) {
1380+
ruby_xfree(pixels);
1381+
HANDLE_ERROR(-1);
1382+
}
1383+
1384+
result = rb_str_new(pixels, pitch * h);
1385+
ruby_xfree(pixels);
1386+
return result;
1387+
}
1388+
13431389
/*
13441390
* Crear the rendering target with the drawing color.
13451391
* @return [nil]
@@ -2939,6 +2985,7 @@ void rubysdl2_init_video(void)
29392985
rb_define_method(cRenderer, "copy", Renderer_copy, 3);
29402986
rb_define_method(cRenderer, "copy_ex", Renderer_copy_ex, 6);
29412987
rb_define_method(cRenderer, "present", Renderer_present, 0);
2988+
rb_define_method(cRenderer, "read_pixels", Renderer_read_pixels, 2);
29422989
rb_define_method(cRenderer, "draw_color",Renderer_draw_color, 0);
29432990
rb_define_method(cRenderer, "draw_color=",Renderer_set_draw_color, 1);
29442991
rb_define_method(cRenderer, "clear", Renderer_clear, 0);

0 commit comments

Comments
 (0)