从 bmp 文件中读取 RGB 像素

Posted

技术标签:

【中文标题】从 bmp 文件中读取 RGB 像素【英文标题】:Reading RGB pixels from bmp file 【发布时间】:2015-12-11 20:21:07 【问题描述】:

我有一个小的 bmp 文件,如果 R、G 和 B 不全为零,我想获取每个像素的 RGB 值并将这些值输出到 txt 文件中。我写了以下程序;它正确读取标题数据,但没有出现 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;



【问题讨论】:

BMP 文件格式比您想象的要复杂得多。使用库而不是滚动您自己的 BMP 导入器。 【参考方案1】:

我运行了代码,它运行良好,我想你的意思是“RGB 值没有出现”你没有看到整数值,在这种情况下,这将解决它:

ofs<<"R: "<<int(R)<<" G: "<<int(G)<<" B: "<<int(B)<<"  position in file: "<<ifs.tellg()<<"\r\n";

更新:我之前发布过你可以用 ifs >> R >> G >> B 替换 ifs.read();正如@Benjamin Lindley 指出的那样,这是不正确的,因为 >> 运算符用于格式化文本,而不是二进制。这意味着如果文件包含例如空格/换行符/等字符,操作员将跳过它并获取下一个字符。在这种简单的情况下,最好使用 ifs.get(char)。

【讨论】:

当然,除非@IInspectable 指出,该文件不像我以前测试的那样简单,在这种情况下,获取一个库并使用它来检查图像内部 我错过了很多次!很高兴它有帮助。你能把我的帖子标记为答案吗? 你绝对不能像那样读取 RGB 值。它们存储为二进制值,而不是文本。 布鲁斯,当然! :) 抱歉耽搁了,这个网站对我来说是新的【参考方案2】:

您对需要检查的图像编码做了几个假设。

如果您查看BMP header,您会看到:

在偏移量 28 处,文件不一定像您假设的那样每个像素具有 3*8 位。每个像素可以有 1、4、8 或 24 位;

在偏移量 30 处,指定了压缩类型。可以为 0 无 (你的假设)但也是Running Length Encoding: 1=RLE-8 或 2=RLE-4。

在偏移量 34 处可以直接读取图像数据的大小(以字节为单位),无需自行计算。

还要注意sizeof(int)理论上可能与4不同。这不是问题所在,但这解释了使用微软的DWORD(用于int)和WORD(简称)作为documented here的做法.

我怀疑您的文件中使用了 RLE:在这种情况下,由于压缩,您无法再查看固定位置的像素字节:您需要先解压缩数据。

【讨论】:

就我而言,就这么简单,这是我需要做的课堂作业:) 但感谢您的反馈,我真的很感激 :) 感谢您提供有关图像大小的信息! :)

以上是关于从 bmp 文件中读取 RGB 像素的主要内容,如果未能解决你的问题,请参考以下文章

Fread 返回 0,从 BMP 文件中读取像素

C++ - 从 BMP 文件中读取每个像素的位数

如何使用excel vba从图片文件中读取像素?

读取 BMP 文件 C++(读取 BMP 标头时出现问题)

C - 改变 bmp 文件的像素颜色

VC++图像处理中对BItmap文件结构的读取