如何在带有QT的Raspberry Pi上的LCD和HDMI上同时在Linux中绘制图像?

时间:2016-06-21 12:54:07

标签: linux qt raspberry-pi framebuffer

有没有人知道如何在Linux,Raspberry Pi,Qt中同时使用双帧缓冲区绘制图像。我的意思是我想在LCD显示器上运行我的应用程序并将图像绘制到HDMI中时间。

1 个答案:

答案 0 :(得分:0)

我编写了这段代码,但我在互联网上看到了很多关于如何在Linux fraimbuffer上显示图像的问题。我会留在这里,也许有人需要帮助。该代码在Raspberry Pi 2模型B,B +和Linux内核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;
}