如何在SDL_surface中设置像素?

10

我需要使用这个页面中的以下函数。 SDL_Surface结构被定义为:

typedef struct SDL_Surface {
    Uint32 flags;                           /* Read-only */
    SDL_PixelFormat *format;                /* Read-only */
    int w, h;                               /* Read-only */
    Uint16 pitch;                           /* Read-only */
    void *pixels;                           /* Read-write */
    SDL_Rect clip_rect;                     /* Read-only */
    int refcount;                           /* Read-mostly */
} SDL_Surface;

函数是:

void set_pixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
      Uint8 *target_pixel = (Uint8 *)surface->pixels + y * surface->pitch + x * 4;
      *(Uint32 *)target_pixel = pixel;
}

我有一些疑问,可能是因为缺乏真实图像。

  1. 为什么需要将surface->pitch乘以y,而将x乘以4
  2. 声明target_pixel8位整数指针,然后再将其转换为32位整数指针的必要性是什么?
  3. set_pixel函数返回后,target_pixel如何保留pixel值?
2个回答

10
  1. 每个像素的大小为4(表面使用Uint32值的像素),但计算是在Uint8中进行的。这个4很丑陋,见下文。
  2. 使地址计算以字节为单位。
  3. 由于要写入的像素实际上是32位的,指针必须是32位的才能进行单次写入。

计算必须以字节为单位,因为表面的pitch字段以字节为单位。

以下是重新编写的版本(比我最初尝试的要温和):

void set_pixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
  Uint32 * const target_pixel = (Uint32 *) ((Uint8 *) surface->pixels
                                             + y * surface->pitch
                                             + x * surface->format->BytesPerPixel);
  *target_pixel = pixel;
}

请注意我们如何使用surface->format->BytesPerPixel来分解4。魔术数字不是一个好主意。还要注意,以上假设表面确实正在使用32位像素。


1
可能是一个相当基础的问题,但是 pitch 代表什么?并且 surface->pixel 最初指向窗口的左上角吗? - noufal
2
首先:在“谷歌sdl pitch”上的第一个搜索结果是:“Pitch是内存缓冲区的宽度,可以大于表面的宽度。”说得非常流畅,无法再改进了。其次:是的。(其他任何位置都没有用处……) - Jongware

7
您可以使用以下代码:
unsigned char* pixels = (unsigned char*)surface -> pixels;
pixels[4 * (y * surface -> w + x) + c] = 255;            

x是您想要的点的x值,y是点的y值,c表示您需要的信息:

c=0对应蓝色

c=1对应绿色

c=2对应红色

c=3对应透明度(opacity)


2
表面->w是错误的,应该使用表面->pitch,因为内存对齐填充(通常可被4整除)用于内部内存优化。 - Raffaello

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接