最近一个Qt(C++)的项目需要用到截屏的功能,就花时间研究了一下如何实现。
Qt 确实是好用,截屏只需要下面三行代码就够了。
1 QDesktopWidget *desk = QApplication::desktop();
2 QScreen * screen = QGuiApplication::primaryScreen();
3 QPixmap p = screen->grabWindow(desk->winId());
这三行代码第一行是获取桌面的窗体对象。
第二行是获得一个 QScreen 对象。
第三行是截取屏幕上窗体对象所在区域的图像。
截取的结果是个QPixmap ,如果需要进一步处理的话,可以转化为 QIamge,一行代码就可以了。
QImage image = p.toImage();
原理就这么简单,但是我将这个代码封装了一下,将截屏功能封装成了一个 Camera。一次截屏操作就相当于相机拍一张照片。这样的好处是我这里有大量的相机图像处理的代码模块。将截屏封装成相机之后,就可以非常便捷的连接我的既有代码了。这种方法在设计模式中成为“适配器模式”。
下面是代码:
class ScreenCamera;
/**
* @brief The ScreenCameraInfo class 查询屏幕相机的信息的类
* 用这个类可以查到当前计算机接了几个显示器,给出每个显示器的名称(deviceName)
*/
class ScreenCameraInfo
{
friend class ScreenCamera;
public:
explicit ScreenCameraInfo(QScreen * screen = nullptr);
ScreenCameraInfo(const ScreenCameraInfo &info);
/**
* @brief description 没有实现,返回空字符串
* @return 返回空字符串。
*/
QString description() const;
/**
* @brief deviceName 给出屏幕的名称,比如 "\\.\DISPLAY1", "VGA1" 一类的名称。
* @return
*/
QString deviceName() const;
bool isNull() const;
bool operator!=(const ScreenCameraInfo &other) const;
ScreenCameraInfo &operator=(const ScreenCameraInfo &other);
bool operator==(const ScreenCameraInfo &other) const;
static QList
availableCameras(); static ScreenCameraInfo defaultCamera();
private:
QScreen* m_screen;
};
/**
* @brief The ScreenCamera class 将截屏功能封装成一个相机,可以像相机一样的操作。
*/
class ScreenCamera : public QThread
{
Q_OBJECT
public:
explicit ScreenCamera(QObject *parent = 0);
explicit ScreenCamera(ScreenCameraInfo &info, QObject *parent = 0);
/**
* @brief openDevice 打开一个特定的截屏相机,当计算机连接了多个显示器时通过这个 info 指定截取某一个屏幕的图像
* @param info
* @return
*/
bool openDevice(const ScreenCameraInfo &info);
/**
* @brief setFrameRate 设置定时截屏的帧率。这里模仿相机的帧率设置。
* @param fps frame per second 每秒的截屏数量。 [0.001 - 50]
*/
void setFrameRate(double fps);
/**
* @brief setRoi 设置感兴趣的区域,利用这个函数我们可以只截取屏幕的一部分区域
* @param x 截屏区域的起始X坐标
* @param y 截屏区域的起始Y坐标
* @param width 截屏区域的宽度,-1 表示完整的屏幕宽度
* @param height 截屏区域的高度,-1 表示完整的屏幕高度
*/
void setRoi(int x, int y, int width, int height);
void run() override;
/**
* @brief capture 获取截屏图像
* @return
*/
QImage capture();
signals:
/**
* @brief imageChanged 定时截取图像时没截取一帧图像就激发一次这个信号
* @param image
*/
void imageChanged(const QImage& image);
public slots:
/**
* @brief start 开始图像采集
*/
void start();
/**
* @brief stop 停止图像采集
*/
void stop();
private:
int m_sleepInterval;
QScreen* m_screen;
int m_x;
int m_y;
int m_width;
int m_height;
};
ScreenCameraInfo::ScreenCameraInfo(const ScreenCameraInfo &info)
:m_screen(nullptr)
{
m_screen = info.m_screen;
}
ScreenCameraInfo::ScreenCameraInfo(QScreen * screen)
:m_screen(nullptr)
{
m_screen = screen;
}
bool ScreenCameraInfo::isNull() const
{
return (m_screen == nullptr);
}
QString ScreenCameraInfo::description() const
{
return "";
}
QString ScreenCameraInfo::deviceName() const
{
if(m_screen == nullptr) return "";
return m_screen->name();
}
ScreenCameraInfo ScreenCameraInfo::defaultCamera()
{
QScreen * w = QGuiApplication::primaryScreen();
return ScreenCameraInfo(w);
}
QList
ScreenCameraInfo::availableCameras() {
QList
list = QGuiApplication::screens(); QList
info; foreach (QScreen * s, list)
{
ScreenCameraInfo i(s);
info.append(i);
}
return info;
}
bool ScreenCameraInfo::operator!=(const ScreenCameraInfo &other) const
{
return (m_screen != other.m_screen);
}
ScreenCameraInfo & ScreenCameraInfo::operator=(const ScreenCameraInfo &other)
{
m_screen = other.m_screen;
return *this;
}
bool ScreenCameraInfo::operator==(const ScreenCameraInfo &other) const
{
return m_screen == other.m_screen;
}
ScreenCamera::ScreenCamera(ScreenCameraInfo &info, QObject *parent) : QThread(parent)
{
m_screen = info.m_screen;
m_sleepInterval = 500;
m_x = 0;
m_y = 0;
m_width = -1;
m_height = -1;
}
ScreenCamera::ScreenCamera(QObject *parent) : QThread(parent)
{
m_screen = nullptr;
m_sleepInterval = 500;
m_x = 0;
m_y = 0;
m_width = -1;
m_height = -1;
}
bool ScreenCamera::openDevice(const ScreenCameraInfo &info)
{
m_screen = info.m_screen;
return (m_screen);
}
void ScreenCamera::setFrameRate(double fps)
{
fps = qBound(0.001, fps, 50.0);
m_sleepInterval = 1000 / fps;
}
void ScreenCamera::setRoi(int x, int y, int width, int height)
{
if(m_screen)
{
QRect rect = m_screen->geometry();
m_x = qBound(0, x, rect.width());
m_y = qBound(0, y, rect.height());
m_width = qBound(-1, width, rect.width());
m_height = qBound(-1, height, rect.height());
}
}
void ScreenCamera::run()
{
while(1)
{
if(m_screen)
{
QDesktopWidget *desk = QApplication::desktop();
//qDebug() << "m_width = " << m_width;
//qDebug() << "m_height = " << m_height;
QPixmap p = m_screen->grabWindow(desk->winId(), m_x, m_y, m_width, m_height);
QImage image = p.toImage();
emit imageChanged(image);
}
msleep(m_sleepInterval);
}
}
QImage ScreenCamera::capture()
{
if(m_screen)
{
QDesktopWidget *desk = QApplication::desktop();
QPixmap p = m_screen->grabWindow(desk->winId(), m_x, m_y, m_width, m_height);
QImage image = p.toImage();
return image;
}
return QImage();
}
void ScreenCamera::stop()
{
terminate();
}
void ScreenCamera::start()
{
QThread::start(QThread::InheritPriority);
}
用法很简答,下面给个代码片段:
ScreenCameraInfo info = ScreenCameraInfo::defaultCamera();
qDebug() << info.deviceName();
m_screenCamera = new ScreenCamera(info);
connect(m_screenCamera, SIGNAL(imageChanged(QImage)), m_cameraImage, SLOT(setImage(QImage)));
m_screenCamera->setRoi(0, 0, 500, 500);
m_screenCamera->start();

推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...