从 bmp 文件中读取 RGB 像素
Reading RGB pixels from bmp file
我有一个小的 bmp 文件,如果 R、G 和 B 不全为零,我想获取每个像素的 RGB 值并将这些值输出到一个 txt 文件中。我写了以下程序;它正确读取了 header 数据,但没有显示 RGB 值。我假设我在 for 循环中做错了什么。
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
ifstream ifs;
ofstream ofs;
char input[80];
char output[80];
cout<<"Input file name"<<endl;
cin>>input;
ifs.open(input, ios::binary);
if(!ifs)
{
cout<<"Error in opening file"<<endl;
system("pause");
return 0;
}
cout<<"Output file name"<<endl;
cin>>output;
ofs.open(output, ios::binary);
ifs.seekg(2);
int file_size;
ifs.read((char*)&file_size, sizeof(int));
ofs<<"Bitmap size: "<<file_size<<"\r\n";
ifs.seekg(10);
int beg;
ifs.read((char*)&beg, sizeof(int));
ofs<<"Beggining of image: "<<beg<<"\r\n";
ifs.seekg(18);
int columns;
ifs.read((char*)&columns, sizeof(int));
ofs<<"Column number: "<<columns<<"\r\n";
ifs.seekg(22);
int rows;
ifs.read((char*)&rows, sizeof(int));
ofs<<"Row number: "<<rows<<"\r\n";
int image_size=0;
columns+=(3*columns)%4;
image_size=3*columns*rows;
ofs<<"Size of image"<<image_size<<"\r\n";
ifs.seekg(beg);
unsigned char R,G,B;
for(int i=0; i<image_size; i+=3)
{
ifs.read((char*)&B, sizeof(unsigned char));
ifs.read((char*)&G, sizeof(unsigned char));
ifs.read((char*)&R, sizeof(unsigned char));
if(R!=0 || G!=0 || B!=0)
ofs<<"R: "<<R<<" G: "<<G<<" B: "<<B<<" position in file: "<<ifs.tellg()<<"\r\n";
}
system("pause");
return 0;
}
我 运行 代码并且它工作正常,我认为你的意思是“RGB 值没有出现”你没有看到整数值,在这种情况下这将修复它:
ofs<<"R: "<<int(R)<<" G: "<<int(G)<<" B: "<<int(B)<<" position in file: "<<ifs.tellg()<<"\r\n";
更新:我之前发布过,您可以将 ifs.read() 替换为 ifs >> R >> G >> B;正如@Benjamin Lindley 指出的那样,这是不正确的,因为 >> 运算符用于格式化文本,而不是二进制。这意味着如果文件包含例如 space/newline/etc 字符,运算符将跳过它并获取下一个字符。在这种简单的情况下最好使用 ifs.get(char)。
您对需要检查的图像的编码做了几个假设。
如果您查看 BMP header,您会看到:
在偏移量 28 处文件不一定像您假设的那样每个像素有 3*8 位。每个像素可以有 1、4、8 或 24 位;
在偏移量30处指定了压缩类型。 none 可以为 0
(你的假设)但也是 Running Length Encoding: 1=RLE-8 或 2=RLE-4。
在offset 34处可以直接读取图片数据的字节大小,不需要自己计算。
还请注意 sizeof(int)
在理论上可能与 4 不同。这不是这里的问题,但这解释了使用 Microsoft 的 DWORD
(用于 int)和 WORD
的做法(简称)为 documented here。
我怀疑你的文件中使用了RLE:在这种情况下,由于压缩,你不能再查看固定位置的像素字节:你需要先解压缩数据。
我有一个小的 bmp 文件,如果 R、G 和 B 不全为零,我想获取每个像素的 RGB 值并将这些值输出到一个 txt 文件中。我写了以下程序;它正确读取了 header 数据,但没有显示 RGB 值。我假设我在 for 循环中做错了什么。
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
ifstream ifs;
ofstream ofs;
char input[80];
char output[80];
cout<<"Input file name"<<endl;
cin>>input;
ifs.open(input, ios::binary);
if(!ifs)
{
cout<<"Error in opening file"<<endl;
system("pause");
return 0;
}
cout<<"Output file name"<<endl;
cin>>output;
ofs.open(output, ios::binary);
ifs.seekg(2);
int file_size;
ifs.read((char*)&file_size, sizeof(int));
ofs<<"Bitmap size: "<<file_size<<"\r\n";
ifs.seekg(10);
int beg;
ifs.read((char*)&beg, sizeof(int));
ofs<<"Beggining of image: "<<beg<<"\r\n";
ifs.seekg(18);
int columns;
ifs.read((char*)&columns, sizeof(int));
ofs<<"Column number: "<<columns<<"\r\n";
ifs.seekg(22);
int rows;
ifs.read((char*)&rows, sizeof(int));
ofs<<"Row number: "<<rows<<"\r\n";
int image_size=0;
columns+=(3*columns)%4;
image_size=3*columns*rows;
ofs<<"Size of image"<<image_size<<"\r\n";
ifs.seekg(beg);
unsigned char R,G,B;
for(int i=0; i<image_size; i+=3)
{
ifs.read((char*)&B, sizeof(unsigned char));
ifs.read((char*)&G, sizeof(unsigned char));
ifs.read((char*)&R, sizeof(unsigned char));
if(R!=0 || G!=0 || B!=0)
ofs<<"R: "<<R<<" G: "<<G<<" B: "<<B<<" position in file: "<<ifs.tellg()<<"\r\n";
}
system("pause");
return 0;
}
我 运行 代码并且它工作正常,我认为你的意思是“RGB 值没有出现”你没有看到整数值,在这种情况下这将修复它:
ofs<<"R: "<<int(R)<<" G: "<<int(G)<<" B: "<<int(B)<<" position in file: "<<ifs.tellg()<<"\r\n";
更新:我之前发布过,您可以将 ifs.read() 替换为 ifs >> R >> G >> B;正如@Benjamin Lindley 指出的那样,这是不正确的,因为 >> 运算符用于格式化文本,而不是二进制。这意味着如果文件包含例如 space/newline/etc 字符,运算符将跳过它并获取下一个字符。在这种简单的情况下最好使用 ifs.get(char)。
您对需要检查的图像的编码做了几个假设。
如果您查看 BMP header,您会看到:
在偏移量 28 处文件不一定像您假设的那样每个像素有 3*8 位。每个像素可以有 1、4、8 或 24 位;
在偏移量30处指定了压缩类型。 none 可以为 0 (你的假设)但也是 Running Length Encoding: 1=RLE-8 或 2=RLE-4。
在offset 34处可以直接读取图片数据的字节大小,不需要自己计算。
还请注意 sizeof(int)
在理论上可能与 4 不同。这不是这里的问题,但这解释了使用 Microsoft 的 DWORD
(用于 int)和 WORD
的做法(简称)为 documented here。
我怀疑你的文件中使用了RLE:在这种情况下,由于压缩,你不能再查看固定位置的像素字节:你需要先解压缩数据。