与朋友们一起,我们正在尝试编写应用程序来处理BMP文件,我们将尽可能简化它,因为我们刚刚开始学习C和C ++。使用新的实际尺寸的线条复制效果很好,但现在我想添加灰度效果并出现另一个问题:图片的右侧移动到左边 - 检查图片。是什么导致了这个问题?
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <unistd.h>
using namespace std;
void ReadBMP()
{
FILE* f = fopen("test2.bmp", "rb");
FILE* w = fopen("zapis.bmp", "wb");
if(f == NULL)
throw "Argument Exception";
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
fwrite(info, sizeof(unsigned char), 54, w);
int width = *(int*)&info[18];
int height = *(int*)&info[22];
cout << endl;
cout << "Width: " << width << endl;
cout << "Height: " << height << endl;
int realwidth = 3*width+(4 - ((3*width)%4))%4;
int volume = height * realwidth;
unsigned char* data = new unsigned char[volume];
fwrite(info, sizeof(unsigned char), 54, w);
fread(data, sizeof(unsigned char), volume, f);
unsigned char color = 0;
for(int i = 0; i < volume; i+=3)
{
color = 0;
color+=data[i]*0.114;
color+=data[i+1]*0.587;
color+=data[i+2]*0.299;
data[i] = color;
data[i+1] = color;
data[i+2] = color;
}
fwrite(data, sizeof(unsigned char), volume, w);
fclose(f);
fclose(w);
delete(data);
}
int main()
{
ReadBMP();
return 0;
}
答案 0 :(得分:1)
您的图像数据大小公式错误。首先,您需要通过将宽度乘以每个像素的字节数(24位图像为3),然后向上舍入到最接近的4的倍数来找到音高。然后将音高乘以高度;
int byte_width = width * 3;
int pitch = byte_width + (4 - byte_width % 4) % 4;
int volume = pitch * height;
答案 1 :(得分:0)
正如我在自己的代码中看到的那样(大约20年前写的),图像的每一行都由0或更多空字节补充以对齐起始字节。看来,你计算错误的对齐方式。
只需复制&amp;粘贴在这里:
unsigned short paddingSize;
unsigned short bitsPerLine = width * bitsPerPixel;
if(1 == bitsPerPixel || 4 == bitsPerPixel)
{
if(bitsPerLine % 8)
bitsPerLine += 8;
paddingSize = (bitsPerLine/8) % 2;
}
else if(8 == bitsPerPixel)
paddingSize = 0x0003 & ~((bitsPerLine/8) % 4 - 1);
else
paddingSize = (bitsPerLine/8) % 2;
每一行的实际大小为calculatedSize + paddingSize
,其中calculatedSize
是行的精确大小,以字节为单位,即ceil(bitsPerLine/8)
或(bitsPerLine + 7)/8
ic C / C ++。
我可以对代码说些什么,它已经过调试并且可以正常工作。但我不记得为什么所有这些检查都在这里。
答案 2 :(得分:0)
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
// fwrite(info, sizeof(unsigned char), 54, w); --- comment this line !!!!!!!
int width = *(int*)&info[18];
int height = *(int*)&info[22];
您不必要地将标题写入文件两次。