★★ 关于抓屏的一个技术性问题

Fu7iang 2006-07-07 11:37:47

 本人对 GDI 不熟悉,可目前又急需高效的抓屏方法,用 C + GDI 的就行,
 请不要说写驱动或 DirectShow 之类的,
 BitBlt 这种常规方法的已经实现了,但希望找到一种速度更快的方法,
 据说 GetDIBits、GetObject、GetCurrentObject 之类的某个函数可以直接从
 屏幕 HDC 中取得 BITMAP,不知到该怎么写。。。。。。
 
 大家帮帮忙,高分相赠。谢谢!!!

...全文
833 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复

 被这问题困扰 3 天了,郁闷 ...
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
改成

if(bh.bmiHeader.biBitCount == 16)
nBitClrUsed = 2;
...

可问题依旧... 应该如何解决呢?
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复

 应该怎样解决呢?
蒋晟 2006-07-08
  • 打赏
  • 举报
回复
if(bh.bmiHeader.biBitCount == 16)
nBitClrUsed = 2;

自己在单步调试的时候监视&hScreen之前的几个字节就可以看到
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
void TestRGB( void )
{
HDC hScreen = GetDC(NULL);
HBITMAP hBmp = (HBITMAP) GetCurrentObject (hScreen, OBJ_BITMAP);

BITMAPINFO bh = {0};
bh.bmiHeader.biSize = sizeof(bh.bmiHeader);
GetDIBits(hScreen, hBmp, 0, 0, NULL, &bh, DIB_RGB_COLORS);

int nBitClrUsed = 0;
if (bh.bmiHeader.biBitCount == 24)
nBitClrUsed = 3;
else if(bh.bmiHeader.biBitCount == 16)
nBitClrUsed = 3;
else if(bh.bmiHeader.biBitCount == 32)
nBitClrUsed = 4;

BYTE * bits =new BYTE[ bh.bmiHeader.biWidth * bh.bmiHeader.biHeight * nBitClrUsed ];
GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);

return;
}

这就是那个函数,有什么地方会操作了 stack 呢?
蒋晟 2006-07-08
  • 打赏
  • 举报
回复
执行到 return 会抛出个异常估计是写stack变量时越界,覆盖了返回地址。检查你对局部变量的写入操作。
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复

pomelowu兄,上面的代码可以执行,我把他放在一个函数里
 
void TestRGB( void )
{
HDC hDC = GetDC( NULL );
..........
.......... // 获取 bits 的代码,除了颜色位那里,其它未作任何修改
..........
GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);
// 监视此处 GetDIBits() 返回的扫描行是 768,正常!

return; // 执行到 return 会抛出个异常,
// 内存错误之类的,用 Debug 捕获不到
}

测试环境如下:
XP Sp2,
VS.Net 2005,
Win32 Console Project [C++]
颜色: 16, 32 位模式分别测试


==============================================================================

另外 bh.bmiHeader.biBitCount 如果为 16 和 32,nBitClrUsed 应该是几呢?
初学 GDI,见笑了...
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
多谢羽兄
我对 DirectX 更陌生,暂时没空研究了。

请问 GetDIBits 比 BitBlt 能快多少呢?
(我的目标不是完整的BMP,只要能得到 "RGB位图数组" 就可以了:)

另外在 http://www.shenming.net/shen/oblog/user1/shenming/archives/2006/50.html
中提到 DIBSection 要更快些,要从 Screen 获取 DIBSection 应该按怎样的顺序调用呢?

我想从 BitBlt、GetDIBits、DIBsection 中选择一个最快的方法就可以了
pomelowu 2006-07-08
  • 打赏
  • 举报
回复
再精确下去,你其实就不要在GDI上下功夫了,提高效率也有限。。。还是DShow来得快些。。
pomelowu 2006-07-08
  • 打赏
  • 举报
回复
HDC hScreen = GetDC(NULL); // 取得屏幕 DC
HBITMAP hBmp = (HBITMAP) GetCurrentObject (hScreen, OBJ_BITMAP);
// 取得屏幕DC装载的位图句柄

BITMAPINFO bh = {0};
bh.bmiHeader.biSize = sizeof(bh.bmiHeader);
GetDIBits(hScreen, hBmp, 0, 0, NULL, &bh, DIB_RGB_COLORS); // 查询BITMAPINFO

int nBitClrUsed = 0;
if (bh.bmiHeader.biBitCount == 24)
nBitClrUsed = 3; // 每个像素占用的字节数,以24位为例,其余色深自己判断
BYTE * bits =new BYTE[bh.bmiHeader.biWidth * bh.bmiHeader.biHeight * nBitClrUsed];
GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);
// 获得整张位图的数据,保存到bits指向的空间

然后就可以按图像的坐标在bits中查找你要的像素的RGB信息了。


BitBlt 是复制位图,GetDIBits 是取位图的位图数组。
此外,有一个结论是,BitBlt将图像从屏幕拷到内存DC较慢,而用BitBlt将图像从内存DC拷到屏幕则相对快一些。
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
自己顶一下
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
改用 CreateDIBSection、DIBSection 速度会有提高么?
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
HDC hScreen = GetDC(NULL); // 取得屏幕 DC

能不能直接从这个 DC 中察看 BITMAP 中某些点的 RGB 数据? (不用 GetPixel)

另外,谁知道 BitBlt 和 GetDIBits 的区别和效率有什么不同呢?
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
多谢 QuickGo兄

BitBlt 这种传统方法已经做过了,效率不太理想,有更快的方法么?

fu7iang@qq.com
QQ: 75553995
QuickGo 2006-07-08
  • 打赏
  • 举报
回复
需要截获显示器的显示内容,首先创建显示器的设备内容句柄,也就是在GetDC的时候传入一个NULL,而不是某个窗口的句柄,传入NULL可以获得整个当前屏幕的设备内容句柄。然后再准备一个内存位图和一个内存DC,把内存位图选入内存Dc,并且用Bitblt把整个屏幕的位图画到内存位图上,从而完成截图的过程。如果你需要一个简单的示例,可以发邮件给我。QuickGo@Gmail.com
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
蒋大哥,这片文章我很早就拜读过了,谢谢你给我的启发!
但里面只有概念,没有实例,
希望能有个实实在在的快速抓屏函数,以解燃眉之急。。。。。
蒋晟 2006-07-08
  • 打赏
  • 举报
回复
blog.joycode.com/jiangsheng/ archive/2004/01/01/10410.aspx
Fu7iang 2006-07-07
  • 打赏
  • 举报
回复
http://community.csdn.net/Expert/topic/4867/4867627.xml?temp=.3163721
http://community.csdn.net/Expert/topic/4867/4867625.xml?temp=.266659
http://community.csdn.net/Expert/topic/4867/4867626.xml?temp=.2284204

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧