问题
I have a small bmp file and I want to get the RGB values of each pixel and output those values into a txt file if R, G, and B aren't all zero. I wrote the following program; it reads the header data correctly, but the RGB values aren't coming up. I assume I did something wrong in the for loop.
#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;
}
回答1:
I ran the code and it works fine, I presume you mean by 'RGB values aren't coming up' you are not seeing the integer values, in which case this will fix it:
ofs<<"R: "<<int(R)<<" G: "<<int(G)<<" B: "<<int(B)<<" position in file: "<<ifs.tellg()<<"\r\n";
Update: I posted earlier that you could replace ifs.read() with ifs >> R >> G >> B; As @Benjamin Lindley points out, this is incorrect as the >> operator is for formatted text, not binary. This means if the file contains eg a space/newline/etc character, the operator will skip it and take the next char. Better to use ifs.get(char) in this simple case.
回答2:
You make several assumptions on the encoding of the image that you need to check.
If you look at the BMP header, you'll see:
at offset 28 that the file doesn't necessarily have 3*8 bits per pixel as you assume. It can have 1, 4, 8, or 24 bits per pixel;
at offset 30, the compression type is specified. It can be 0 for none (your assumption) but also be Running Length Encoding: 1=RLE-8 or 2=RLE-4.
at offset 34 you can directly read the size of image data in bytes so that you don't need to calculate it on your own.
Attention also that sizeof(int)
could be in theory different from 4. It's not the problem here, but this explains the practice of using microsoft's DWORD
(for int) and WORD
(for short) as documented here.
I suspect that RLE is used in you file: In this case, due to the compression, you can no longer look at the pixel bytes at a fixed position: you'd need to uncompress the data first.
来源:https://stackoverflow.com/questions/34231931/reading-rgb-pixels-from-bmp-file