一、QT实现截屏为QImage;
这个相对来说网上资料比较多!
#include <QGuiApplication>
#include <QPixmap>
#include <QScreen>
#include<QImage>
int main(int argc, char *argv[])
{
QScreen *screen= QGuiApplication::primaryScreen(); //获取屏幕接口
QPixmap disktop_img= screen>grabWindow(0).scaled(
1024,768,Qt::IgnoreAspectRatio,Qt::SmoothTransformation
); //调整图像大小为1024×768
QImage disktop=disktop_img.toImage(); //转换为QImage
//RGBA 32位转换为RGB 24位
QImage disktop= disktop.convertToFormat(QImage::Format_RGB888);
}
二、实现QImage转YUV:4:2:0
RGBA 是用32位bit来描述一个像素点的,比如宽1024 高768的QImage 实际大小为1024×768×32
一个像素点:8位R、8位的G、8位的B、8位的透明A来组成。
RGB是用24位bit来表示一个像素点的,比如宽1024高768的QImage实际大小为1024×768×24
一个像素点:8位的R、8位的G、8位的B组成。
yuv是由灰度数据+U+V
Y的大小为:图片的宽度×图片的高度;
U的大小为:图片的宽度×图片的高度/4;
V的大小为:图片的宽度×图片的高度/4;
也就是说你拿到一个YUV图像你要知道图像的宽度,高度,4:2:0因为YUV图像文件并不携带宽度,高度信息。也只有得到宽度高度才能在文件中切分出Y,U,V的值;
我们需要用下图来理解YUV 4:2:0
这是一张宽13像素×13像素的RGB24位的原图。
1、Y:遍历每个像素(uint_8[3])计算出Y的数据列表;
2、U:每隔一行并且为奇数时计算一个U值存到U的列表中;
3、V:每隔一行并且为奇数时计算一个U值存到V的列表中;
Y的算法:0.299R+0.587G+0.114B;
U的算法:-0.169R-0.331G+0.5B+128;
V的算法:0.5R-0.419G-0.081*G+128
#include<QByteArray>
#include<QList>
#include <QGuiApplication>
#include <QPixmap>
#include <QScreen>
#include<QImage>
QList<QByteArray> returnyuv(){
//屏幕
QScreen *screen= QGuiApplication::primaryScreen();
//截屏
QPixmap disktop_img= screen->grabWindow(0).scaled(1024,768,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
QImage disktop=disktop_img.toImage();
//rgba转为rgb,也就是上面提到的rgb24;
disktop= disktop.convertToFormat(QImage::Format_RGB888);
//rgb 转 yuv 4:2:0
QByteArray y_l,u_l,v_l,yuv; //Y ,U,V
uchar * d=disktop.bits(); //截屏QImage的数据
//循环变量
int i,j;
int width=disktop.width(); //截屏QImage宽
int height=disktop.height(); //截屏QImage高
uint8_t r,g,b,y,u,v;
for(i=0;i<height;i++){ //遍历截屏QImage的所有行.
for(j=0;j<width;j++){ //遍历当前行的所有像素.
int pos=i*(width*3)+j*3; //行号*行宽=已遍历行的数据+这一行的第几个像素,3表示:一个像素占3个bit
//一个像素的数据格式:[B,G,R]
r=d[pos+2]; //取出当前像素的R
g=d[pos+1]; //取出当前像素的G
b=d[pos]; //取出当前像素的B
y=0.299*r+0.587*g+0.114*b; //根据公式求出Y的值
y_l.append(y); //把值压入Y的Bytearray;
if(i%2==0 and j%2==0){ // 偶数行并且偶数像素(4个像素取1个像素计算出UV)
u=-0.169*r-0.331*g+0.5*b+128; //计算出U值
u_l.append(u); //把U值压入U的Bytearray
v=0.5*r-0.419*g-0.081*b+128; //计算出V值
v_l.append(v); //把V值压入V的Bytearray
}
}
}
QList<QByteArray> yuv_byte; //[Y[Qbytearray],U[Qbytearray],V[Qbytearray]]
yuv_byte.append(y_l);
yuv_byte.append(v_l);
yuv_byte.append(u_l);
return yuv_byte; //返回yuv
}
//验证转换是否成功
int main(){
QFile write_file_yuv("./tmp.yuv");
write_file_yuv.open(QIODevice::WriteOnly);
if (write_file_yuv.isOpen()){
QByteArray tmp_file;
QList<QByteArray> yuv_byte= returnyuv(); //调用截屏返回[y,u,v]
for(int i=0;i<yuv_byte.length();i++){
tmp_file.append(yuv_byte[i]);
}
write_file_yuv.write(tmp_file); //本地文件存储
write_file_yuv.flush();
write_file_yuv.close();
}
}
yuview 播放器