使用 BMP - 加载和保存
Working with BMP - loading and saving
我们正在与朋友一起尝试编写应用程序来处理 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;
}
您的图像数据大小公式有误。首先,您需要找到间距,方法是将宽度乘以每个像素的字节数(24 位图像为 3),然后四舍五入到最接近的 4 的倍数。然后将间距乘以高度;
int byte_width = width * 3;
int pitch = byte_width + (4 - byte_width % 4) % 4;
int volume = pitch * height;
正如我在自己的代码(大约 20 年前编写的)中看到的那样,图像的每一行都由 0 个或更多空字节补充以对齐起始字节。看来,你的对齐计算错误。
只需复制并粘贴到此处:
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++。
关于代码,我能说的是它已经过调试并且可以正常工作。但是我不记得为什么要在这里进行所有这些检查。
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];
您正在不必要地写 header 来归档两次。
我们正在与朋友一起尝试编写应用程序来处理 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;
}
您的图像数据大小公式有误。首先,您需要找到间距,方法是将宽度乘以每个像素的字节数(24 位图像为 3),然后四舍五入到最接近的 4 的倍数。然后将间距乘以高度;
int byte_width = width * 3;
int pitch = byte_width + (4 - byte_width % 4) % 4;
int volume = pitch * height;
正如我在自己的代码(大约 20 年前编写的)中看到的那样,图像的每一行都由 0 个或更多空字节补充以对齐起始字节。看来,你的对齐计算错误。
只需复制并粘贴到此处:
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++。
关于代码,我能说的是它已经过调试并且可以正常工作。但是我不记得为什么要在这里进行所有这些检查。
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];
您正在不必要地写 header 来归档两次。