图解 bmp 文件(BITMAP,windows位图文件)格式
既然是图解,此处省去介绍....直接上图
以下代码中SetPixel()为在屏幕中打点的函数,在单片机中由自己实现,
根据不同的位深来解析,都是根据以上图片方式,推导出来的算法.
并没有实现压缩算法,图像高度为负的情况,并且未优化,图像较大时速度慢
(pmybmp指向bmp文件的数组)
//windows下加入缓冲提高速度
HDC hdc=GetDC(hWnd);//second method
HDC hmdc = CreateCompatibleDC(hdc);
HBITMAP hbmp = CreateCompatibleBitmap(hdc, bminfohdr.biWidth, bminfohdr.biHeight);
SelectObject(hmdc, hbmp);
char *pmybmp = (char*)BMP_WAVE;BITMAPFILEHEADER bmfilehdr;BITMAPINFOHEADER bminfohdr; memcpy(&bmfilehdr, &pmybmp[0], sizeof(BITMAPFILEHEADER));//14memcpy(&bminfohdr, &pmybmp[14], sizeof(BITMAPINFOHEADER));//40printf("\n..............................\n");printf("\nsizeof(BITMAPFILEHEADER)=%d\n", sizeof(BITMAPFILEHEADER));printf("bmfilehdr.bfType=%#02x\n", bmfilehdr.bfType);printf("bmfilehdr.bfSize=%#04x,bmp文件大小:%d字节\n", bmfilehdr.bfSize, bmfilehdr.bfSize);printf("bmfilehdr.bfOffBits=%#04x (到RGBQUAD偏移字节)\n", bmfilehdr.bfOffBits);printf("sizeof(BITMAPINFOHEADER)=%d\n", sizeof(BITMAPINFOHEADER));printf("bminfohdr.biSize=%#04x ( 结构体BITMAPINFOHEADER大小,=sizeof(BITMAPINFOHEADER) )\n", bminfohdr.biSize);printf("bminfohdr.biWidth=%#04x (位图宽:%dpixels)\n", bminfohdr.biWidth, bminfohdr.biWidth);printf("bminfohdr.biHeight=%#04x (位图高:%dpixels)\n", bminfohdr.biHeight, bminfohdr.biHeight);printf("bminfohdr.biPlanes=%#02x (平面数)\n", bminfohdr.biPlanes);printf("bminfohdr.biBitCount=%#02x (%d位深,1:单色,4:16色,8:256色,16:高彩色,24:真彩色,32:增强真彩色)\n", bminfohdr.biBitCount, bminfohdr.biBitCount);printf("bminfohdr.biCompression=%d (压缩算法:0:BI_RGB,1:BI_RLE8,2:BI_RLE4,3:BI_BITFIELEDS,4:BI_JPEG,5:BI_PNG)\n", bminfohdr.biCompression);printf("bminfohdr.biSizeImage=%d (位图缓冲,BI_RGB常为0)\n", bminfohdr.biSizeImage);printf("bminfohdr.biXPelsPerMeter=%d (水平分辨率,pixels/meter)\n", bminfohdr.biXPelsPerMeter);printf("bminfohdr.biYPelsPerMeter=%d (垂直分辨率,pixels/meter)\n", bminfohdr.biYPelsPerMeter);printf("bminfohdr.biClrUsed=%d (位深为1~8时,用于指定调用板用到的颜色数,0表示全部都用到)\n", bminfohdr.biClrUsed);printf("bminfohdr.biClrImportant=%d (0表示所有色彩都重要)\n", bminfohdr.biClrImportant);switch (bminfohdr.biBitCount)//位深,bpp,bit per pixel{//色彩位数case 32://0x20,增强真彩色,RGBA ///bminfohdr.biCompression == BI_RGB ||bminfohdr.biCompression ==BI_BITFIELDS{for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount / 8)*h;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头RGBQUAD *pixelclr = (RGBQUAD*)&pmybmp[idxRGB];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbRed, pixelclr->rgbGreen, pixelclr->rgbBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 24://24bit/pixel,0x18,真彩色,16777216色{long pad0 = (4 - bminfohdr.biBitCount / 8 * bminfohdr.biWidth % 4) % 4;//补0字节数,bitcount 为位数要除以8!!!for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount / 8 + pad0)*h;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头RGBTRIPLE *pixelclr = (RGBTRIPLE*)&pmybmp[idxRGB];// printf("index:%d,RGB(%d,%d,%d)\n", idxRGB, pixelclr->rgbtRed, pixelclr->rgbtGreen, pixelclr->rgbtBlue);SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbtRed, pixelclr->rgbtGreen, pixelclr->rgbtBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 16://0x10,高彩色,65536色,RGB565,RGB444,RGB555switch (bminfohdr.biSize){case 0x28://X1RGB555,最高位空{int pad0 = 32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount + pad0)*h / 8;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头USHORT color = *(USHORT*)&pmybmp[idxRGB];RGBTRIPLE pixelclr;pixelclr.rgbtRed = ((0x7c00 & color) >> 7);//RED:D6D5D4D3D2,即每个分量只有5位,靠MSB位置处放pixelclr.rgbtGreen = ((0x03e0 & color) >> 2);//GREEN:D6D5D4D3D2pixelclr.rgbtBlue = ((0x001f & color) << 3);//BLUE:D6D5D4D3D2SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr.rgbtRed, pixelclr.rgbtGreen, pixelclr.rgbtBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 0x38://根据掩膜来取RGB,X4RGB444,RGB565{if (bminfohdr.biCompression == BI_BITFIELDS){struct CLRMASK{DWORD RedMask, GreenMask, BlueMask, AlphaMask;};int rr = 0, rg = 0, rb = 0;CLRMASK *clr = (CLRMASK*)&pmybmp[icolor_table];//printf("icolor_table:%02X,RGBA_MASK:%04x,%04x,%04x,%04x\n", icolor_table, clr->RedMask, clr->GreenMask, clr->BlueMask, clr->AlphaMask);int pad0 = (32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32) % 32;//cmd.puts("...............,.............\n");if (clr->RedMask == 0xf800 && clr->GreenMask == 0x07e0 && clr->BlueMask == 0x001f) { rr = 8; rg = 3; rb = 3; }else if (clr->RedMask == 0x0f00 && clr->GreenMask == 0x00f0 && clr->BlueMask == 0x000f) { rr = 4; rg = 0; rb = 4; }for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount + pad0)*h / 8;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头USHORT color = *(USHORT*)&pmybmp[idxRGB];RGBTRIPLE pixelclr;pixelclr.rgbtRed = (BYTE)((clr->RedMask & color) >> rr);//RED:D6D5D4D3D2,即每个分量只有5位,靠MSB位置处放pixelclr.rgbtGreen = (BYTE)((clr->GreenMask & color) >> rg);//GREEN:D6D5D4D3D2pixelclr.rgbtBlue = (BYTE)((clr->BlueMask & color) << rb);//BLUE:D6D5D4D3D2SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr.rgbtRed, pixelclr.rgbtGreen, pixelclr.rgbtBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}}break;}break;case 8://8bit/pixel,256色{long pad0 = (4 - bminfohdr.biBitCount * bminfohdr.biWidth / 8 % 4) % 4;//补0字节数//if (pad0 == 4) pad0 = 0;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth + pad0; w++){//位图颜色数据索引unsigned long ibmoffset = w + (bminfohdr.biWidth + pad0) * h;unsigned char iclrtbl = pmybmp[bmfilehdr.bfOffBits + ibmoffset];//由索引到调色板,0XBB,0XGG,0XGG,0XAA //icolor_table指向 调色板 的开头RGBQUAD *pixelclr = (RGBQUAD*)&pmybmp[icolor_table + iclrtbl * 4];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbRed, pixelclr->rgbGreen, pixelclr->rgbBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}// printf("FINISHED\n");}break;case 4: //4bit/pixel,16色位图// bminfohdr.biCompression{int pad0 = (32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32) % 32;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){//索引,4位的索引,即半字节索引unsigned long ibmoffset = bmfilehdr.bfOffBits + w / 2 + (bminfohdr.biBitCount*bminfohdr.biWidth + pad0) / 8 * h;unsigned char iclrtbl = (pmybmp[ibmoffset] >> ((1 - (w & 0x1)) * 4)) & 0x0f;//由索引到调色板,0XBB,0XGG,0XGG,0XAA //icolor_table指向 调色板 的开头RGBQUAD *pixelclr = (RGBQUAD*)&pmybmp[icolor_table + iclrtbl * 4];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbRed, pixelclr->rgbGreen, pixelclr->rgbBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 1://单色,一般为黑白,1=白,0=黑,但其实两是两种可定义的颜色,即双色位图 {int pad0 = (32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32) % 32;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){long idx = (w + h*(bminfohdr.biWidth + pad0)) / 8;unsigned char mask = (1 << (7 - w % 8));unsigned char dat = pmybmp[bmfilehdr.bfOffBits + idx];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, (dat & mask) ? RGB(255, 255, 255) : RGB(0, 0, 0)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;}
//windows下加入缓冲提高速度
BitBlt(hdc,1,1,bminfohdr.biWidth,bminfohdr.biHeight, hmdc, 0, 0, SRCCOPY);
DeleteObject(hbmp);
DeleteDC(hmdc);
ReleaseDC(hWnd,hdc);
补充:在WINDOWS上可以用一条语句代替以上代码,速度非常之快,超乎想象,不知道WINDOWS内部是怎么实现的
SetDIBitsToDevice(hdc, 0, 0, bminfohdr.biWidth, bminfohdr.biHeight, 0, 0, 0, bminfohdr.biHeight, (pmybmp+ bmfilehdr.bfOffBits), (BITMAPINFO*)&pmybmp[14], DIB_RGB_COLORS);
//lpvBits :Pointer to DIB color data stored as an array of bytes.
//BITMAPFILEHEADER.bfOffBits:Specifies the offset, in bytes, from the BITMAPFILEHEADER structure to the bitmap bits
图解 bmp 文件(BITMAP,windows位图文件)格式相关推荐
- Python打包工具Pyintealler打包py文件为windows exe文件过程及踩坑记录+实战例子
Python打包工具Pyintealler打包py文件为windows exe文件过程及踩坑记录+实战例子 目录 Python打包工具Pyintealler打包py文件为windows exe文件过程 ...
- linux头文件与windows头文件,socklen_t在windows和linux平台下的头文件定义
5-udev多路径 udev多路径 查看scsi的唯一标识符 用这个计算机可以识别 重启服务 想要看到下面的,可能重启服务也不行,那就需要重启计算机了 虚拟磁盘 安装这个包multipath 重启服务 ...
- 位图文件(BMP)格式分析
一.文件格式 Bmp文件是非常常用的位图文件,无论是游戏还是其他都被广泛使用.针对bmp文件的处理也有一堆现成的api进行调用,然而文件内部究竟怎样,如何自己来解析这样的文件呢?为了消除无聊,我用了 ...
- 位图文件, JPG格式,PNG格式
位图文件(Bitmap), 扩展名可以是.bmp或者.dib.位图文件是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2.4.8.16.24和32位色彩 ...
- 重温WIN32 API ------ 窗口上绘制位图文件
1 基本思路 做界面仿真时,经常需要在窗口上贴图,随着图片数量的增多,通过资源文件中添加位图的方式会变得越来越不可控.所以本着"资源与程序分离"的原则,还是使用外部位图文件更加清晰 ...
- 使用 Windows 脚本文件 (.wsf)
使用 Windows 脚本文件 (.wsf) Windows 脚本文件 (*.wsf) 是含有可扩展标记语言 (XML) 代码的文本文档.它综合了几个可增强脚本灵活性的功能.由于 Windows 脚本 ...
- [转载]初识Windows 脚本文件(*.wsf)
初识Windows 脚本文件(*.wsf) Windows 脚本文件(*.wsf) 是含有可扩展标记语言 (XML) 代码的文本文档,它综合了几个可增强脚本灵活性的功能.由于 Windows 脚本文件 ...
- widnows命令行常用命令使用 和 windows创建文件,写内容到文件
widnows命令行常用命令使用 和 windows创建文件,写内容到文件 1 查看windows命令行常用命令的使用文档 1.1 查看windows中命令行命令 1.2 windows查看某个指定命 ...
- windows.edb文件过大,导致c盘空间极小问题
解决方案2:删除并重建Windows.edb文件 解决Windows.edb文件巨大的windows 10问题的另一个快速解决方法是删除Windows.edb文件. 步骤1:在任务管理器中终止Sear ...
最新文章
- 逻辑覆盖测试(一)语句覆盖
- java类的运行顺序_Java语言类的基本运行顺序
- python读取excel画散点图-python学习之matplotlib绘制散点图实例
- zabbix server is not running the information displayed may not be current
- vue vue实例中的data与vue组件中的data()
- 拿来即用的 Python 时间范围判断方法
- 【渝粤题库】广东开放大学 建筑工程概预算 形成性考核
- atitit.网络文件访问协议.unc smb nfs ftp http的区别
- GlobalMapper20提取点位的高程信息
- jsp与jspx文件
- 武汉大学计算机网络安全学院,消息︱武汉大学计算机学院(新)与国家网络安全学院正式组建...
- 如何在 iPhone 和 iPad 上将你的照片转换为 PDF?
- 李航统计学习方法笔记——泛化误差上界
- 巧解决阿里云虚拟主机免费版被DDOS攻击问题
- 网卡VXLAN的offload技术介绍
- Xilinx ZynqMP相关
- 学习笔记:python爬虫(第一次写笔记,多多包涵)
- Matlab之选取特定区域的坐标点
- T13735 fateice-string洛谷八连测2
- 听君一席话,胜读十年书