txt - Cómo dibujar imágenes en Linux al mismo tiempo en LCD y HDMI en Raspberry Pi con QT?
raspberry pi zero os (1)
Escribí este código, pero vi muchas preguntas en Internet sobre cómo mostrar la imagen en Linux fraimbuffer. Lo dejo aquí, quizás alguien necesite ayuda con eso. Ese código fue probado en Raspberry Pi 2 modelo B, B + y Linux Kernel 4.4.y. con Qt 5.6
Archivo: fbdi.pro
QT += core
QT += gui
QT += widgets
CONFIG += c++11
TARGET = fbdi
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += fbdi.cpp
Archivo: 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;
}
¿Alguien sabe cómo dibujar una imagen en Linux, Raspberry Pi, Qt con doble framebuffer al mismo tiempo? Quiero decir que quiero ejecutar mi aplicación en la pantalla LCD y dibujar una imagen en HDMI al mismo tiempo.