嵌入式Linux系统下的 QT 截图程序
·
QT程序方式
程序可以截取整个屏幕
环境配置
Linux终端运行QT程序,环境变量配置
export QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER=1
# 嵌入式FrameBuffer模式
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
# 或使用EGLFS(需要GPU支持)
export QT_QPA_PLATFORM=eglfs
QT程序源码
#include <QCoreApplication>
#include <QGuiApplication>
#include <QScreen>
#include <qdatetime.h>
#include <QPixmap>
#include <QDebug>
#include <QCoreApplication>
#include <QApplication>
int main(int argc, char *argv[])
{
qDebug()<<"------------start-------------";
QGuiApplication app(argc, argv);
// 获取主屏幕对象
QScreen *primaryScreen = QGuiApplication::primaryScreen();
if (!primaryScreen) {
qDebug()<<"------------no primaryScreen-------------";
return -1;
}
qDebug()<<"------------截取整个屏幕(root window)-------------";
QPixmap screenshot = primaryScreen->grabWindow(0);
qDebug()<<"------------生成带时间戳的文件名-------------";
QString filename = QDateTime::currentDateTime()
.toString("'screenshot_'yyyyMMdd-hhmmss'.png'");
qDebug()<<"filename ="<<filename;
// 保存为PNG格式
screenshot.save(filename, "PNG");
return app.exec();
}
效果

Linux系统下的程序方式
读取Linux帧缓冲区并将其保存为PNG文件的程序。
git仓库地址https://github.com/AndrewFromMelbourne/fb2png
源代码
//-------------------------------------------------------------------------
//
// The MIT License (MIT)
//
// Copyright (c) 2013 Andrew Duncan
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-------------------------------------------------------------------------
#include <errno.h>
#include <fcntl.h>
#include <png.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
char *program = argv[0];
char *fbdevice = "/dev/fb0";
char *pngname = "fb.png";
int opt = 0;
//--------------------------------------------------------------------
while ((opt = getopt(argc, argv, "d:p:")) != -1)
{
switch (opt)
{
case 'd':
fbdevice = optarg;
break;
case 'p':
pngname = optarg;
break;
default:
fprintf(stderr,
"Usage: %s [-d device] [-p pngname]\n",
program);
exit(EXIT_FAILURE);
break;
}
}
//--------------------------------------------------------------------
int fbfd = open(fbdevice, O_RDWR);
if (fbfd == -1)
{
fprintf(stderr,
"%s: cannot open framebuffer - %s",
program,
strerror(errno));
exit(EXIT_FAILURE);
}
struct fb_fix_screeninfo finfo;
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1)
{
fprintf(stderr,
"%s: reading framebuffer fixed information - %s",
program,
strerror(errno));
exit(EXIT_FAILURE);
}
struct fb_var_screeninfo vinfo;
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1)
{
fprintf(stderr,
"%s: reading framebuffer variable information - %s",
program,
strerror(errno));
exit(EXIT_FAILURE);
}
if ((vinfo.bits_per_pixel != 16) &&
(vinfo.bits_per_pixel != 24) &&
(vinfo.bits_per_pixel != 32))
{
fprintf(stderr, "%s: only 16, 24 and 32 ", program);
fprintf(stderr, "bits per pixels supported\n");
exit(EXIT_FAILURE);
}
void *memp = mmap(0,
finfo.smem_len,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fbfd,
0);
close(fbfd);
fbfd = -1;
if (memp == MAP_FAILED)
{
fprintf(stderr,
"%s: failed to map framebuffer device to memory - %s",
program,
strerror(errno));
exit(EXIT_FAILURE);
}
uint8_t *fbp = memp;
memp = NULL;
//--------------------------------------------------------------------
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
if (png_ptr == NULL)
{
fprintf(stderr,
"%s: could not allocate PNG write struct\n",
program);
exit(EXIT_FAILURE);
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
fprintf(stderr,
"%s: could not allocate PNG info struct\n",
program);
exit(EXIT_FAILURE);
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_write_struct(&png_ptr, &info_ptr);
fprintf(stderr, "%s: error creating PNG\n", program);
exit(EXIT_FAILURE);
}
FILE *pngfp = fopen(pngname, "wb");
if (pngfp == NULL)
{
fprintf(stderr, "%s: Unable to create %s\n", program, pngname);
exit(EXIT_FAILURE);
}
png_init_io(png_ptr, pngfp);
png_set_IHDR(
png_ptr,
info_ptr,
vinfo.xres,
vinfo.yres,
8,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
png_bytep png_buffer = malloc(vinfo.xres * 3 * sizeof(png_byte));
if (png_buffer == NULL)
{
fprintf(stderr, "%s: Unable to allocate buffer\n", program);
exit(EXIT_FAILURE);
}
//--------------------------------------------------------------------
int r_mask = (1 << vinfo.red.length) - 1;
int g_mask = (1 << vinfo.green.length) - 1;
int b_mask = (1 << vinfo.blue.length) - 1;
int bytes_per_pixel = vinfo.bits_per_pixel / 8;
int y = 0;
for (y = 0; y < vinfo.yres; y++)
{
int x;
for (x = 0; x < vinfo.xres; x++)
{
int pb_offset = 3 * x;
size_t fb_offset = (vinfo.xoffset + x) * (bytes_per_pixel)
+ (vinfo.yoffset + y) * finfo.line_length;
uint32_t pixel = 0;
switch (vinfo.bits_per_pixel)
{
case 16:
pixel = *((uint16_t *)(fbp + fb_offset));
break;
case 24:
pixel += *(fbp + fb_offset);
pixel += *(fbp + fb_offset + 1) << 8;
pixel += *(fbp + fb_offset + 2) << 16;
break;
case 32:
pixel = *((uint32_t *)(fbp + fb_offset));
break;
default:
// nothing to do
break;
}
png_byte r = (pixel >> vinfo.red.offset) & r_mask;
png_byte g = (pixel >> vinfo.green.offset) & g_mask;
png_byte b = (pixel >> vinfo.blue.offset) & b_mask;
png_buffer[pb_offset] = (r * 0xFF) / r_mask;
png_buffer[pb_offset + 1] = (g * 0xFF) / g_mask;
png_buffer[pb_offset + 2] = (b * 0xFF) / b_mask;
}
png_write_row(png_ptr, png_buffer);
}
//--------------------------------------------------------------------
free(png_buffer);
png_buffer = NULL;
png_write_end(png_ptr, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(pngfp);
//--------------------------------------------------------------------
munmap(fbp, finfo.smem_len);
//--------------------------------------------------------------------
return 0;
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)