复制以下代码,保存为 bmp.h ,作为头文件使用。
#include <iostream>
#include <cstdio>
#define WIDTHBYTES(bits) (((bits)+31)/32*4)//用于使图像宽度所占字节数为4byte的倍数
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD; //win32,win64,lin32改为long(4字节),linux64 long下为8字节
typedef int LONG;
//位图文件头信息结构定义
//其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)
typedef struct tagBITMAPFILEHEADER {
DWORD bfSize; //文件大小
WORD bfReserved1; //保留字,不考虑
WORD bfReserved2; //保留字,同上
DWORD bfOffBits; //实际位图数据的偏移字节数,即前三个部分长度之和
} BITMAPFILEHEADER;
//信息头BITMAPINFOHEADER,也是一个结构,其定义如下:
typedef struct tagBITMAPINFOHEADER{
//public:
DWORD biSize; //指定此结构体的长度,为40
LONG biWidth; //位图宽
LONG biHeight; //位图高
WORD biPlanes; //平面数,为1
WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩
DWORD biSizeImage; //实际位图数据占用的字节数
LONG biXPelsPerMeter; //X方向分辨率
LONG biYPelsPerMeter; //Y方向分辨率
DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数)
DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的
} BITMAPINFOHEADER;
void getW_x(double w_x[4],double x);
void getW_y(double w_y[4], double y);
class BMP
{
private:
BITMAPFILEHEADER bitHead;
BITMAPINFOHEADER bitInfoHead;
int width;
int height;
WORD fileType;
public:
BYTE *pColorData;
BMP();
BMP(int width,int height);
~BMP();
void setBitHead(BITMAPFILEHEADER bitHead);
void setBitInfoHead(BITMAPINFOHEADER bitInfoHead);
void setPColorData(BYTE *pColorData);
BITMAPFILEHEADER getBitHead();
BITMAPINFOHEADER getBitInfoHead();
BYTE * getPColorData();
WORD getBitCount();
void setfileType(WORD fileType);
WORD getfileType();
int rows();
int cols();
};
BMP::BMP()
{
}
BMP::BMP(int width,int height):width(width),height(height) //有参数的构造函数,通过初始化列表赋值
{
this->bitHead.bfSize=width*height*3+54;
this->bitHead.bfReserved1=0; //保留字,不考虑
this->bitHead.bfReserved2=0; //保留字,同上
this->bitHead.bfOffBits=54;
this->fileType=19778;
this->bitInfoHead.biSize=40; //指定此结构体的长度,为40
this->bitInfoHead.biWidth=width; //位图宽
this->bitInfoHead.biHeight=height; //位图高
this->bitInfoHead.biPlanes=1; //平面数,为1
this->bitInfoHead.biBitCount=24; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
this->bitInfoHead.biCompression=0; //压缩方式,可以是0,1,2,其中0表示不压缩
this->bitInfoHead.biSizeImage=width*height*3; //实际位图数据占用的字节数
this->bitInfoHead.biXPelsPerMeter=0; //X方向分辨率
this->bitInfoHead.biYPelsPerMeter=0; //Y方向分辨率
this->bitInfoHead.biClrUsed=0; //使用的颜色数,如果为0,则表示默认值(2^颜色位数)
this->bitInfoHead.biClrImportant=0;
//写位图的数据
int write_width = (((width*24)+31)/32*4);//计算写位图的实际宽度(字节)并确保它为4byte的倍数
this->pColorData = (BYTE *)malloc(write_width*height);//开辟内存空间存储图像处理之后数据
memset(this->pColorData, 0, write_width*height);
}
BMP::~BMP()
{
}
void BMP::setfileType(WORD fileType)
{
this->fileType=fileType;
}
WORD BMP::getfileType()
{
return this->fileType;
}
BITMAPFILEHEADER BMP::getBitHead()
{
return this->bitHead;
}
BITMAPINFOHEADER BMP::getBitInfoHead()
{
return this->bitInfoHead;
}
BYTE * BMP::getPColorData()
{
return this->pColorData;
}
void BMP::setBitHead(BITMAPFILEHEADER bitHead)
{
this->bitHead=bitHead;
}
void BMP::setBitInfoHead(BITMAPINFOHEADER bitInfoHead)
{
this->bitInfoHead=bitInfoHead;
this->width = bitInfoHead.biWidth;
this->height = bitInfoHead.biHeight;
}
void BMP::setPColorData(BYTE *pColorData)
{
this->pColorData=pColorData;
}
int BMP::rows()
{
return this->height;
}
int BMP::cols()
{
return this->width;
}
WORD BMP::getBitCount()
{
return this->bitInfoHead.biBitCount;
}
int imread(const char strFile[50],BMP &bmp)
{
FILE* pfile=fopen(strFile, "rb");//文件打开图像
BITMAPFILEHEADER bitHead;
BITMAPINFOHEADER bitInfoHead;
WORD fileType;
fread(&fileType, 1, sizeof(WORD), pfile);
bmp.setfileType(fileType);
if (fileType != 0x4d42)
{
std::cout<<"file is not .bmp file!"<<std::endl;
return 0;
}
fread(&bitHead, 1, sizeof(tagBITMAPFILEHEADER), pfile);
fread(&bitInfoHead, 1, sizeof(BITMAPINFOHEADER), pfile);
int width = bitInfoHead.biWidth;
int height = bitInfoHead.biHeight;
//分配内存空间把源图存入内存
int l_width = WIDTHBYTES(width*bitInfoHead.biBitCount);//计算位图的实际宽度并确保它为4byte的倍数
BYTE *pColorData = (BYTE *)malloc(height*l_width);//开辟内存空间存储图像数据
memset(pColorData, 0, height*l_width);
long nData = height*l_width; //把位图数据信息读到数组里
fread(pColorData, 1, nData, pfile);//图像处理可通过操作这部分数据加以实现
bmp.setBitHead(bitHead);
bmp.setBitInfoHead(bitInfoHead);
bmp.setPColorData(pColorData);
fclose(pfile);
}
int imwrite(const char strFile[50],BMP &bmp)
{
FILE* wfile=fopen(strFile, "wb");//打开文件为存储修改后图像做准备
WORD fileType=bmp.getfileType();
fwrite(&fileType,1,sizeof(WORD),wfile);
BITMAPFILEHEADER writebitHead=bmp.getBitHead();
BITMAPINFOHEADER writebitInfoHead=bmp.getBitInfoHead();
int mywritewidth = WIDTHBYTES(writebitInfoHead.biWidth*writebitInfoHead.biBitCount);//BMP图像实际位图数据区的宽度为4byte的倍数,在此计算实际数据区宽度
long write_nData = mywritewidth*writebitInfoHead.biHeight;//截取的位图数据区长度定义
fwrite(&writebitHead, 1, sizeof(tagBITMAPFILEHEADER), wfile);//写回位图文件头信息到输出文件
fwrite(&writebitInfoHead, 1, sizeof(BITMAPINFOHEADER), wfile);//写回位图信息头信息到输出文件
BYTE *PColorData=bmp.getPColorData();
fwrite(PColorData, 1, write_nData, wfile); //将处理完图像数据区写回文件
fclose(wfile);
}