1首先我们需要定义组成bmp的四部分的结构体
#pragma once
using BYTE = unsigned char;
using WORD = unsigned short;
using DWORD = unsigned int;
using LONG = unsigned long;
#pragma pack(push)
#pragma pack(2)
struct BITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
};
struct BITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
};
struct RGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRED;
BYTE rgbReserved;
};
#pragma pack(pop)
2 构建可以读取bmp的类bitmap
#pragma once
#include "bitmapQuad.h"
#include <iostream>
#include <fstream>
class bitmap {
private:
FILE* m_rfp;
FILE* m_wfp;
FILE* m_wfp1;
FILE* m_wfp2;
BITMAPFILEHEADER* m_pbfHeader;
BITMAPINFOHEADER* m_pbiHeader;
RGBQUAD* m_prgbQuad;
BYTE* m_pImgData;
DWORD m_imgSize;
private:
inline void readFileHeader(BITMAPFILEHEADER* bmFileHeader);
inline void readInfoHeader(BITMAPINFOHEADER* bmInfoHeader);
inline void readRgbQuad(RGBQUAD* rgbQuad, const int& rgbQuadSize);
inline void readImgData(BYTE* pImgData, const DWORD& imgSize);
private:
inline void writeFileHeader(BITMAPFILEHEADER* pbfHeader);
inline void writeInfoHeader(BITMAPINFOHEADER* pbiHeader);
inline void writeRgbQuad(RGBQUAD* prgbQuad, const int& rgbQuadSize);
inline void writeImgData(BYTE* pImgData, const DWORD& imgSize);
private:
void createGrey_8();
public:
bitmap(const char* readFilePath, const char* writeFilePath);
bitmap(const char* readFilePath, const char* writeFilePath0, const char* writeFilePath1, const char* writeFilePath2);
~bitmap();
void rgb24_to_grey8();
void grey8_to_antiGrey8();
void rgb24_to_3grey8();
};
3 实现
#include "bitmap.h"
#pragma region bmp文件四部分的读入
inline
void bitmap::readFileHeader(BITMAPFILEHEADER* bmFileHeader) {
fread(bmFileHeader, sizeof(BITMAPFILEHEADER), 1, m_rfp);
}
inline
void bitmap::readInfoHeader(BITMAPINFOHEADER* bmInfoHeader) {
fread(bmInfoHeader, sizeof(BITMAPINFOHEADER), 1, m_rfp);
}
inline
void bitmap::readRgbQuad(RGBQUAD* rgbQuad, const int& rgbQuadSize) {
fread(rgbQuad, rgbQuadSize, 1, m_rfp);
}
inline
void bitmap::readImgData(BYTE* pImgData, const DWORD& imgSize) {
fread(pImgData, imgSize, 1, m_rfp);
}
#pragma endregion
#pragma region bmp文件四部分的写入
inline
void bitmap::writeFileHeader(BITMAPFILEHEADER* bmFileHeader) {
fwrite(bmFileHeader, sizeof(BITMAPFILEHEADER), 1, m_wfp);
}
inline
void bitmap::writeInfoHeader(BITMAPINFOHEADER* bmInfoHeader) {
fwrite(bmInfoHeader, sizeof(BITMAPINFOHEADER), 1, m_wfp);
}
inline
void bitmap::writeRgbQuad(RGBQUAD* rgbQuad, const int& rgbQuadSize) {
fwrite(rgbQuad, rgbQuadSize, 1, m_wfp);
}
inline
void bitmap::writeImgData(BYTE* pImgData, const DWORD& imgSize) {
fwrite(pImgData, imgSize, 1, m_wfp);
}
#pragma endregion
#pragma region 构造和析构函数
bitmap::bitmap(const char* readFilePath, const char* writeFilePath) {
m_rfp = fopen(readFilePath, "rb");
m_wfp = fopen(writeFilePath, "wb");
m_pbfHeader = new BITMAPFILEHEADER;
readFileHeader(m_pbfHeader);
if (m_pbfHeader->bfType == 0x4d42) {
m_pbiHeader = new BITMAPINFOHEADER;
readInfoHeader(m_pbiHeader);
if (m_pbiHeader->biBitCount == 24) {
m_imgSize = m_pbiHeader->biSizeImage;
m_pImgData = new BYTE[m_imgSize];
readImgData(m_pImgData, m_imgSize);
fclose(m_rfp);
}
if (m_pbiHeader->biBitCount == 8) {
m_prgbQuad = new RGBQUAD[256];
readRgbQuad(m_prgbQuad, sizeof(RGBQUAD) * 256);
m_imgSize = m_pbiHeader->biSizeImage;
m_pImgData = new BYTE[m_imgSize];
readImgData(m_pImgData, m_imgSize);
fclose(m_rfp);
}
}
}
bitmap::bitmap(const char* readFilePath, const char* writeFilePath0, const char* writeFilePath1, const char* writeFilePath2) {
m_rfp = fopen(readFilePath, "rb");
m_wfp = fopen(writeFilePath0, "wb");
m_wfp1 = fopen(writeFilePath1, "wb");
m_wfp2 = fopen(writeFilePath2, "wb");
m_pbfHeader = new BITMAPFILEHEADER;
readFileHeader(m_pbfHeader);
if (m_pbfHeader->bfType == 0x4d42) {
m_pbiHeader = new BITMAPINFOHEADER;
readInfoHeader(m_pbiHeader);
if (m_pbiHeader->biBitCount == 24) {
m_imgSize = m_pbiHeader->biSizeImage;
m_pImgData = new BYTE[m_imgSize];
readImgData(m_pImgData, m_imgSize);
fclose(m_rfp);
}
}
}
bitmap::~bitmap() {
fclose(m_wfp);
if(m_pbfHeader != nullptr)
delete m_pbfHeader;
if (m_pbiHeader != nullptr)
delete m_pbiHeader;
if (m_prgbQuad != nullptr)
delete m_prgbQuad;
if (m_pImgData != nullptr)
delete m_pImgData;
}
#pragma endregion
#pragma region 创建颜色表
void bitmap::createGrey_8() {
BYTE rgb = 0;
BYTE rgbReserved = 0;
m_prgbQuad = new RGBQUAD[256];
for (int i = 0; i < 256; ++i) {
m_prgbQuad[i].rgbBlue = rgb;
m_prgbQuad[i].rgbGreen = rgb;
m_prgbQuad[i].rgbRED = rgb;
m_prgbQuad[i].rgbReserved = rgbReserved;
++rgb;
}
}
#pragma endregion
#pragma region 处理图片的方法
void bitmap::rgb24_to_grey8() {
DWORD imgSize = m_pbiHeader->biHeight * (m_pbiHeader->biWidth / 4 + 1) * 4;
BYTE* imgData = new BYTE[imgSize]{};
m_pbfHeader->bfOffBits = 54 + 1024;
m_pbfHeader->bfSize = m_pbfHeader->bfOffBits + imgSize;
m_pbiHeader->biBitCount = 8;
m_pbiHeader->biSizeImage = imgSize;
m_pbiHeader->biClrUsed = 256;
createGrey_8();
int tmp;
for (unsigned int i = 0; i < m_imgSize; i += 3) {
tmp = (float)m_pImgData[i] * 0.114f + (float)m_pImgData[i + 1] * 0.587f + (float)m_pImgData[i + 2] * 0.299f;
imgData[i / 3] = BYTE(tmp);
}
writeFileHeader(m_pbfHeader);
writeInfoHeader(m_pbiHeader);
writeRgbQuad(m_prgbQuad, 256 * sizeof(RGBQUAD));
writeImgData(imgData, imgSize);
}
void bitmap::grey8_to_antiGrey8() {
for (unsigned int i = 0; i < m_imgSize; ++i) {
m_pImgData[i] = abs(m_pImgData[i] - 255);
}
writeFileHeader(m_pbfHeader);
writeInfoHeader(m_pbiHeader);
writeRgbQuad(m_prgbQuad, sizeof(RGBQUAD) * 256);
writeImgData(m_pImgData, m_imgSize);
}
void bitmap::rgb24_to_3grey8() {
DWORD imgSize = m_pbiHeader->biHeight * (m_pbiHeader->biWidth / 4 + 1) * 4;
BYTE* imgData0 = new BYTE[imgSize]{};
BYTE* imgData1 = new BYTE[imgSize]{};
BYTE* imgData2 = new BYTE[imgSize]{};
#pragma region 生成第一张图片
m_pbfHeader->bfOffBits = 54 + 1024;
m_pbfHeader->bfSize = m_pbfHeader->bfOffBits + imgSize;
m_pbiHeader->biBitCount = 8;
m_pbiHeader->biSizeImage = imgSize;
m_pbiHeader->biClrUsed = 256;
createGrey_8();
for (unsigned int i = 0; i < m_imgSize; i += 3) {
imgData0[i / 3] = m_pImgData[i];
}
writeFileHeader(m_pbfHeader);
writeInfoHeader(m_pbiHeader);
writeRgbQuad(m_prgbQuad, 256 * sizeof(RGBQUAD));
writeImgData(imgData0, imgSize);
fclose(m_wfp);
m_wfp = m_wfp1;
#pragma endregion
#pragma region 生成第二张图片
for (unsigned int i = 0; i < m_imgSize; i += 3) {
imgData0[i / 3] = m_pImgData[i + 1];
}
writeFileHeader(m_pbfHeader);
writeInfoHeader(m_pbiHeader);
writeRgbQuad(m_prgbQuad, 256 * sizeof(RGBQUAD));
writeImgData(imgData0, imgSize);
fclose(m_wfp);
m_wfp = m_wfp2;
#pragma endregion
#pragma region 生成第三张图片
for (unsigned int i = 0; i < m_imgSize; i += 3) {
imgData0[i / 3] = m_pImgData[i + 2];
}
writeFileHeader(m_pbfHeader);
writeInfoHeader(m_pbiHeader);
writeRgbQuad(m_prgbQuad, 256 * sizeof(RGBQUAD));
writeImgData(imgData0, imgSize);
#pragma endregion
}
#pragma endregion
一个测试读写BMP文件的例子 自己定义了BMP文件的结构体
#pragma pack(push)
#pragma pack(1)
typedef struct tag_bitmap_file_header {
unsigned short file_type;
unsigned long file_size;
unsigned short reserved1;
unsigned short reserved2;
unsigned int offset_bits;
}bitmap_file_header;
typedef struct tag_bitmap_info_header {
unsigned int bitmap_info_size;
int bitmap_width;
int bitmap_height;
unsigned short planes;
unsigned short image_depth;
unsigned int compression;
unsigned int image_size;
int x_pels_permeter;
int y_pels_permeter;
unsigned int color_used;
unsigned int color_important;
}bitmap_info_header;
typedef struct tag_bitmap_palette {
unsigned char blue;
unsigned char green;
unsigned char red;
unsigned char reserved;
}bitmap_palette;
#pragma pack(pop)
实现代码
#pragma region 创建颜色表
RGBQUAD* m_prgbQuad;
void createGrey_8() {
BYTE rgb = 0;
BYTE rgbReserved = 0;
m_prgbQuad = new RGBQUAD[256];
for (int i = 0; i < 256; ++i) {
m_prgbQuad[i].rgbBlue = rgb;
m_prgbQuad[i].rgbGreen = rgb;
m_prgbQuad[i].rgbRed = rgb;
m_prgbQuad[i].rgbReserved = rgbReserved;
++rgb;
}
}
#pragma endregion
void saveToBMP()
{
Mat src = imread("d:\\test.bmp");
bitmap_file_header src_file_head;
bitmap_info_header src_info_head;
bitmap_palette src_palette;
int s1 = sizeof(BITMAPFILEHEADER);
int s2 = sizeof(bitmap_file_header);
int s3 = sizeof(bitmap_palette);
FILE* fsrc = fopen("d:\\test.bmp", "rb");
fread(&src_file_head, 1, sizeof(BITMAPFILEHEADER), fsrc);
fread(&src_info_head, 1, sizeof(BITMAPINFOHEADER), fsrc);
fread(&src_palette, 1, sizeof(RGBQUAD), fsrc);
int src_image_size = src_info_head.image_size;
unsigned char* src_image_buff = new unsigned char[src_image_size];
fread(src_image_buff, 1, src_image_size, fsrc);
fclose(fsrc);
FILE* fw = fopen("d:\\mybmp.bmp", "wb");
if (fw == nullptr)
return;
fwrite(&src_file_head, 1, sizeof(bitmap_file_header), fw);
fwrite(&src_info_head, 1, sizeof(bitmap_info_header), fw);
fwrite(&src_palette, 1, sizeof(bitmap_palette), fw);
fwrite(src_image_buff, 1, src_image_size , fw);
fclose(fw);
auto rows = src.rows;
int colorTablesize = 0;
auto biBitCount = src.depth();
if (src.depth() == 8)
colorTablesize = 1024;
auto depth = src.depth();
auto channels = src.channels();
unsigned char* pData = src.data;
auto elem_size = src.elemSize();
int line_bytes = (src.cols * elem_size / 4 +1) *4 ;
int image_size = line_bytes * src.rows;
bitmap_file_header fileHead;
fileHead.file_type = 0x4D42;
fileHead.reserved1 = 0;
fileHead.reserved2 = 0;
fileHead.offset_bits = 54 + 1024;
fileHead.file_size =fileHead.offset_bits
+ image_size;
FILE* fp = fopen("d:\\mybmp2.bmp", "wb");
if (fp == nullptr)
return;
fwrite(&fileHead,1, sizeof(bitmap_file_header), fp);
bitmap_info_header head;
head.bitmap_info_size = 40;
head.image_depth = 8;
head.color_important = 0;
head.color_used = 256;
head.compression = 0;
head.bitmap_height = src.rows;
head.bitmap_width = src.cols*3;
head.planes = 1;
head.image_size = image_size;
head.x_pels_permeter = 0;
head.y_pels_permeter = 0;
fwrite(&head, 1,sizeof(bitmap_info_header), fp);
if (head.image_depth == 8)
{
createGrey_8();
fwrite(m_prgbQuad, sizeof(RGBQUAD), 256, fp);
}
else {
bitmap_palette palette = src_palette;
palette.blue = 255; palette.green = 255; palette.red = 255; palette.reserved = 255;
fwrite(&palette, 1, sizeof(bitmap_palette), fp);
}
fwrite(src_image_buff, 1, src_image_size, fp);
fclose(fp);
delete[] src_image_buff;
delete[] m_prgbQuad;
}