有没有人知道如何在Linux,Raspberry Pi,Qt中同时使用双帧缓冲区绘制图像。我的意思是我想在LCD显示器上运行我的应用程序并将图像绘制到HDMI中时间。
答案 0 :(得分:0)
我编写了这段代码,但我在互联网上看到了很多关于如何在Linux fraimbuffer上显示图像的问题。我会留在这里,也许有人需要帮助。该代码在Raspberry Pi 2模型B,B +和Linux内核4.4.y上进行了测试。用Qt 5.6
QT += core
QT += gui
QT += widgets
CONFIG += c++11
TARGET = fbdi
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += 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;
}