最近接手一個項目,需要UOS系統上實作螢幕和視窗捕獲。
由于QT隻提供了螢幕捕獲功能,沒有提供視窗捕獲,于是就找到了老朋友——OBS(畢竟MacOS的螢幕捕獲也是扒的OBS代碼)。
幸運的是,UOS系統商店自帶OBS,直接省去了編譯環節。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcucDM4ETNwYTN50CM2IDOyAzM5EDNxATMxIDMy0iNwQjM2UjMvwFMxEjMwIzLcZDM0IjN1IzLcd2bsJ2Lc12bj5ycn9Gbi52YuAjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
從上圖可以看出,OBS自帶螢幕捕獲和視窗捕獲,視窗捕獲也可以擷取目前桌面上打開的頁面。
試用了一下,視窗捕獲時最小化視窗,會導緻程式卡死,也就是說最小化時擷取不到圖像。問題不大,能用就行。
看了一下obs源碼,相關代碼在plugins->linux-capture裡。
用到的主要是X11庫。
整理了一下obs和網上的代碼,實作螢幕捕獲+視窗捕獲。
包含頭檔案
調用庫,在xx.pro檔案裡添加
視窗列舉、擷取視窗名稱
将視窗顯示到QListWidget中
擷取整個螢幕圖像并顯示到QListWidget中
可以看出螢幕截圖跟視窗截圖的差別就是擷取Window參數方法不同。使用XGetImage擷取圖像完全相同。
再進一步觀察可以發現,在擷取視窗Window時,先調用 RootWindow 擷取目前螢幕的Window,然後使用 XGetWindowProperty 擷取目前螢幕下的所有視窗。
最終實作效果:
捕獲到了Desktop和QT這兩個程式的視窗圖像,以及整個螢幕的圖像。
但是Desktop為什麼是黑的?
原來XGetImage擷取到的是視窗的可見部分,運作程式時,QT處于最大化,把整個Desktop都擋住了,擷取到的圖像就是全黑的,把QT縮小以後在運作一遍試試。
DDE Dock是dock欄的圖像,被拉伸以後就這麼奇怪。
可以看出Desktop頁面也顯示出來了,并且Dock欄和QT遮擋住的部分是黑色。
程式目标可以說達成一半了。
順便說一個程式運作時出現的崩潰錯誤
Debug發現程式崩潰在XImage轉QImage這裡。傳來的XImage是一個空指針,導緻程式崩潰。
QImage image = QImage((const uchar *)(pImage->data), pImage->width, pImage->height, pImage->bytes_per_line, QImage::Format_RGB32);
崩潰在QT Creator視窗,當時的情況是
當我把QT最大化或者移動到桌面最中間時,程式又能正常運作了。
經過反複試驗得出了一個結論,如果視窗有一部分位于螢幕外,XGetImage就會傳回空指針。
修改一下代碼,隻截屏顯示在桌面的部分,截去在螢幕外的部分
發現還是會崩潰,調試發現attrs.x和attrs.y永遠都是0,并不是視窗的實際坐标。
谷歌一下才知道,要想擷取目前視窗在螢幕上的坐标,需要用 XTranslateCoordinates 轉換一下
x和y就是視窗的實際坐标。
改一下代碼,運作成功
大功告成(一半)。
對比OBS,OBS可以擷取視窗的完整圖像,哪怕視窗有一部分在螢幕外。還需要繼續研究obs代碼。。。
未完待續。