Bmp图像的数据格式及读取
数据格式参考:https://www.cnblogs.com/l2rf/p/5643352.html
一、BMP文件读取
下面代码通过读取一个二值bmp文件,并将数据以01的形式打印到文件中,代码中对分配的内存没有手动释放。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | union MyByte { byte bvalue; struct mytype { byte bit0 : 1; byte bit1 : 1; byte bit2 : 1; byte bit3 : 1; byte bit4 : 1; byte bit5 : 1; byte bit6 : 1; byte bit7 : 1; } type; }; int main( void ) { //BMP文件的数据按照从文件头开始的先后顺序分为四个部分: //BITMAPFILEHEADER,位图文件头(bmp file header): 提供文件的格式、大小等信息 //BITMAPINFOHEADER,位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息 //RGBQUAD,调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表 //位图数据(bitmap data):图像数据区 MyByte my; my.bvalue = 0xF1; my.type.bit1; fstream fs; string path = "tmp.bmp" ; fs.open(path, ios::in | ios::binary); if (!fs.is_open()) { return -1; } BITMAPFILEHEADER bmpFileHeader = { 0 }; //读取header //sizeof(BITMAPFILEHEADER)在当前PC上大小为14,而不是16,如果是16需要注意对齐问题 fs.read(( char *)&bmpFileHeader, sizeof (BITMAPFILEHEADER)); //文件标识符,必须为"BM",小端模式,即0x4d42 才是Windows位图文件 if (bmpFileHeader.bfType != 0x4D42) { return -1; }; BITMAPINFOHEADER bmpInfoHeader = { 0 }; fs.read(( char *)&bmpInfoHeader, sizeof (BITMAPINFOHEADER)); if (bmpInfoHeader.biBitCount == 1) { /*解析二值图像的调色板*/ /*二值图像的调色板只有黑白两种颜色,即这边的pRGB只有两个元素,(0,0,0,0)和(255,255,255,0)*/ /*第四个值保留,一般用于阿尔法通道*/ <br> /*biBitCount 小于等于8的情况下,都存有调色板,数据区对应的存储在调色板中的索引值,超过8时,bmp中不存储调色板信息*/ int size = 1 << bmpInfoHeader.biBitCount; RGBQUAD *pRGB = new RGBQUAD[size]; for ( int i = 0; i < size; ++i) { fs.read(( char *)&pRGB[i], sizeof (RGBQUAD)); } /*计算每行读取的字节数。每行数据4字节对齐,不足4字节的会自动补齐*/ int lineBytes = ((bmpInfoHeader.biWidth * bmpInfoHeader.biBitCount + 31) / 8) / 4 * 4; std::fstream fsout; vector<byte *> v; for ( int j = 0; j < bmpInfoHeader.biHeight ; ++j) { byte *buf = new byte[lineBytes]; memset (buf, 0, lineBytes); fs.read(( char *)buf, lineBytes); v.push_back(buf); } fsout.open( "t1022.txt" , ios::out); //默认bmp位图数据存储是相反的,即上面的图像数据存储在数据末端。 //读取时需要颠倒下。 for ( int j = bmpInfoHeader.biHeight - 1; j >= 0; --j) { byte * buf = v.at(j); for ( int jj = 0; jj < lineBytes; ++jj) { MyByte b; b.bvalue = buf[jj]; //注意字节序,前面的数据存储在高bit位。每比特存储的实质是调色板的索引值,即0表示pRGB[0]的值,这里表示(0,0,0)即黑色 fsout << (unsigned int )b.type.bit7; fsout << (unsigned int )b.type.bit6; fsout << (unsigned int )b.type.bit5; fsout << (unsigned int )b.type.bit4; fsout << (unsigned int )b.type.bit3; fsout << (unsigned int )b.type.bit2; fsout << (unsigned int )b.type.bit1; fsout << (unsigned int )b.type.bit0; } fsout << endl; } fsout.close(); } fs.close(); return 0; } |
截图如下:
原图:
posted on 2019-10-22 00:37 merlinzjl 阅读(4126) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具