刚学习了几天DirectDraw,书中作者示例多是8位调色板的全屏程序,而且是读取8位位图,可以很方便的使用SetDisplayMode来改变显示模式,按字节写入像素。而在窗口模式中,现在普遍的32BPP和使用24位位图就没有那么方便了,而且书中没有很完整的示例。
使用窗口模式的DirectDraw主要有以下几个问题:
1.24位位图的像素格式到32位像素格式的转换
2.不能使用Flip,需要使用Blt从离屏表面来复制到主显示表面。
3.确定真正的用户窗口。
4.剪裁。
后3个问题书中给了很好的示例,但是对于第1点,像素操作没有说的太多,作者的意思是不要立刻陷于技术细节。但是在今天我想独立写一个窗口的DD程序时确实遇到像素操作上的问题。
0.本来我是这样想的
24位位图数据区[RR][GG][BB] ……
映射在32位BPP的每个像素时在前面的A位补零即可:[00][RR][GG][BB]
但却出现了颜色怎么都不对的情况。
1.24位位图的数据区是如何存放的
位图的14Bytes+40Bytes+4*nBytes的三个头就不说了。直接用_lread或者ReadFile读入Microsoft相应的结构就OK了。因为颜色不对,所以我用UltraEdit查看了一个我画的全紫色的24位位图,数据区如下:
[FF][00][80] ……
查了一下颜色表,等于是:
[BB][GG][RR]。
可以发现,顺序与RGB正相反。
2.显示表面的像素格式
于是修改程序,在显示表面也反序写入:
[BB][GG][RR][AA] ……
试验成功。
3.用法
使用宏,生成一个DWORD:
_RGB32BIT(0, 128, 0, 255) 等价于 00 80 00 FF。
由于是littleendian,所以这个DWORD在内存的表示顺序是 [FF][00][80][00]。
使用下面的语句就可以在(x,y)上进行相应对24位位图的着色:
4.补充
上面的代码只适用于位图像素宽度为4的倍数的情况,而当位图像素个数不是4的倍数则会在每行补适当的0,所以在计算索引时要有相应的改动,下面的代码实现了将按bmp中倒行排序的buffer转成正常顺序,并且计算了补零,读取一个BITMAP24的示例。