读取24位bmp像素数据(带透明通道)

  一种读取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];//b赋给temp
                lpvBits[width * i + j] = lpvBits[width * i + j + 2];//r赋给b
                lpvBits[width * i + j + 2] = tempBR;//temp赋给r
            }
            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;
}
Licensed under CC BY-NC-SA 4.0
最后更新于 0001-01-01 00:00 UTC
使用 Hugo 构建
主题 StackJimmy 设计