首页 > 作文

QT+OpenCV实现录屏功能

更新时间:2023-04-04 16:30:47 阅读: 评论:0

本文使用qt+opencv来实现对指定窗体画面录制,并保存为avi文件。

(1)获取窗体界面

qscreen类有一个grabwindow函数,可以用来获取窗体的画面,这个函数使用很简单,就是传入窗体句柄和要截取的坐标。但是这个函数有一个缺陷,它是通过截取桌面画面的方式,而不是通过

窗体获取界面,所以当你的窗体被其他窗体遮挡时,就无法截取完整的窗体界面,如果你是要录制整个桌面画面,那用这个函数就可以了,下面的方法调用gdi函数来实现,即使窗体被遮挡时仍然能够获取到完整界面,但是窗体最小化时也一样无法获取。

/**  函数功能:获取窗体指定窗体图像*  参   数:hd:窗体句柄*         pm:保存获取到的图片*        项目合作协议范本 x:截南京警官学院取的起始x坐标,*         y:截取的起始y坐标,*         w:截取的宽度*         h:截取的高度*/bool getgdibitmap(hwnd hd,qpixmap &pm, int x, int y, int w, int h){  if(hd==null)红螺慧缘谷生态景区    return fal;  hdc hdc;  hdc=getdcex(hd,null,dcx_parentclip );  hdc hmemdc;          //内存缓冲设备环境  hbitmap hbmmem,hbmold;    //内存缓冲设备环境中的位图  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));  memt(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);  //创建内存兼容设备环境  //创建内存兼容位图  hbmmem=createcompatiblebitmap(hdc,pinfo_header->biwidth,pinfo_header->biheight);  hbmold=(hbitmap)lectobject(hmemdc,hbmmem);  //将内存设备环境中的内容绘制到物理设备环境  hdc  bitblt(hmemdc,0,0,pinfo_header->biwidth,pinfo_header->biheight,hdc,cx+rc.left,xc+cy+rc.top,captureblt|srccopy);  hbitmap hbitmap=(hbitmap)lectobject(hmemdc,hbmold);  // 获得数据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 fal;  }  bool bret=bitmaptopixmap(hbitmap,pm);  releadc(hd,hdc);  //释放资源  deleteobject(hbmmem);  deleteobject(hbmold);  deletedc(hmemdc);  free(pbitmapinfo);  ::deleteobject(hbitmap);  delete [] pbuffer;  return bret;}  /**  函数功能:将bitmap转为qpixmap*/bool bitmaptopixmap(hbitmap hbitmap, qpixmap &pm){  hdc   hdc;  //设备描述表  int   ibits;  //当前显示分辨率下每个像素所占字节数  word  wbitcount;  //位图中每个像素所占字节数  //定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数  dword      dwpalettesize=0,dwbmbitssize,dwdibsize;  bitmap     bitmap;  //位图属性结构  bitmapfileheader  bmfhdr;  //位图文件头结构  bitmapinfoheader  bi;  //位图信息头结构  lpbitmapinfoheader lpbi;  //指向位图信息头结构  handle  2017年央视元宵晚会   hdib, hpal;  hpalette   holdpal=null;  //定义文件,分配内存句柄,调色板句柄  //计算位图文件每个像素所占字节数  hdc = createdc(l"display",null,null,null);  ibits = getdevicecaps(hdc, bitspixel) * getdevicecaps(hdc, planes);  deletedc(hdc);  if (ibits <= 1)    wbitcount = 1;  el if (ibits <= 4)    wbitcount = 4;  el if (ibits <= 8)    wbitcount = 8;  el if (ibits <= 24)    wbitcount = 24;  el    wbitcount = 24;  //计算调色板大小  if (wbitcount <= 8)    dwpalettesize=(1<<wbitcount)*sizeof(rgbquad);  //设置位图信息头结构  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.biclrud      = 0;  bi.biclrimportant   = 0;  dwbmbitssize = ((bitmap.bmwidth*wbitcount+31)/32)*4*bitmap.bmheight;  //为位图内容分配内存  hdib = globalalloc(ghnd,dwbmbitssize+dwpalettesize+sizeof(bitmapinfoheader));  lpbi = (lpbitmapinfoheader)globallock(hdib);  *lpbi = bi;  // 处理调色板  hpal = getstockobject(default_palette);  if (hpal)  {    hdc = ::getdc(null);    holdpal=lectpalette(hdc,(hpalette)hpal,fal);    realizepalette(hdc);  }  // 获取该调色板下新的像素值  getdibits(hdc,hbitmap,0,(uint)bitmap.bmheight,(lpstr)lpbi+sizeof(bitmapinfoheader)+dwpalettesize, (bitm高情商对话apinfo *)lpbi,dib_rgb_colors);  //恢复调色板  if (holdpal)  {    lectpalette(hdc, holdpal, true);    realizepalette(hdc);    ::releadc(null, hdc);  }  // 设置位图文件头  bmfhdr.bftype = 0x4d42; // "bm"  dwdibsize=sizeof(bitmapfileheader)+sizeof(bitmapinfoheader)+dwpalettesize+dwbmbitssize;  bmfhdr.bfsize = dwdibsize;  bmfhdr.bfrerved1 = 0;  bmfhdr.bfrerved2 = 0;  bmfhdr.bfoffbits = (dword)sizeof(bitmapfileheader)+(dword)sizeof(bitmapinfoheader)+dwpalettesize;  std::vector<uchar>buffer;  uchar *p=(uchar*)&bmfhdr;  // 写入位图文件头  buffer.inrt(buffer.end(),p,p+sizeof(bitmapfileheader));  // 写入位图文件其余内容  p=(uchar*)lpbi;  buffer.inrt(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 =fal;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.relea();}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))  {      //转成qimage格式用于显示     qimage img = mattoimage(frame);     emit frame(img);     qthread::msleep(40);  }  capture.relea();  emit playfinsh();}qimage mattoimage(mat mat){  if(mat.type() == cv_8uc1)  {    qimage image(mat.cols, mat.rows, qimage::format_indexed8);    // t the color table (ud to translate colour indexes to qrgb values)    image.tcolorcount(256);    for(int i = 0; i < 256; i++)    {      image.tcolor(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  el 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();  }  el 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();  }  el  {    qdebug() << "error: mat could not be converted to qimage.";    return qimage();  }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。

本文发布于:2023-04-04 16:30:46,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/6623916c88c2f300600e2d0ed456c826.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:QT+OpenCV实现录屏功能.doc

本文 PDF 下载地址:QT+OpenCV实现录屏功能.pdf

标签:位图   窗体   调色板   函数
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图