如何使用 SDL 修改像素?

发布于 2024-11-26 19:50:50 字数 192 浏览 0 评论 0原文

我有一个小问题:我无法修改 SDL 屏幕的像素。

具体来说,以下代码不起作用。

Uint32 * pixels = (Uint32 *) screen -> pixels; 
screen -> pixels = pixels;

这可以编译,但没有显示任何内容。我缺少什么?

I have a slight problem: I can't modify the pixels of an SDL screen.

Specifically, the following code doesn't work.

Uint32 * pixels = (Uint32 *) screen -> pixels; 
screen -> pixels = pixels;

This compiles, but it doesn't show anything. What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

多情出卖 2024-12-03 19:50:50

我有以下函数用于在 SDL_Surface 中设置像素。有两个版本,分别适用于 32 位、24 位、16 位和 8 位表面。如果您只想设置单个像素,则可以使用普通版本。但是如果你想设置一堆像素,首先你锁定表面,然后你使用nolock版本(这样命名是因为它不锁定表面),然后你解锁。这样,您就不会重复锁定和解锁表面,这应该是一项昂贵的操作,尽管我认为我从未真正测试过它。

void PutPixel32_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint32));
    *((Uint32*)pixel) = color;
}

void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    pixel[0] = (color >> 24) & 0xFF;
    pixel[1] = (color >> 16) & 0xFF;
    pixel[2] = (color >> 8) & 0xFF;
#else
    pixel[0] = color & 0xFF;
    pixel[1] = (color >> 8) & 0xFF;
    pixel[2] = (color >> 16) & 0xFF;
#endif
}

void PutPixel16_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint16));
    *((Uint16*)pixel) = color & 0xFFFF;
}

void PutPixel8_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint8));
    *pixel = color & 0xFF;
}

void PutPixel32(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel32_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}

void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel24_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
}

void PutPixel16(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel16_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}

void PutPixel8(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel8_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}

I had the following functions lying around for setting pixels in an SDL_Surface. There are two versions each for 32-bit, 24-bit, 16-bit and 8-bit surfaces. If you just want to set a single pixel, you would use the normal versions. But if you want to set a bunch of pixels, first you lock the surface, then you use the nolock version(named so because it does not lock the surface), then you unlock. This way you aren't repeatedly locking and unlocking the surface, which is supposed to be an expensive operation, though I don't think I ever actually tested it.

void PutPixel32_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint32));
    *((Uint32*)pixel) = color;
}

void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    pixel[0] = (color >> 24) & 0xFF;
    pixel[1] = (color >> 16) & 0xFF;
    pixel[2] = (color >> 8) & 0xFF;
#else
    pixel[0] = color & 0xFF;
    pixel[1] = (color >> 8) & 0xFF;
    pixel[2] = (color >> 16) & 0xFF;
#endif
}

void PutPixel16_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint16));
    *((Uint16*)pixel) = color & 0xFFFF;
}

void PutPixel8_nolock(SDL_Surface * surface, int x, int y, Uint32 color)
{
    Uint8 * pixel = (Uint8*)surface->pixels;
    pixel += (y * surface->pitch) + (x * sizeof(Uint8));
    *pixel = color & 0xFF;
}

void PutPixel32(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel32_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}

void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel24_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
}

void PutPixel16(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel16_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}

void PutPixel8(SDL_Surface * surface, int x, int y, Uint32 color)
{
    if( SDL_MUSTLOCK(surface) )
        SDL_LockSurface(surface);
    PutPixel8_nolock(surface, x, y, color);
    if( SDL_MUSTLOCK(surface) )
        SDL_UnlockSurface(surface);
}
恬淡成诗 2024-12-03 19:50:50

操作 screen->pixels 的内容将会修改像素,但有一些注意事项。

首先,正如代码片段中所示,请注意,screen->pixels 是指向表面像素数据的指针。基于表面的宽度(surface->pitch)和像素的大小(以字节为单位),像素数据本身作为线性数组从该指针进行访问。
像素大小(又称深度)是在初始化期间使用 SDL_SetVideoMode() 设置的,可以在 screen->format->BytesPerPixel 中找到。

进行更改之前可能需要锁定表面。

此外,根据传递给 SDL_SetVideoMode() 的选项,您可能还需要调用 SDL_Flip() 来显示您所做的更改。

可以在此处找到像素操作的工作示例。


正如评论中所指出的,问题中列出的代码实际上不会执行任何可见的操作,因为没有对像素数据进行任何更改。

Manipulating the contents of screen->pixels will modify pixels, with a couple of caveats.

First, as you've shown in the code snippet, note that screen->pixels is a pointer to the pixel data of the surface. The pixel data itself is accessed as a linear array from that pointer based on the width of the surface (surface->pitch) and the size of the pixel in bytes.
The pixel size (aka depth) is set during initialisation, using SDL_SetVideoMode() and can be found in screen->format->BytesPerPixel.

Locking of the surface before making changes may be necessary.

In addition, depending on the options that were passed to SDL_SetVideoMode() you may also need to call SDL_Flip() to display the changes that you've made.

A working example of pixel manipulation can be found here.


As has been pointed out in the comments, the code listed in the question is not actually going to do anything visible as no changes are being made to the pixel data.

紫﹏色ふ单纯 2024-12-03 19:50:50

添加一个 SDL2 变体,不是在表面上操作像素,而是在渲染器中操作像素(如果您尝试在屏幕外部操作像素,则不会崩溃,这与之前的答案不同)

void putPixelRGB(SDL_Renderer* renderer, int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
    SDL_SetRenderDrawColor(renderer, (Uint8)r, (Uint8)g, (Uint8)b, 255);
    SDL_RenderDrawPoint(renderer, x, y);
}

Adding an SDL2 variant manipulating pixels not on a surface but in a renderer (and which does not crash if you try to manipulate pixels outside of your screen, unlike previous answers)

void putPixelRGB(SDL_Renderer* renderer, int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
    SDL_SetRenderDrawColor(renderer, (Uint8)r, (Uint8)g, (Uint8)b, 255);
    SDL_RenderDrawPoint(renderer, x, y);
}
烟火散人牵绊 2024-12-03 19:50:50

您不得修改 SDL_Surface 结构的内容。如果你想复制像素,你应该 malloc() 一些内存,然后 memcpy() 像素。

You must not modify the contents of the SDL_Surface structure. If you want to copy the pixels you should malloc() some memory and then memcpy() the pixels.

踏雪无痕 2024-12-03 19:50:50

为什么要改变一个像素?

制作一个新的表面&一个矩形

// 代码 ------------>

SDL_Surface *screen, *PIXEL = NULL;

SDL_Rect PIXELRect;
PIXELRect.h=5;
PIXELRect.w=5;
PIXELRect.x=100;
PIXELRect.y=100;

screen = SDL_SetVideoMode(640, 468, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT);

while(running){
SDL_FillRect(screen, &PIXELRect, (#color));
}

why change a pixel?

make a new surface & a Rect

// CODE ------------>

SDL_Surface *screen, *PIXEL = NULL;

SDL_Rect PIXELRect;
PIXELRect.h=5;
PIXELRect.w=5;
PIXELRect.x=100;
PIXELRect.y=100;

screen = SDL_SetVideoMode(640, 468, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT);

while(running){
SDL_FillRect(screen, &PIXELRect, (#color));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文