首页
社区
课程
招聘
[讨论]BITMAPINFO的赋值方法
2009-3-17 05:40 10139

[讨论]BITMAPINFO的赋值方法

2009-3-17 05:40
10139
BITMAPINFO是API中的一个结构:
typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD          bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;

本身第二个参数就很难理解,如果让咱们定义这样的结构,一般是:
typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD*        bmiColors;
} BITMAPINFO, *PBITMAPINFO;

这样好初始化,好理解,好赋值...

对于API的这个结构,就不好赋值,因为咱们bitmap的结构,有可能是分开得到的,如头信息,调色板,包括数据流,都是分开得到的.如果赋给bmiColors一个RGBQUAD*指针,编译时提示非法,如果赋给他一个数组,也提示非法.所以我通常都是:

char p[sizeof(BITMAPINFOHEADER) + 0x400];
得到bmih和pPal后,再
memcpy(p, &bmih, sizeof(BITMAPINFOHEADER));
memcpy(p + sizeof(BITMAPINFOHEADER), 0x400, pPal);
PBITMAPINFO pbmi = (PBITMAPINFO)p;
这样很麻烦,且影响到了程序的执行效率.

如何做更好呢?如何理解bmiColors[1]呢?如何用普通的赋值方法给这个结构赋值呢?
如:
BITMAPINFO bmi;
bmi.bmiColors = ....;
或:
BITMAPINFO bmi = {xx, yy};

许多大论坛都没有回复的问题。。。。。。。。

[培训]科锐软件逆向50期预科班报名即将截止,速来!!! 50期正式班报名火爆招生中!!!

收藏
免费 0
打赏
分享
最新回复 (7)
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wping 2009-3-17 07:30
2
0
tagBITMAPINFO tbitmap;
RGBQUAD  rgb1;

tbitmap.bmiColors[0]=rgb1;

我没用过这个东东  
不过我这样定义和使用是没有问题的
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wping 2009-3-17 07:31
3
0
看看DELPHI中的定义
它是翻译自WINDOWS.H 的(应该)
tagBITMAPINFO = packed record
    bmiHeader: TBitmapInfoHeader;
    bmiColors: array[0..0] of TRGBQuad;
  end;
可以看出,第2个参数就是一个只有一个元素的数组
雪    币: 216
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
smartbear 2009-3-17 15:00
4
0
调色板不可能只有一两种颜色,但不能赋数组的,为什么呢?我想是,这个结构的数据必须是连续的,这样WINDOWS才能正确引用,而咱们给第二个成员赋数组和指针,相当于和第一个成员的数据不连续了,所以WINDOWS才用了[1]这种怪异的方法来表示这个结构成员。
我用的笨办法,通过了内存指针来转换为这个结构的指针,其内存数据是连续的,所以可以正常工作。

但还有没有其他好的办法呢?
雪    币: 130
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sojoo 2009-3-17 21:21
5
0
// 内存中数据和文件中结构是一致的
// 这个结构体是定义文件格式
typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD          bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;

// 这个定义和 bmp 文件格式定义违背
// 调色板紧跟着 infoheader
// 否则你还需要定义一个结构体描述文件的形态
typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD*        bmiColors;
} BITMAPINFO, *PBITMAPINFO;
雪    币: 130
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sojoo 2009-3-17 21:22
6
0
BITMAPINFO 的大小等于 infoheader的大小+clscount*sizeof(RGBQAD)
雪    币: 216
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
smartbear 2009-3-18 13:40
7
0
照这么说,[1]的意思就是表示这内存连续的意思了,如果把bmiHeader理解为0,他就是1喽...
所以直接赋不容易,除非事先知道了调色板的颜色数,分配好内存,一次性将数据读到这块内存中...
如果头信息和调色板分开获得的话,只能分配好相应大小的内存,分别拷入了...
看来只有我那种方法了...
BITMAPINFOHEADER bmih = ...;
bmih.biClrUsed = bmih.biClrUsed ==0 ? 0xff :  bmih.biClrUsed;
BITMAPINFO bmi = (BITMAPINFO)new BYTE[bmih.biClrUsed * sizeof(RGBQUAD)];
//如果事先知道颜色数,可不用在栈中动态分配,不过要转换指针格式一下
//const int nClrSize = 0xff;
//char p[sizeof(BITMAPINFOHEADER) + nClrSize *sizeof(RGBQUAD)];
//BITMAPINFO* pbmi = (BITMAPINFO*)p;
//分别拷入头信息和调色板
雪    币: 216
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
smartbear 2009-3-18 13:45
8
0
[QUOTE=sojoo;592882]// 内存中数据和文件中结构是一致的
// 这个结构体是定义文件格式
typedef struct tagBITMAPINFO {
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD          bmiColors[1];
} BITMAPINFO, *PBI...[/QUOTE]

自己定义的这个结构是不能用在GDI的函数中的,因为不符合BITMAPINFO那块内存的结构...
如:
HBITMAP hbmTile = ::CreateDIBitmap(hDC, &bmih, CBM_INIT, pBits, pbmi, DIB_RGB_COLORS);
这句虽然可以编译过去,但显示时颜色会错乱的...所以最终结果,你还是要填充WINDOWS的BITMAPINFO结构...
游客
登录 | 注册 方可回帖
返回