PySDL2 锁定纹理并修改像素



我在 PySDL2 中找不到任何锁定纹理和修改像素的有价值的示例

这是我的代码:

def run():
sdl2.ext.init()
window = SDL_CreateWindow(b"test" sdl2.SDL_WINDOWPOS_CENTERED, sdl2.SDL_WINDOWPOS_CENTERED, 1024, 768, sdl2.SDL_WINDOW_SHOWN)
renderer = SDL_CreateRenderer(window, -1, sdl2.SDL_RENDERER_ACCELERATED)
texture = SDL_CreateTexture(renderer, sdl2.SDL_PIXELFORMAT_RGB888, sdl2.SDL_TEXTUREACCESS_STREAMING, 1024, 768)
surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000)
running = True
while running:
events = sdl2.ext.get_events()
for event in events:
if event.type == sdl2.SDL_QUIT or event.type == sdl2.SDL_MOUSEBUTTONDOWN:
running = False
break
sdl2.SDL_LockTexture(texture, None, ctypes.byref(ctypes.c_void_p(surface.contents.pixels)), ctypes.byref(ctypes.c_int(surface.contents.pitch)))
#
# How to change the pixels ???
# surface.contents.pixels[0][0] = Color(0, 255, 255)

sdl2.SDL_UnlockTexture(texture)
# window.refresh()
sdl2.SDL_RenderPresent(renderer)
return 0

如何在surface.contents.pixels中更改像素?

感谢!

如果要调整表面像素数据,为什么要锁定纹理?也许你想改变纹理,我希望我能帮助你: 所以 sdl2。SDL_LockTexture无法按预期工作。它锁定纹理,但最后两个参数用于返回纹理的间距和像素数据。这很奇怪。您通常希望函数如下所示:

pixels, pitch = sdl2.SDL_LockTexture(texture, None)

因此,您应该传递空变量,而不是 surface.content.pixel 和 surface.content.pitch,这些变量应指定为 ctype 变量。例:

pixels = ctypes.c_void_p()
pitch  = ctypes.c_int()
sdl2.SDL_LockTexture(texture, None, ctypes.byref(pixels), ctypes.byref(pitch))

所以SDL_LockTexture之后,你得到了这些变量中的像素数据和音高。 如果我们更改像素,纹理会在解锁纹理时自动保存更改。

但是,像素的格式不正确。因此,为了更改它,我们必须对其进行转换:

actual_pixels = ctypes.cast(pixels, ctypes.POINTER(ctypes.c_ubyte * (pitch.value * size[1]))).contents

现在我们有一些可以合作的东西。

请注意,actual_pixels现在是一个一维数组,要更改它,您可以使用以下内容:

for x in range(0, size[0] * 4, 4):
for y in range(0, size[1]):
actual_pixels[x + (y * pitch.value)    ] = 255 # Red
actual_pixels[x + (y * pitch.value) + 1] = 255 # Green
actual_pixels[x + (y * pitch.value) + 2] = 255 # Blue 
actual_pixels[x + (y * pitch.value) + 3] = 255 # Alpha

然后,您只需解锁纹理即可保存。 如果纹理显示的内容与您想要的不同,您可以更改像素格式(我有 sdl2。SDL_PIXELFORMAT_RGBA32(的纹理,或者如果 alpha 不起作用,请使用sdl2。SDL_SetTextureBlendMode(纹理,SDL2.SDL_BLENDMODE_BLEND(。

您的函数将如下所示:

def run():
sdl2.ext.init()
window = SDL_CreateWindow(b"test", sdl2.SDL_WINDOWPOS_CENTERED, sdl2.SDL_WINDOWPOS_CENTERED, 1024, 768, sdl2.SDL_WINDOW_SHOWN)
renderer = SDL_CreateRenderer(window, -1, sdl2.SDL_RENDERER_ACCELERATED)
size = (100, 100)
texture = SDL_CreateTexture(renderer, sdl2.SDL_PIXELFORMAT_RGB888, sdl2.SDL_TEXTUREACCESS_STREAMING, size[0], size[1])
#surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000)
running = True
while running:
events = sdl2.ext.get_events()
for event in events:
if event.type == sdl2.SDL_QUIT or event.type == sdl2.SDL_MOUSEBUTTONDOWN:
running = False
break

pixels = ctypes.c_void_p()
pitch  = ctypes.c_int()
sdl2.SDL_LockTexture(texture, None, ctypes.byref(pixels), ctypes.byref(pitch))
actual_pixels = ctypes.cast(pixels, ctypes.POINTER(ctypes.c_ubyte * (pitch.value * size[1]))).contents
for x in range(0, size[0] * 4, 4):
for y in range(0, size[1]):
actual_pixels[x + (y * pitch.value)    ] = randint(0,255) # Red
actual_pixels[x + (y * pitch.value) + 1] = randint(0,255) # Green
actual_pixels[x + (y * pitch.value) + 2] = randint(0,255) # Blue 
actual_pixels[x + (y * pitch.value) + 3] = randint(0,255) # Alpha
sdl2.SDL_UnlockTexture(texture)
sdl2.SDL_RenderCopy(
renderer,
texture,
sdl2.SDL_Rect(
0,
0,
size[0],
size[1]
),
sdl2.SDL_Rect(
0,
0,
size[0],
size[1]
))
sdl2.SDL_RenderPresent(renderer)

这只是一个例子,但您可以以任何方式调整像素。

需要注意的是,不建议在每一帧都使用此功能,图像越大,它需要的性能就越大。在我的示例中,我有一个大小为 100、100 的纹理,它的工作速度足够快。

但是,如果您想更改表面,则没有理由这样做。纹理要快得多。

相关内容

  • 没有找到相关文章

最新更新