我正在开发一个简单的程序,该程序应该将灰度24位bmp存储到数组中,操作数组然后从数组中创建另一个24位bmp。图像保证是正方形。该程序适用于尺寸为125x125或更小的图像,但为较大的图像输出垃圾,我无法弄清楚原因。代码和源图像如下:
SELECT FOR UPDATE
答案 0 :(得分:3)
这里的根本问题是调整,正如其他人在评论中所指出的那样。每条扫描线填充为四个字节的倍数。 (内存中的扫描线也必须以4字节边界开始,但这不适用于此。)对于较小的尺寸,你会变得“幸运”。
在24-bpp位图中,扫描线需要width * 3
个字节的数据。要计算需要多少填充字节,首先计算“步幅”,然后减去实际数据量。
int data_bytes_per_row = 3 * size; // your width is size
int stride = (data_bytes_per_row + 3) / 4 * 4;
int padding_bytes = stride - data_bytes_per_row;
现在你可以读取这样的数据:
int i = 0;
for (int row = 0; row < size; ++row) {
for (int col = 0; col < size; ++col) {
// need only every third byte
img[i++] = fgetc(source);
fgetc(source);
fgetc(source);
}
for (int pad = 0; pad < padding_bytes; ++pad) {
fgetc(source);
}
}
同样,写作:
int i = 0;
for (int row = 0; row < size; ++row) {
for (int col = 0; col < size; ++col) {
// need to triple every byte
fputc(img[i], dest);
fputc(img[i], dest);
fputc(img[i], dest);
++i;
}
for (int pad = 0; pad < padding_bytes; ++pad) {
fputc('\0', dest);
}
}
答案 1 :(得分:1)
24位位图每像素有3个字节。因此,如果您的图片有size * size
像素,则总字节数为size * size * 3
填充也是24位位图中的主要问题。但如果这不是问题,您必须按如下方式更改代码:
unsigned char img[size*size*3];
每隔3个字节读取一次,因此您必须阅读i * 3
,而不是i
for(int i = 0; i < size * size; i++)
{
img[i * 3] = (char)fgetc(source);
fgetc(source);
fgetc(source);
}
每隔3个字节写一次:
for(int i = 0; i < size * size; i++)
{
fputc(img[i * 3], dest);
fputc(img[i * 3], dest);
fputc(img[i * 3], dest);
}
要考虑填充,请改用此代码
int main(void)
{
FILE *fin = fopen("source.bmp", "rb");
FILE *fout = fopen("dest.bmp", "wb");
char info[54] = { 0 };
fread(info, sizeof(info), 1, fin);
fwrite(info, sizeof(info), 1, fout);
int width = *(int*)(info + 18);
int height = *(int*)(info + 22);
int bitcount = *(int*)(info + 28);
if(memcmp(info, "BM", 2) != 0 || width < 1 || height < 1 || bitcount != 24)
return 0;
int stride = width * 3 + width % 4;
char *buf = malloc(stride);
for(int row = height - 1; row >= 0; row--)
{
fread(buf, 1, stride, fin);
for(int col = 0; col < stride; col += 3)
{
unsigned char* p = (buf + col);
unsigned char b = p[0];
unsigned char g = p[1];
unsigned char r = p[2];
unsigned char gray = (unsigned char)(.3 * r + .6 * g + .1 * b);
p[0] = p[1] = p[2] = gray;
}
fwrite(buf, 1, stride, fout);
}
return 0;
}