我之前发过关于这个问题的帖子..但问题无法解决。 所以我可以诚实地说,这是我在编程经历中遇到的最奇怪,无法解释的并发症。
问题是当我从缓冲区中绘制bmp时。
如果我改变图像的尺寸,例如,如果我使宽度&gt; <身高或身高>宽度,图像正常呈现。看看代码:
void bmp_bdraw (BYTE* BUFF)
{
word WIDTH, HEIGHT, W, H; // word - unsigned short
BYTE R, G, B; // BYTE - unsigned char
(!BUFF || !BUFF[COUNT-1]) ? // debug1
(error("Error in function 'bmp_bdraw'. There is no data to read from.")) : ;
WIDTH = BUFF[18] + BUFF[19] * 256;
HEIGHT = BUFF[22] + BUFF[23] * 256;
ofs = 54;
if(BUFF[0] != 'B' | BUFF[1] != 'M') error // debug2
("Warning: Data identifier error in function 'bmp_bdraw' occurred. Invalid BMP file loaded.");
for(H=HEIGHT-1; H>=1; H--)
{
for(W=0; W<WIDTH; W++)
{
B = sgetc(BUFF); // fgetc-like function but from buff
G = sgetc(BUFF);
R = sgetc(BUFF);
setpen(R, G, B, 0, 1); // sets the color, transparancy and size of the pen
putpixel(W, H); // and puts the pixel at the right location
}
}
if(W != WIDTH || H > 1) // debug3
error("Error in function 'bmp_bdraw'. Rendering failed. The file might be damaged.");
if(real_fps < 11)
error("Too low fps rate."); // debug4
我在行中注意到的是:for(H=HEIGHT-1; H>=1; H--)
是H>=1
在直接绘制(bmp to render)函数(100%工作并使用相同的方法)中,它是H>=0
但是..如果我将H>=1
更改为H>=0
,则返回缓冲区溢出错误,返回
通过sgetc
函数。
答案 0 :(得分:2)
更新了代码
numPadBytes = WIDTH * 3;
numPadBytes %= 4;
if(0 != numPadBytes) numPadBytes = 4 - numPadBytes;
for(H=HEIGHT-1; H>=1; H--)
{
for(W=0; W<WIDTH; W++)
{
B = sgetc(BUFF); // fgetc-like function but from buff
G = sgetc(BUFF);
R = sgetc(BUFF);
setpen(R, G, B, 0, 1); // sets the color, transparancy and size of the pen
putpixel(W, H); // and puts the pixel at the right location
}
for(tmp = 0; tmp < numPadBytes; ++tmp)
{
/* Ignore bytes */
sgetc(BUFF);
}
}
您需要将numPadBytes
和tmp
声明为您函数的本地int
。
答案 1 :(得分:2)
您需要在x方向上遍历位图的 stride 。位图的每一行填充为四个字节的倍数。
您的代码循环遍历宽度(* 3个字节),但行末可能有1..3个额外字节。结果是你过早地开始绘制到输出缓冲区,将第一行之外的所有内容偏向左侧。
您可以按如下方式计算步幅。使用它而不是宽度。
int stride = 4 * ((width * bytesPerPixel + 3) / 4); // in bytes
因此,阅读图像数据看起来就像这样......
unsigned char *scan0 = buf + pixel_buffer_offset;
for (int y = 0; y < height; ++y)
{
// sets the pointer to the beginning of the yth row
unsigned byte *row = scan0 + y * stride;
for (int x = 0; x < width; ++x)
{
unsigned char b = *row++;
unsigned char g = *row++;
unsigned char r = *row++;
setpen(r, g, b, 0, 1);
putpixel(x, y);
}
}
你写的任何缓冲区应该初始化为0,因为我们没有写出填充字节。如果您不想这样做,那么您将需要遍历每一行的整个步幅。
还要确保为其分配了stride * height
个字节,而不是width * height * 3
。
答案 2 :(得分:1)
我建议只涉及一行并且不会引起头痛的事情:
ofs = ofs + WIDTH%4;
在外循环中,在内循环之后。我刚刚发现它有效..而且我不知道为什么人们提出这么多代码而不是这样做。如果其他人决定从缓冲区渲染,希望有所帮助。