Does anyone knows how to draw an image in Linux, Raspberry Pi, Qt with double framebuffer in same time. I mean i want to run my application on LCD display and draw image to HDMI in same time.
How to draw image in Linux at same time on LCD and HDMI on Raspberry Pi with QT?
Asked Answered
I wrote this code, but I saw a lot of questions on the Internet how to display the image on Linux fraimbuffer. I'll leave it here, maybe someone need help with it. That code was tested on Raspberry Pi 2 model B,B+ and Linux Kernel 4.4.y. with Qt 5.6
File: fbdi.pro
QT += core
QT += gui
QT += widgets
CONFIG += c++11
TARGET = fbdi
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += fbdi.cpp
File: 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;
}
© 2022 - 2024 — McMap. All rights reserved.
QT_QPA_PLATFORM=linuxfb
,QT_QPA_GENERIC_PLUGINS=evdevtouch,evdevmouse,evdevkeyboard
,QT_QPA_EVDEV_KEYBOARD_PARAMETERS=grab=1
in its environment - isn't that the whole point of using a cross-platform library such as Qt? – Delisadelisle