Bmp行程编码C++文件类
时间: 2023-11-14 09:11:24 浏览: 77
C++图像处理用于显示bmp文件的类,类名为DIB
以下是一个简单的C++文件类,可用于读取BMP文件并进行行程编码压缩。注意,此示例只支持24位无压缩BMP格式文件。
```
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
// BMP文件头结构体
#pragma pack(push, 1) // 关闭结构体字节对齐
struct BMPHeader
{
char bfType[2];
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
};
#pragma pack(pop) // 恢复结构体字节对齐
// BMP信息头结构体
#pragma pack(push, 1) // 关闭结构体字节对齐
struct BMPInfoHeader
{
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
};
#pragma pack(pop) // 恢复结构体字节对齐
// RGB颜色结构体
#pragma pack(push, 1) // 关闭结构体字节对齐
struct RGBColor
{
unsigned char blue;
unsigned char green;
unsigned char red;
};
#pragma pack(pop) // 恢复结构体字节对齐
// 行程编码的像素结构体
#pragma pack(push, 1) // 关闭结构体字节对齐
struct RLEPixel
{
unsigned char count; // 连续像素的数量
RGBColor color; // 颜色值
};
#pragma pack(pop) // 恢复结构体字节对齐
// BMP文件类
class BMPFile
{
public:
BMPFile() {}
~BMPFile() {}
// 读取BMP文件
bool read(const char* filename)
{
ifstream file(filename, ios::binary);
if (!file)
{
cerr << "Error: Failed to open file " << filename << endl;
return false;
}
BMPHeader header;
file.read((char*)&header, sizeof(BMPHeader));
BMPInfoHeader infoHeader;
file.read((char*)&infoHeader, sizeof(BMPInfoHeader));
if (header.bfType[0] != 'B' || header.bfType[1] != 'M')
{
cerr << "Error: Invalid file format" << endl;
return false;
}
if (infoHeader.biCompression != 0)
{
cerr << "Error: Unsupported BMP format" << endl;
return false;
}
width = infoHeader.biWidth;
height = infoHeader.biHeight;
int rowSize = (width * 3 + 3) / 4 * 4; // 每行像素数据的字节数,需要按照4字节对齐
int imageSize = rowSize * height; // 图像数据区的大小
pixels.resize(width * height);
file.seekg(header.bfOffBits, ios::beg); // 定位到像素数据区
for (int i = 0; i < height; i++)
{
RGBColor* row = &pixels[(height - i - 1) * width]; // 由于BMP文件的像素数据是从下到上存储的,所以需要反向读取
for (int j = 0; j < width; j++)
{
RGBColor color;
file.read((char*)&color, sizeof(RGBColor));
row[j] = color;
}
file.seekg(rowSize - width * sizeof(RGBColor), ios::cur); // 跳过4字节对齐的填充数据
}
file.close();
return true;
}
// 将BMP文件进行行程编码压缩,并保存为新的BMP文件
bool compress(const char* filename)
{
ofstream file(filename, ios::binary);
if (!file)
{
cerr << "Error: Failed to open file " << filename << endl;
return false;
}
int rowSize = (width * 3 + 3) / 4 * 4; // 每行像素数据的字节数,需要按照4字节对齐
int imageSize = rowSize * height; // 图像数据区的大小
BMPHeader header;
header.bfType[0] = 'B';
header.bfType[1] = 'M';
header.bfSize = sizeof(BMPHeader) + sizeof(BMPInfoHeader) + width * height * sizeof(RLEPixel);
header.bfReserved1 = 0;
header.bfReserved2 = 0;
header.bfOffBits = sizeof(BMPHeader) + sizeof(BMPInfoHeader);
BMPInfoHeader infoHeader;
infoHeader.biSize = sizeof(BMPInfoHeader);
infoHeader.biWidth = width;
infoHeader.biHeight = height;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 24;
infoHeader.biCompression = 0;
infoHeader.biSizeImage = width * height * sizeof(RLEPixel);
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
file.write((char*)&header, sizeof(BMPHeader));
file.write((char*)&infoHeader, sizeof(BMPInfoHeader));
vector<RLEPixel> rlePixels; // 存储行程编码后的像素数据
for (int i = 0; i < height; i++)
{
RGBColor* row = &pixels[(height - i - 1) * width]; // 由于BMP文件的像素数据是从下到上存储的,所以需要反向读取
int j = 0;
while (j < width)
{
RLEPixel pixel;
pixel.color = row[j];
int count = 1;
while (j + count < width && row[j + count].red == pixel.color.red && row[j + count].green == pixel.color.green && row[j + count].blue == pixel.color.blue && count < 255)
{
count++;
}
pixel.count = count;
rlePixels.push_back(pixel);
j += count;
}
// 添加行终止标志
RLEPixel endPixel;
endPixel.count = 0;
rlePixels.push_back(endPixel);
}
file.write((char*)rlePixels.data(), rlePixels.size() * sizeof(RLEPixel));
file.close();
return true;
}
private:
int width;
int height;
vector<RGBColor> pixels;
};
```
使用示例:
```
BMPFile bmpFile;
bmpFile.read("input.bmp");
bmpFile.compress("output.bmp");
```
其中,`input.bmp`为输入文件名,`output.bmp`为输出文件名。
阅读全文