一种读取24位bitmap资源的全部像素数据(加透明通道)的方法。
相关知识
BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
◆ 位图文件头(bmp file header): 提供文件的格式、大小等信息
◆ 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
◆ 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
◆ 位图数据(bitmap data):图像数据区
24位和32位不需要调色板。
提取像素原理
24位,除去位图信息头后的剩余部分就是所需的像素信息。需注意的是,它的像素数据按照BGR排列,且数据从位图左下方开始,从左到右,从下到上存储。并且24位位图是没有透明通道的。
但我需要将其转换为RGB排列,且从上到下读取数据。另外我需要能显示透明色,也就是说,将24位位图转换为32位位图,即读取数据时增加一个透明通道(设置为0则透明)。
代码
以下是我写的实现该功能的粗糙代码。
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
| BYTE* GetImageData(CBitmap* cBitmap) { BITMAP bmp; cBitmap->GetBitmap(&bmp); HBITMAP hbm = (HBITMAP)*cBitmap; HDC hDC = ::GetDC(NULL); LONG width = bmp.bmWidth * 4; LONG height = bmp.bmHeight; BITMAPINFO bi; bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = bmp.bmWidth; bi.bmiHeader.biHeight = bmp.bmHeight; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = width * height; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biImportant = 0; BYTE* lpvBits = new BYTE[width * height]; ::ZeroMemory(lpvBits, width * height); ::GetDC(NULL); ::GetDIBits(hDC, hbm, 0, height, lpvBits, &bi, DIB_RGB_COLORS); BYTE buffer = 0; BYTE* pData=new BYTE[width * height]; int temp = 0; for(int i= height - 1;i >= 0; --i) { for(int j=0;j < width; ++j) { if(j % 4 == 0) { BYTE tempBR = 0; tempBR = lpvBits[width * i + j]; lpvBits[width * i + j] = lpvBits[width * i + j + 2]; lpvBits[width * i + j + 2] = tempBR; } if(j % 4 == 3) { if(lpvBits[width * i + j - 3] == 255 && lpvBits[width * i + j - 2] == 255 && lpvBits[width * i + j - 1] == 255) { lpvBits[width * i + j] == 0; } else { lpvBits[width * i + j] == 255; } } buffer = lpvBits[width * i + j]; memcpy(&pData[temp++], &buffer, 1); } } if(lpvBits != 0) { delete lpvBits; lpvBits = 0; } ::ReleaseDC(NULL, hDC); DeleteObject(cBitmap); return pData; }
|