如何将像素缓冲区复制到更大的缓冲区
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;
我正在尝试将一组像素复制到更大的像素缓冲区中。显然,我计算的坐标错误,可能是步幅,但我找不到我遗漏的东西。我得到了一个完全混乱的结果。
所以本质上,我试图实现的是将 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;