如何将像素缓冲区复制到更大的缓冲区

How to copy a pixel buffer into a larger one

我正在尝试将一组像素复制到更大的像素缓冲区中。显然,我计算的坐标错误,可能是步幅,但我找不到我遗漏的东西。我得到了一个完全混乱的结果。

所以本质上,我试图实现的是将 RGBA 像素数组复制到更大的 RGB 数组(alpha 被丢弃), 保持正确的步伐。请参阅下图以直观地表示预期结果。

void draw(const uint8_t* tileRGBA, uint8_t* canvasRGB, const int canvasStride,
          const int tileWidth, const int tileHeight)
{
    for (int y = 0; y < tileHeight; y++)
    {
        for (int x = 0; x < tileWidth; x++)
        {
            long tileIndex = (4 * x) + (y * tileWidth);
            long canvasIndex = (3 * x) + (y * canvasStride);

            canvasRGB[canvasIndex] = tileRGBA[tileIndex];
            canvasRGB[canvasIndex + 1] = tileRGBA[tileIndex + 1];
            canvasRGB[canvasIndex + 2] = tileRGBA[tileIndex + 2];
        }
    }
}

uint8_t* test(uint32_t* tileRGBA, const int tileWidth, const int tileHeight)
{
    int canvasStride = tileWidth * 5; // 5 is just an arbitrary value for this example, in this case a canvas 5 times the width of the tile

    uint8_t* canvasRGB = new uint8_t[canvasStride * tileHeight * 3];

    draw((uint8_t*)tileRGBA, canvasRGB, canvasStride, tileWidth, tileHeight);

    return canvasRGB;
}

已解决:感谢 Johnny Mopp 的评论。这是括号的问题。

这个:

long tileIndex = (4 * x) + (y * tileWidth)
long canvasIndex = (3 * x) + (y * canvasStride);

一定是这样的:

long tileIndex = 4 * (x + y * tileWidth);
long canvasIndex = 3 * (x + y * canvasStride);

问题出在你的索引计算上。

要在一维数组中获取二维索引(行,列),您可以这样做:

index = ((number_of_columns * row) + col) * sizeof(data)

其中 number_of_columns 是数据中 "columns" 的预期数量 - 在本例中为图像的宽度。 sizeof(data) 是数组中一项的大小(以字节为单位)——在本例中,RGBA 为 4 个字节,RGB 为 3 个字节。所以,正如你所确定的,它应该是:

long tileIndex = 4 * (x + y * tileWidth);
long canvasIndex = 3 * (x + y * canvasStride);

如果可以将数据表示为单个项目,则可以取消 sizeof 乘法。例如,在您的情况下,创建 2 个结构:

struct RGB {
    uint8_t r,g,b;
};
struct RGBA {
    uint8_t r,g,b,a;
};

然后将参数作为这些结构的数组传递:

void draw(const RGBA* tileRGBA, RGB* canvasRGB, const int canvasStride, const int tileWidth, const int tileHeight)

则计算简化为:

long tileIndex = x + y * tileWidth;
long canvasIndex = x + y * canvasStride;