在项目中,我们有要录制屏幕的需求,录制屏幕有多种方法,可以基于windows api的BitBlt 、ffmpeg的AVDevice、directx 和QT,本文讲解基于QT5的抓屏。QT相对于其他几种抓屏方式优势是跨平台做的比较好,接口简单,劣势相对于directx抓屏消耗大一些,但directx只能是windows。经过测试directx抓屏速度最快,其他接口速度基本一致。
创新互联长期为上千余家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为襄汾企业提供专业的网站制作、成都网站制作,襄汾网站改版等技术服务。拥有10年丰富建站经验和众多成功案例,为您定制开发。
在我的电脑上qt 1080P屏幕抓屏消耗60~80毫秒,720p消耗30~50,也就是说如果抓屏1080我一秒最多录制10帧。这个性能要算好,不然会造成阻塞。
先获取主屏幕然后抓屏存到QPixmap
//获取主屏幕
QScreen *scr = QGuiApplication::primaryScreen();
//抓屏
QPixmap pix= scr->grabWindow(QApplication::desktop()->winId());
将QPixmap转为可以直接访问rgb数据的QImage
就两行代码非常简单,抓屏后数据存放在pix中,将QPixmap转换为QImage就可以取到rgb数据了。
QImage img= pix.toImage();
uchar *date = img.bits();
QImage格式分析
取到截屏数据后,我们就要进行编码压缩,编码可以使用ffmpeg,需要确定取到的数据格式,可以通过img.format成员获取,我这边获取的是Format_RGB32。另外要注意QT中的图像数据不一定每个像素连续存储,每一行会以4对齐,最简单解决方案,就是要保证你图像的宽度是4的倍数。如果无法保证,可以通过 img.bytesPerLine() 获取每一行的字节数。
如果想要将桌面绘制到QWidget中测试,重载paintEvent函数
void QTScreen::paintEvent(QPaintEvent *event)
{
QScreen *scr = QGuiApplication::primaryScreen();
//抓屏
QPixmap pix= scr->grabWindow(QApplication::desktop()->winId());
QImage img= pix.toImage();
QPainter p;
p.begin(this);
p.drawImage(QPoint(0, 0), qi);
p.end();
}
更多的资料也可以关注我51CTO上的视频课程
夏老师的课堂 http://edu.51cto.com/lecturer/12016059.html
http://edu.51cto.com/course/10359.html