如何在 C 中用新的/更新的像素阵列更新/替换 SDL Surface 像素阵列?

Posted

技术标签:

【中文标题】如何在 C 中用新的/更新的像素阵列更新/替换 SDL Surface 像素阵列?【英文标题】:How do I update/replace an SDL Surface pixel array with a new/updated pixel array in C? 【发布时间】:2020-05-25 20:30:13 【问题描述】:

我正在尝试使用 SDL 使单色图像出现在屏幕上。所以我拥有的数组将具有 0x00 或 0xFF 的值。

首先,我制作了一个 200x200 的小窗口,创建了一个新表面,使用 FillRect 将其设置为黑色。当我打印出音高和像素格式时,我得到 800 的音高和 rgb888 的格式。如果我理解正确,这意味着表面->像素的尺寸是 800x200,因为每个像素都附加了 2 个字节的信息?

我不明白的是,如果我想将该表面像素阵列更改为完全不同的东西,阵列的格式是什么?如果我有一个包含一个像素 [0xFF] 的简单数组,那么为表面的 RGB 值格式化的数组是否会是 [0xFF, 0xFF, 0xFF]?对于我想在屏幕上更改的每个像素,我需要更新数组中的三个值吗?

在我弄清楚如何格式化数组后,它是否像surface->pixels = newArray一样简单?然后更新窗口表面之后?

【问题讨论】:

【参考方案1】:

SDL_pixels.h

#define SDL_DEFINE_PIXELFORMAT(type, order, layout, bits, bytes) \
    ((1 << 28) | ((type) << 24) | ((order) << 20) | ((layout) << 16) | \
     ((bits) << 8) | ((bytes) << 0))

对于RGB888,我们有:

    SDL_PIXELFORMAT_RGB888 =
        SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB,
                               SDL_PACKEDLAYOUT_8888, 24, 4),

对于SDL_PACKEDORDER_*,我们有:

/** Packed component order, high bit -> low bit. */

所以,每个像素都是一个 [packed] 32 unsigned int,取入 32 位整数时的顺序是:

X | R | G | B

对于小端机器,在内存中的顺序是颠倒的:

B | G | R | X

但是,请参阅下面的警告...


如果我理解正确,这意味着表面->像素的尺寸是 800x200,因为每个像素都附加了额外的 2 个字节的信息?

不,每个像素是 4 字节,只有 3 个 [有用] 值(如上以 32 位整数查看)。

等式是:

pitch = number_of_bytes_per_pixel_in_memory * width

对你来说,是:800 = 4 * 200


该格式可以更改RGB 字节的顺序,以及第四个字节是否具有任何价值(例如,RGBA 格式的透明度/alpha 混合)。

对于RGB888,以下是我为说明而编写的一些转换函数:

typedef unsigned int u32;
typedef unsigned char byte;

enum 
    RSHF = 16,
    GSHF = 8,
    BSHF = 0,
;

// rgb2pixel -- convert RGB values to pixel value
u32
rgb2pixel(byte r,byte g,byte b)

    u32 pix;

    pix = 0;
    pix |= ((u32) r) << RSHF;
    pix |= ((u32) g) << GSHF;
    pix |= ((u32) b) << BSHF;

    return pix;


// pix2red -- extract red from RGB pixel
byte
pix2red(u32 pix)

    byte color;

    color = pix >> RSHF;

    return color;


// pix2green -- extract green from RGB pixel
byte
pix2green(u32 pix)

    byte color;

    color = pix >> GSHF;

    return color;


// pix2blue -- extract blue from RGB pixel
byte
pix2blue(u32 pix)

    byte color;

    color = pix >> BSHF;

    return color;


警告:我不完全确定“打包的组件订单”是什么意思。

我对上述顺序的解释假设它是像素被提取为 32 位整数值之后的顺序。

但是,它可能意味着它是内存中的顺序,在这种情况下,我上面创建的图表将被颠倒。

如果您从以下位置存储所有值:

rgb2pixel(0xFF,0x00,0x00)

你应该得到一个红色的背景。如果你换成蓝色,那么RSHFBSHF 应该互换。

【讨论】:

感谢详细回答,但我必须注意,音高公式仅在特定情况下是正确的。如果格式是例如RGB24(未打包到 32 位,每个像素为 3 个字节)然后行将被填充为 4 字节对齐,并且间距将反映最后的间隙(最后的 0-3 个额外字节,取决于宽度)。跨度>

以上是关于如何在 C 中用新的/更新的像素阵列更新/替换 SDL Surface 像素阵列?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 Apollo Client 中用新 id 更新或替换缓存条目的 id?

如何更新云套件数据

如何在 ng-bootstrap 轮播中用 div 替换图像?

在Cassandra中用新的键值对更新地图类型列,而不是完全覆盖地图。

一个博客萌新的C语言之旅(持续更新中....)

使用 python 中的 sed 替换字符串和更新文件