欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

QT+OpenCV實現(xiàn)錄屏功能

 更新時間:2022年01月19日 15:15:18   作者:平凡的編程者  
這篇文章主要為大家詳細(xì)介紹了QT+OpenCV實現(xiàn)錄屏功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文使用QT+opencv來實現(xiàn)對指定窗體畫面錄制,并保存為avi文件。

(1)獲取窗體界面

QScreen類有一個grabWindow函數(shù),可以用來獲取窗體的畫面,這個函數(shù)使用很簡單,就是傳入窗體句柄和要截取的坐標(biāo)。但是這個函數(shù)有一個缺陷,它是通過截取桌面畫面的方式,而不是通過

窗體獲取界面,所以當(dāng)你的窗體被其他窗體遮擋時,就無法截取完整的窗體界面,如果你是要錄制整個桌面畫面,那用這個函數(shù)就可以了,下面的方法調(diào)用GDI函數(shù)來實現(xiàn),即使窗體被遮擋時仍然能夠獲取到完整界面,但是窗體最小化時也一樣無法獲取。

/*
* ? ?函數(shù)功能:獲取窗體指定窗體圖像
* ? 參 ? ? ?數(shù):hd:窗體句柄
* ? ? ? ? ? ? ? ? pm:保存獲取到的圖片
* ? ? ? ? ? ? ? ? x:截取的起始x坐標(biāo),
* ? ? ? ? ? ? ? ? y:截取的起始y坐標(biāo),
* ? ? ? ? ? ? ? ? w:截取的寬度
* ? ? ? ? ? ? ? ? h:截取的高度
*/
bool GetGDIBitmap(HWND hd,QPixmap &pm, int x, int y, int w, int h)
{
? ? if(hd==NULL)
? ? ? ? return false;
? ? HDC hDC;
? ? hDC=GetDCEx(hd,NULL,DCX_PARENTCLIP );
? ? HDC hMemDC; ? ? ? ? ? ? ? ? ? ?//內(nèi)存緩沖設(shè)備環(huán)境
? ? HBITMAP hbmMem,hbmOld; ? ? ? ?//內(nèi)存緩沖設(shè)備環(huán)境中的位圖
? ? RECT rc;
? ? rc.left=x;
? ? rc.top=y;
? ? rc.right=x+w;
? ? rc.bottom=y+h;
? ? //判斷邊境值
? ? RECT clientrc;
? ? ::GetClientRect(hd,&clientrc);

? ? int xc =0;
? ? int cx =0;
? ? int cy =0;

? ? if(rc.bottom>clientrc.bottom || rc.bottom<0)
? ? ? ? rc.bottom=clientrc.bottom;

? ? if(rc.right>clientrc.right || rc.right<0)
? ? ? ? rc.right=clientrc.right;

? ? // 24位圖的BITMAPINFO
? ? BITMAPINFO *pBITMAPINFO = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER));
? ? memset(pBITMAPINFO, 0, sizeof(BITMAPINFOHEADER));
? ? BITMAPINFOHEADER *pInfo_Header = (BITMAPINFOHEADER *)pBITMAPINFO;
? ? pInfo_Header->biSize = sizeof(BITMAPINFOHEADER);
? ? pInfo_Header->biWidth = rc.right - rc.left;
? ? pInfo_Header->biHeight = (rc.bottom - rc.top);
? ? pInfo_Header->biPlanes = 1;
? ? pInfo_Header->biBitCount = 24;
? ? pInfo_Header->biCompression = BI_RGB;

? ? hMemDC=CreateCompatibleDC(hDC); ? ?//創(chuàng)建內(nèi)存兼容設(shè)備環(huán)境
? ? //創(chuàng)建內(nèi)存兼容位圖
? ? hbmMem=CreateCompatibleBitmap(hDC,pInfo_Header->biWidth,pInfo_Header->biHeight);

? ? hbmOld=(HBITMAP)SelectObject(hMemDC,hbmMem);
? ? //將內(nèi)存設(shè)備環(huán)境中的內(nèi)容繪制到物理設(shè)備環(huán)境 ? hDC
? ? BitBlt(hMemDC,0,0,pInfo_Header->biWidth,pInfo_Header->biHeight,hDC,cx+rc.left,xc+cy+rc.top,CAPTUREBLT|SRCCOPY);
? ? HBITMAP hBitmap=(HBITMAP)SelectObject(hMemDC,hbmOld);

? ? // 獲得數(shù)據(jù)buf
? ? DWORD bufSize=(pInfo_Header->biWidth * 3 + 3) / 4 * 4 * pInfo_Header->biHeight;
? ? BYTE * pBuffer = new BYTE[bufSize];

? ? int aHeight=pInfo_Header->biHeight;

? ? if(::GetDIBits(hMemDC, hBitmap, 0, aHeight, pBuffer,pBITMAPINFO, DIB_RGB_COLORS) == 0)
? ? {
? ? ? ? return false;
? ? }

? ? bool bret=BitmapToPixmap(hBitmap,pm);


? ? ReleaseDC(hd,hDC);
? ? //釋放資源
? ? DeleteObject(hbmMem);
? ? DeleteObject(hbmOld);
? ? DeleteDC(hMemDC);
? ? free(pBITMAPINFO);
? ? ::DeleteObject(hBitmap);
? ? delete [] pBuffer;
? ? return bret;
} ? ?

/*
* ? ?函數(shù)功能:將bitmap轉(zhuǎn)為QPixmap
*/
bool BitmapToPixmap(HBITMAP hBitmap, QPixmap &pm)
{
? ? HDC ? ? hDC;
? ? //設(shè)備描述表
? ? int ? ? iBits;
? ? //當(dāng)前顯示分辨率下每個像素所占字節(jié)數(shù)
? ? WORD ? ?wBitCount;
? ? //位圖中每個像素所占字節(jié)數(shù)
? ? //定義調(diào)色板大小, 位圖中像素字節(jié)大小 , ?位圖文件大小 , 寫入文件字節(jié)數(shù)
? ? DWORD ? ? ? ? ? dwPaletteSize=0,dwBmBitsSize,dwDIBSize;
? ? BITMAP ? ? ? ? ?Bitmap;
? ? //位圖屬性結(jié)構(gòu)
? ? BITMAPFILEHEADER ? bmfHdr;
? ? //位圖文件頭結(jié)構(gòu)
? ? BITMAPINFOHEADER ? bi;
? ? //位圖信息頭結(jié)構(gòu)
? ? LPBITMAPINFOHEADER lpbi;
? ? //指向位圖信息頭結(jié)構(gòu)
? ? HANDLE ? ? ? ? ?hDib, hPal;
? ? HPALETTE ? ? hOldPal=NULL;
? ? //定義文件,分配內(nèi)存句柄,調(diào)色板句柄

? ? //計算位圖文件每個像素所占字節(jié)數(shù)
? ? hDC = CreateDC(L"DISPLAY",NULL,NULL,NULL);
? ? iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
? ? DeleteDC(hDC);
? ? if (iBits <= 1)
? ? ? ? wBitCount = 1;
? ? else if (iBits <= 4)
? ? ? ? wBitCount = 4;
? ? else if (iBits <= 8)
? ? ? ? wBitCount = 8;
? ? else if (iBits <= 24)
? ? ? ? wBitCount = 24;
? ? else
? ? ? ? wBitCount = 24;
? ? //計算調(diào)色板大小
? ? if (wBitCount <= 8)
? ? ? ? dwPaletteSize=(1<<wBitCount)*sizeof(RGBQUAD);

? ? //設(shè)置位圖信息頭結(jié)構(gòu)
? ? GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
? ? bi.biSize ? ? ? ? ? ?= sizeof(BITMAPINFOHEADER);
? ? bi.biWidth ? ? ? ? ? = Bitmap.bmWidth;
? ? bi.biHeight ? ? ? ? ?= Bitmap.bmHeight;
? ? bi.biPlanes ? ? ? ? ?= 1;
? ? bi.biBitCount ? ? ? ? = wBitCount;
? ? bi.biCompression ? ? ?= BI_RGB;
? ? bi.biSizeImage ? ? ? ? = 0;
? ? bi.biXPelsPerMeter ? ? = 0;
? ? bi.biYPelsPerMeter ? ? = 0;
? ? bi.biClrUsed ? ? ? ? ? = 0;
? ? bi.biClrImportant ? ? ?= 0;

? ? dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
? ? //為位圖內(nèi)容分配內(nèi)存
? ? hDib ?= GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
? ? lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
? ? *lpbi = bi;
? ? // 處理調(diào)色板
? ? hPal = GetStockObject(DEFAULT_PALETTE);
? ? if (hPal)
? ? {
? ? ? ? hDC = ::GetDC(NULL);
? ? ? ? hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);
? ? ? ? RealizePalette(hDC);
? ? }
? ? // 獲取該調(diào)色板下新的像素值
? ? GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS);
? ? //恢復(fù)調(diào)色板
? ? if (hOldPal)
? ? {
? ? ? ? SelectPalette(hDC, hOldPal, TRUE);
? ? ? ? RealizePalette(hDC);
? ? ? ? ::ReleaseDC(NULL, hDC);
? ? }
? ? // 設(shè)置位圖文件頭
? ? bmfHdr.bfType = 0x4D42; ?// "BM"
? ? dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize;
? ? bmfHdr.bfSize = dwDIBSize;
? ? bmfHdr.bfReserved1 = 0;
? ? bmfHdr.bfReserved2 = 0;
? ? bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;

? ? std::vector<uchar>buffer;
? ? uchar *p=(uchar*)&bmfHdr;
? ? // 寫入位圖文件頭
? ? buffer.insert(buffer.end(),p,p+sizeof(BITMAPFILEHEADER));
? ? // 寫入位圖文件其余內(nèi)容
? ? p=(uchar*)lpbi;
? ? buffer.insert(buffer.end(),p,p+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize);
? ? //清除
? ? GlobalUnlock(hDib);
? ? GlobalFree(hDib);
? ? pm=QPixmap::fromImage(QImage::fromData(buffer.data(),buffer.size()));
? ? return true;
}

(2)錄制畫面

bool g_needstop =false;void Record()
{
? ? ?RECT rect;
? ? ?//獲取窗體位置大小
? ? ?GetWindowRect(hd,&rect);
? ? ?cv::Size frameSize;
? ? ?frameSize.width=rect.right-rect.left;
? ? ?frameSize.height=rect.bottom-rect.top; ??
? ? ?cv::VideoWriter VideoWriter;
? ? ?if(!VideoWriter.open("d:\\1.avi",CV_FOURCC('M', 'J', 'P', 'G'),40,frameSize))
? ? ? ? ?return;
? ? while(!g_needstop)
? ? {
? ? ? ? QPixmap pm;
? ? ? ? GetGDIBitmap(hd,pm,0,0,frameSize.width,frameSize.height);
? ? ? ? VideoWriter.write(ImageToMat(pm.toImage()));
? ? } ? ? ? ?VideoWriter.release();?
}

Mat ImageToMat(QImage img,QString imgFormat)
{
? ? if(img.isNull())
? ? ? ? return Mat();
? ? QByteArray ba;
? ? QBuffer buffer(&ba);
? ? buffer.open(QIODevice::WriteOnly);
? ? img.save(&buffer,imgFormat.toLatin1().data());
? ? _InputArray arrSrc(ba.data(), ba.size());
? ? Mat mat = cv::imdecode(arrSrc, CV_LOAD_IMAGE_COLOR);
? ? return mat;
}

(3) 播放視頻

void Play()
{
? ? cv::VideoCapture Capture;
? ? if(!Capture.open("d:\\1.avi"))
? ? ? ? ? return;
? ? Mat frame;
? ? //逐幀讀取畫面
? ? while(Capture.read(frame))
? ? {
? ? ? ? ? ? //轉(zhuǎn)成QImage格式用于顯示
? ? ? ? ? ?QImage img = MatToImage(frame);
? ? ? ? ? ?emit Frame(img);
? ? ? ? ? ?QThread::msleep(40);
? ? }
? ? Capture.release();
? ? emit PlayFinsh();
}

QImage MatToImage(Mat mat)
{
? ? if(mat.type() == CV_8UC1)
? ? {
? ? ? ? QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
? ? ? ? // Set the color table (used to translate colour indexes to qRgb values)
? ? ? ? image.setColorCount(256);
? ? ? ? for(int i = 0; i < 256; i++)
? ? ? ? {
? ? ? ? ? ? image.setColor(i, qRgb(i, i, i));
? ? ? ? }
? ? ? ? // Copy input Mat
? ? ? ? uchar *pSrc = mat.data;
? ? ? ? for(int row = 0; row < mat.rows; row ++)
? ? ? ? {
? ? ? ? ? ? uchar *pDest = image.scanLine(row);
? ? ? ? ? ? memcpy(pDest, pSrc, mat.cols);
? ? ? ? ? ? pSrc += mat.step;
? ? ? ? }
? ? ? ? return image;
? ? }
? ? // 8-bits unsigned, NO. OF CHANNELS = 3
? ? else if(mat.type() == CV_8UC3)
? ? {
? ? ? ? // Copy input Mat
? ? ? ? const uchar *pSrc = (const uchar*)mat.data;
? ? ? ? // Create QImage with same dimensions as input Mat
? ? ? ? QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
? ? ? ? return image.rgbSwapped();
? ? }
? ? else if(mat.type() == CV_8UC4)
? ? {
? ? ? ? qDebug() << "CV_8UC4";
? ? ? ? // Copy input Mat
? ? ? ? const uchar *pSrc = (const uchar*)mat.data;
? ? ? ? // Create QImage with same dimensions as input Mat
? ? ? ? QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
? ? ? ? return image.copy();
? ? }
? ? else
? ? {
? ? ? ? qDebug() << "ERROR: Mat could not be converted to QImage.";
? ? ? ? return QImage();
? ? }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語言實現(xiàn)第一次防死版掃雷游戲

    C語言實現(xiàn)第一次防死版掃雷游戲

    大家好,本篇文章主要講的是C語言實現(xiàn)第一次防死版掃雷游戲,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • C++中的作用域案例詳解

    C++中的作用域案例詳解

    作用域規(guī)定了標(biāo)識符在代碼中的可見性和可訪問性,全局作用域中的標(biāo)識符可以在整個程序中使用,局部作用域中的標(biāo)識符只能在其所在的代碼塊中使用,而命名空間作用域提供了一種組織和封裝代碼的方式,以避免命名沖突,這篇文章主要介紹了C++中的作用域,需要的朋友可以參考下
    2024-02-02
  • C++多重繼承引發(fā)的重復(fù)調(diào)用問題與解決方法

    C++多重繼承引發(fā)的重復(fù)調(diào)用問題與解決方法

    這篇文章主要介紹了C++多重繼承引發(fā)的重復(fù)調(diào)用問題與解決方法,結(jié)合具體實例形式分析了C++多重調(diào)用中的重復(fù)調(diào)用問題及相應(yīng)的解決方法,需要的朋友可以參考下
    2018-05-05
  • 詳解C++中的內(nèi)存同步模式(memory order)

    詳解C++中的內(nèi)存同步模式(memory order)

    這篇文章主要介紹了C++中的內(nèi)存同步模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • C++中的偽隨機(jī)數(shù)

    C++中的偽隨機(jī)數(shù)

    這篇文章主要介紹了C++中的偽隨機(jī)數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C++實現(xiàn)LeetCode(211.添加和查找單詞-數(shù)據(jù)結(jié)構(gòu)設(shè)計)

    C++實現(xiàn)LeetCode(211.添加和查找單詞-數(shù)據(jù)結(jié)構(gòu)設(shè)計)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(211.添加和查找單詞-數(shù)據(jù)結(jié)構(gòu)設(shè)計),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Qt編程實現(xiàn)小時鐘

    Qt編程實現(xiàn)小時鐘

    這篇文章主要為大家詳細(xì)介紹了Qt編程實現(xiàn)小時鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C++如何采用Daemon進(jìn)行后臺程序的部署

    C++如何采用Daemon進(jìn)行后臺程序的部署

    這篇文章主要介紹了C++采用Daemon進(jìn)行后臺程序的部署,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • C++的缺省參數(shù)你了解嘛

    C++的缺省參數(shù)你了解嘛

    這篇文章主要為大家介紹了C++缺省參數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • Qt數(shù)據(jù)庫應(yīng)用之超級自定義委托

    Qt數(shù)據(jù)庫應(yīng)用之超級自定義委托

    Qt中需要用到自定義委托的情形很多,比如提供下拉框選擇,進(jìn)度條展示下載進(jìn)度啥的,默認(rèn)的單元格是沒有這些效果的,需要自己單獨用委托的形式來展示。本文將為大家介紹Qt中如何進(jìn)行超級自定義委托,需要的可以參考一下
    2022-03-03

最新評論