如何使用 QT 在 Raspberry Pi 上的 LCD 和 HDMI 上同时在 Linux 中绘制图像?
Posted
技术标签:
【中文标题】如何使用 QT 在 Raspberry Pi 上的 LCD 和 HDMI 上同时在 Linux 中绘制图像?【英文标题】:How to draw image in Linux at same time on LCD and HDMI on Raspberry Pi with QT? 【发布时间】:2016-06-21 12:54:06 【问题描述】:有谁知道如何在 Linux、Raspberry Pi、Qt 中同时使用双帧缓冲区绘制图像。 我的意思是我想在 LCD 显示器上运行我的应用程序并同时将图像绘制到 HDMI时间。
【问题讨论】:
我认为这种事情的首选格式是提出问题,然后自己回答。您可能需要多解释一下,以便将来的读者清楚。 这不是问题!请将所有答案放入答案中,然后将问题编辑为问题。回答你自己的问题完全没问题! 为什么要添加额外的代码,而不是仅仅在其环境中使用QT_QPA_PLATFORM=linuxfb
、QT_QPA_GENERIC_PLUGINS=evdevtouch,evdevmouse,evdevkeyboard
、QT_QPA_EVDEV_KEYBOARD_PARAMETERS=grab=1
运行您的程序 - 这不是使用跨平台库的全部意义,例如Qt?
因为您不能在 QT 中同时使用双帧缓冲区。尝试使用 /dev/fb1 执行您的程序并将图像设置为 /dev/fb0 - 这就是该代码存在的原因。玩得开心
【参考方案1】:
我写了这段代码,但是在网上看到很多关于如何在Linux fraimbuffer上显示图像的问题。我会把它留在这里,也许有人需要帮助。该代码在 Raspberry Pi 2 型号 B、B+ 和 Linux Kernel 4.4.y 上进行了测试。使用 Qt 5.6
文件:fbdi.pro
QT += core
QT += gui
QT += widgets
CONFIG += c++11
TARGET = fbdi
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += fbdi.cpp
文件:fbdi.cpp
#include <QDebug>
#include <QImage>
#include <QRgb>
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <unistd.h>
#define FB_ERROR_OPEN_FBD 0x0001 // Could not open the framebuffer device
#define FB_ERROR_READ_FSI 0x0002 // Read fixed display information failed
#define FB_ERROR_READ_VSI 0x0004 // Read variable display information failed
#define FB_ERROR_MAPS_MEM 0x0008 // Mapping memory failed
#define FB_ERROR_LOAD_IMG 0x0016 // Load image file failed
#define FB_ERROR_TRAN_IMG 0x0032 // Transformation image file
struct fb_fix_screeninfo;
struct fb_var_screeninfo;
typedef fb_fix_screeninfo finfo;
typedef fb_var_screeninfo vinfo;
struct linuxfb_t
int device; // file handler
uint8_t *data; // data ptr
finfo fix_info; // fixed display information
vinfo var_info; // variable display information
int err_code; // error code
char *err_mesg; // error mesage
long screensize; // calculated screen size
;
///
/// \brief fb_error Set error code and message
/// \param fb Pointer to struct linuxfb_t
/// \param code Error number
/// \param message Error message
/// \return bool Always false
///
bool fb_error(linuxfb_t *fb, int code, QString message)
fb->err_code = code;
fb->err_mesg = message.toLocal8Bit().data();
return false;
///
/// \brief fb_fatal Output message if an error accurred
/// \param fb Pointer to struct linuxfb_t
/// \return int Error code
///
int fb_fatal(linuxfb_t *fb)
qDebug("Error %d: %s", fb->err_code, fb->err_mesg);
return fb->err_code;
///
/// \brief fb_draw Draw specified image on linux framebuffer
/// \param fb Pointer to struct linuxfb_t
/// \param device Path to linux framebuffer device (eg. /dev/fb0)
/// \param filename Path to image file which support by Qt
/// \return bool True if the function success, overwise false
///
bool fb_draw(linuxfb_t *fb, const char *device, const char *filename)
fb->device = open(device, O_RDWR);
if( fb->device < 0 )
return fb_error(fb, FB_ERROR_OPEN_FBD, QString("Unable to open specified device"));
if( ioctl(fb->device, FBIOGET_VSCREENINFO, &fb->var_info) )
return fb_error(fb, FB_ERROR_READ_VSI, QString("Unable to read variable screen information"));
if( ioctl(fb->device, FBIOGET_FSCREENINFO, &fb->fix_info) )
return fb_error(fb, FB_ERROR_READ_FSI, QString("Unable to get fixed screen information"));
fb->screensize = fb->var_info.xres * fb->var_info.yres * (fb->var_info.bits_per_pixel/8);
fb->data = (uint8_t *) mmap(0, fb->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb->device, (off_t) 0);
if( (intptr_t) fb->data == -1 )
return fb_error(fb, FB_ERROR_MAPS_MEM, QString("Failed to map framebuffer device to memory"));
QImage img_orig;
if( !img_orig.load(filename) )
munmap(fb->data, fb->screensize);
close(fb->device);
return fb_error(fb, FB_ERROR_LOAD_IMG, "Could not open the file you specified");
QImage img_trans;
img_trans = img_orig.scaled(fb->var_info.xres, fb->var_info.yres);
if( img_trans.isNull() )
munmap(fb->data, fb->screensize);
close(fb->device);
return fb_error(fb, FB_ERROR_TRAN_IMG, "Could not transform image");
for( uint32_t x=0; x < fb->var_info.xres; x++ )
for( uint32_t y=0; y < fb->var_info.yres; y++ )
long location = (x+fb->var_info.xoffset) * (fb->var_info.bits_per_pixel/8) +
(y+fb->var_info.yoffset) * fb->fix_info.line_length;
QRgb color = img_trans.pixel(x,y);
uint32_t pixel = (qRed(color)<<fb->var_info.red.offset) |
(qGreen(color)<<fb->var_info.green.offset) |
(qBlue(color)<<fb->var_info.blue.offset) ;
*((uint32_t*)(fb->data+location)) = pixel;
munmap(fb->data, fb->screensize);
close(fb->device);
return true;
///
/// \brief main Application entry point
/// \return result
///
int main()
// Create linuxfb variable
linuxfb_t fb;
// Output some image
if( !fb_draw(&fb, "/dev/fb0", "/tmp/test.png") )
// Failed
return fb_fatal(&fb);
// success
return 0;
【讨论】:
以上是关于如何使用 QT 在 Raspberry Pi 上的 LCD 和 HDMI 上同时在 Linux 中绘制图像?的主要内容,如果未能解决你的问题,请参考以下文章
我们如何在Qt工具包(Qt)应用程序中读取已挂载(Raspberry pi)usb中的所有mp3文件
我们如何在 Qt 工具包(Qt)应用程序中读取已安装(Raspberry pi)usb 中的所有 mp3 文件
如何从 Raspberry Pi 上的动作中获取 .mp4 视频?