BMP文件的读取和保存
来源:互联网 发布:万科金域名城业主论坛 编辑:程序博客网 时间:2024/04/30 07:26
BMP文件介绍
BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,采用位映射存储格式,但是不压缩的特性也带来了读取和保存上的方便。BMP文件的图像深度可选lbit、4bit、8bit、24bit以及32bit。BMP文件存储数据时,图像是以扫描行为单位进行存储。行内像素从左至右扫描,windows平台行扫描从下至上。Windows平台上的图形图像软件都支持BMP文件的读取和保存。
BMP文件结构
数据类型定义
using BYTE = unsigned char; //1Byteusing WORD = unsigned short int; //2Byteusing DWORD = unsigned long int; //4Byteusing LONG = long; //4Byteusing LLONG = long long; //8Byte
BMP文件头结构体
typedef struct tagBITMAPFILEHEADER{ WORD bfType; DWORD bfSize; //位图文件总大小包含填充的空字节 WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits;}BITMAPFILEHEADER;
作者所用是MSVC14.0编译器,内存对齐方式是4字节对齐,所以文件头结构体的实际大小是4+4+2+2+4=16字节而不是2+4+2+2+4=14字节。如果直接向这个结构体填充数据,那么会实际读取16字节的数据,第3第4个字节被读取到内存空间但是却无法访问,实际应用过程把bfType成员从结构体中剔除,单独读取,结构体作为整体进行读取。
BMP文件信息头结构体
typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; //位图宽度,以像素为单位 LONG biHeight; //位图高度,以像素为单位 WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; //位图图像数据的实际大小 LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant;}BITMAPINFOHEADER;
需要注意,图像的扫描行从下至上存储则biHeight成员为正数反之则为负数windows、Linux平台是正数,OS/2平台为负数。ps:博主没见过OS/2机器,查资料得知。
BMP文件调色板结构体
typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved;}RGBQUAD;
当BMP图像颜色深度是1bit、4bit和8bit时,调色板有2^1、2^4和2^8个。1bit像素深度的BMP位图称作二值图像。8bit像素深度的BMP图像通常用作灰度图,256个调色板每个调色板中的Blue,Green,Red颜色分量都相等,依次从0变化到255。当然也可以自定义调色板中颜色分量的数值。
BMP图像数据
BYTE* ImageData = new BYTE[biSizeImage]{0};
图像数据保存到字节数组,数组的大小为biSizeImage。biHeight*biWidth并不一定等于biSizeimage,因为扫描行存储是以4字节整数倍保存,填充的空行用0补齐。
示例函数(c++11)
WORD bfType;BITMAPFILEHEADER bitMapFileHeader;BITMAPINFOHEADER bitMapInfoHeader;RGBQUAD *rgbQuad;BYTE *imageData;//载入一个BMP文件,支持1bit、4bit、8bit、24bit、32bit图像深度void Load(const char* filepath){ std::ifstream imageFile(filepath, std::ios::in | std::ios::binary); if (!imageFile) return ; imageFile.read((char*)&bfType, sizeof(WORD)); if (bfType != 0x4D42) return ; imageFile.read((char*)&bitMapFileHeader, sizeof(BITMAPFILEHEADER)); imageFile.read((char*)&bitMapInfoHeader, sizeof(BITMAPINFOHEADER)); imageData = new BYTE[bitMapInfoHeader.biSizeImage]{ 0 }; if (bitMapInfoHeader.biBitCount == 24 || bitMapInfoHeader.biBitCount == 32) { imageFile.read((char*)imageData, bitMapInfoHeader.biSizeImage); } else if (bitMapInfoHeader.biBitCount == 1 || bitMapInfoHeader.biBitCount == 4 || bitMapInfoHeader.biBitCount == 8) { int rgbQuadNum = (int)std::pow(2,bitMapInfoHeader.biBitCount); rgbQuad = new RGBQUAD[rgbQuadNum]; imageFile.read((char*)this.rgbQuad, sizeof(RGBQUAD)*rgbQuadNum); imageFile.read((char*)imageData, bitMapInfoHeader.biSizeImage); } imageFile.clear(); imageFile.close();}void Save(const char* filepath){ std::ofstream imageSaveFile(filepath, std::ios::out | std::ios::binary); if (!imageSaveFile) { return ; } imageSaveFile.write((char*)&bfType, sizeof(WORD)); imageSaveFile.write((char*)&bitMapFileHeader, sizeof(BITMAPFILEHEADER)); imageSaveFile.write((char*)&bitMapInfoHeader, sizeof(BITMAPINFOHEADER)); if (bitMapInfoHeader.biBitCount == 1 || bitMapInfoHeader.biBitCount == 4 || bitMapInfoHeader.biBitCount == 8) { int rgbQuadNum = (int)std::pow(2,bitMapInfoHeader->biBitCount); imageSaveFile.write((char*)this->rgbQuad, sizeof(RGBQUAD)*rgbQuadNum); } imageSaveFile.write((char*)imageData, bitMapInfoHeader->biSizeImage); imageSaveFile.clear(); imageSaveFile.close();}
0 0
- BMP文件的读取和保存
- 读取bmp文件然后在重新保存为一新的bmp文件
- BMP文件的读取
- 读取bmp文件,缩放后保存
- 文件的读取和保存
- 文件的保存和读取
- 文件的保存和读取
- 保存YUV和保存bmp文件
- 数字图像处理--BMP文件的读入和保存
- 数字图像处理--BMP文件的读入和保存
- BMP图像的读取与保存
- BMP文件读取的程序
- BMP文件读取的程序
- BMP文件的读取显示
- 关于BMP文件的读取
- 保存和读取文件
- 文件保存和读取
- 文件保存和读取
- Apatana Studio 3 导入工程向导
- jQuery 自动触发事件
- web前端 常用meta标签
- 2048游戏JS实战笔记1
- 外观模式
- BMP文件的读取和保存
- Android AsyncTask详解
- html及css复习总结
- 关于打分去掉最高分和最低分的代码
- 两点经纬度求曲面距离
- 报错:table is not mapped……
- Ubuntu 升级后版本号还是显示旧版本号问题解决方法
- HDOJ 1003 Max Sum C++
- 宏定义