Open AresAndy opened 5 years ago
Please add some details or better, reproducible code. I gave no idea what you're doing and expecting...
Yes, sorry, I totally forgot to include any actual source code..
What I'm trying to do (surely in a unsafe, inefficient way, but I don't mind at the moment..) is to get the RGB values of a pixel at x,y
coordinates. I looked around for quite a while, and stumbled on a piece of C code, that I roughly transliterated to crystal:
def get_pix_at(surf, x, y)
# debugger
LibSDL.lock_surface(surf)
ll_surface = surf.surface
bpp = ll_surface.format.value.bytesPerPixel
pix = (ll_surface.pixels + y * ll_surface.pitch * bpp).as(UInt32*).value
r = 0_u8
g = 0_u8
b = 0_u8
pr : UInt8* = pointerof(r)
pg : UInt8* = pointerof(g)
pb : UInt8* = pointerof(b)
LibSDL.get_rgb(pix, ll_surface.format, pr, pg, pb)
res = [pr.value, pg.value, pb.value]
LibSDL.unlock_surface(surf)
return res
end
This compiles with no warning whatsoever, does not crash when used, but the RGB array is constantly [0,0,0]
.. When debugging this function, ll_surface
contains most of the property of its type, except for pixels
. It's nice to see that rather than crashing for a bad pointer dereference it returns zero, but still.. If ll_surface
is a LibSDL::Surface
, one instance of it should contain pixels
.. Right?
lib LibSDL
# ...
struct Surface
flags : UInt32
format : PixelFormat*
w : Int
h : Int
pitch : Int
pixels : Void*
userdata : Void*
locked : Int
lock_data : Void*
clip_rect : Rect
map : Void* # BlitMap*
refcount : Int
end
# and so forth...
Have a look to http://lazyfoo.net/SDL_tutorials/lesson31/index.php
All samples are ports of Lazy Foo' tutorials, but I never went as far as reading a pixel color (lesson 31) and Surface#pixels
is unavailable for the moment.
Oh, I see... Are there any plans/timelines to make Surface#pixels
available? Or any workarounds?
I'm doing a fun weekend project, but it could be interesting for newcomers to show how Crystal can be used outside from web development and library bindings design, in a practical manner.
You can reopen SDL::Surface
:
class SDL::Surface
def pixels
surface.pixels
end
end
Then you have a direct access to the underlying void*
buffer of the surface, whose actual format depends on the surface format. For example:
def get_pixel(surface, x, y)
buffer = surface.pixels.as(UInt32*) # <= assumes 32-bit depth!
pixel = buffer + x + y * surface.width
LibSDL.get_rgb(pixel.value, out r, out g, out b)
{r, g, b}
end
window = SDL::Window.new(640, 480)
window.surface.fill(255, 0, 0)
p get_pixel(window.surface, 120, 240)
Hi, sorry to reply so lately, but I got stuck with other things..
I tried this piece of code, it has the problem that you're not passing a format
parameter to LibSDL.get_rgb
, but that can be fetched from the surface
parameter. Anyhow, the final result of the function is alway {0,0,0}
, no matter what kind of bit depth I use, no matter what the coordinates are.
I feel like there is something missing in the library at this point
No problem for me on Linux. Is the surface really 32-bit?
When debugging,
Surface
struct returned fromwindow.surface.to_unsafe
does not containpixels
, but property is clearly defined (atsdl/src/lib_sdl/surface.cr
), therefore pixel read access is impossible