首页 > 系统相关 >lcd4linux实现输出framebuffer图像到LCD

lcd4linux实现输出framebuffer图像到LCD

时间:2024-03-28 18:35:08浏览次数:33  
标签:widget Image LCD bpp fb lcd4linux framebuffer property image

根据文章: Linux下支持AX206 LCD FOR AIDA64 Business ,可以实现输出png图片到AX206 LCD。那么如果我们想输出framebuffer的图像到LCD屏幕呢?如何实现?

根据[email protected]:ukoda/lcd4linux-ax206.git仓库的代码,我们可以看到png图片的渲染是通过widget_image.c中的 static void widget_image_render(const char *Name, WIDGET_IMAGE * Image) 函数实现的。

我们可以通过如下修改,实现输出framebuffer图像到AX206 LCD的效果:

diff --git a/contrib/picoLCD/dpf_480_320.conf b/contrib/picoLCD/dpf_480_320.conf
new file mode 100644
index 0000000..34e6b51
--- /dev/null
+++ b/contrib/picoLCD/dpf_480_320.conf
@@ -0,0 +1,42 @@
+Display dpf {
+    Driver     'DPF'
+    Port       'usb0'
+    Font       '6x8'
+    Foreground 'ffffff'
+    Background '000000'
+    Basecolor  '000000'
+    Orientation 0          # 0 = landscape, 1 = portrait
+                          # 2 = reverse landscape, 3 = reverse portrait
+    Backlight  backlight   # Backlight variable control, 0..7 (0=off, 7=max)
+}
+
+Widget Bgnd {
+    class 'Image'
+    file '/dev/fb1'
+    reload 1
+    update 1000
+    inverted 0
+    visible 1
+       fb_width 480
+       fb_height 320
+       fb_bpp 32
+}
+
+Display 'DPF'
+
+Layout layout_480x320 {
+       Layer 2 {
+               X1.Y1 'Bgnd'
+    }
+}
+
+Layout 'layout_480x320'
+
+Variables {
+    backlight 7
+    tick 500
+    tack 200
+    minute 60000
+}
+
+
diff --git a/widget_image.c b/widget_image.c
index accabfe..2238731 100644
--- a/widget_image.c
+++ b/widget_image.c
@@ -38,6 +38,10 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #ifdef HAVE_GD_GD_H
 #include <gd/gd.h>
@@ -69,6 +73,111 @@
 #include <dmalloc.h>
 #endif
 
+static int obtain_frame_from_framebuffer(unsigned char *frame_buf,
+       char *fb_dev, int width, int height, int bpp)
+{
+       int fb_fd = open(fb_dev, O_RDWR);
+       if (fb_fd < 0) {
+               error("open dev %s failed", fb_dev);
+               return -1;
+       }
+
+       int nread = read(fb_fd, frame_buf, width*height*bpp);
+       if (nread <= 0) {
+               error("read failed from framebuffer:%d", nread);
+               close(fb_fd);
+               return -1;
+       }
+
+       close(fb_fd);
+       return 0;
+}
+
+static gdImagePtr createImageFromRgb32(unsigned char *rgbData, int width, int height)
+{
+       gdImagePtr im;
+       int x, y;
+       int color;
+
+       im = gdImageCreateTrueColor(width, height);
+       if (!im) {
+               error("Could not create image.\n");
+               return NULL;
+       }
+
+       for (y = 0; y < height; y++) {
+               for (x = 0; x < width; x++) {
+                       int index = (y * width + x) * 4;
+
+                       unsigned char b = rgbData[index];
+                       unsigned char g = rgbData[index + 1];
+                       unsigned char r = rgbData[index + 2];
+
+                       color = gdImageColorAllocate(im, r, g, b);
+
+                       gdImageSetPixel(im, x, y, color);
+               }
+       }
+
+       return im;
+}
+
+static gdImagePtr createImageFromRgb24(unsigned char *rgbData, int width, int height)
+{
+       gdImagePtr im;
+       int x, y;
+       int color;
+
+       im = gdImageCreateTrueColor(width, height);
+       if (!im) {
+               error("Could not create image.\n");
+               return NULL;
+       }
+
+       for (y = 0; y < height; y++) {
+               for (x = 0; x < width; x++) {
+                       int index = (y * width + x) * 3;
+
+                       unsigned char r = rgbData[index];
+                       unsigned char g = rgbData[index + 1];
+                       unsigned char b = rgbData[index + 2];
+
+                       color = gdImageColorAllocate(im, r, g, b);
+
+                       gdImageSetPixel(im, x, y, color);
+               }
+       }
+
+       return im;
+}
+
+static int create_image_from_framebuffer(char *dev_fb, WIDGET_IMAGE *Image)
+{
+       int width, height, Bpp;
+       int retval;
+
+       width = P2N(&Image->fb_width);
+       height = P2N(&Image->fb_height);
+       Bpp = P2N(&Image->fb_bpp) / 8;
+       unsigned char img_buf[width*height*Bpp];
+
+       /* we only support rgba and rgb current */
+       if (width <= 0 || height <= 0 || (Bpp != 4 && Bpp != 3))
+               return -1;
+
+       retval = obtain_frame_from_framebuffer(img_buf, dev_fb, width, height, Bpp);
+       if (retval)
+               return -1;
+
+       if (Bpp == 4)
+               Image->gdImage = createImageFromRgb32(img_buf, width, height);
+       else if (Bpp == 3)
+               Image->gdImage = createImageFromRgb24(img_buf, width, height);
+       else
+               return -1;
+
+       return 0;
+}
 
 static void widget_image_render(const char *Name, WIDGET_IMAGE * Image)
 {
@@ -105,13 +214,22 @@ static void widget_image_render(const char *Name, WIDGET_IMAGE * Image)
             return;
         }
 
-        fd = fopen(file, "rb");
-        if (fd == NULL) {
-            error("Warning: Image %s: fopen(%s) failed: %s", Name, file, strerror(errno));
-            return;
-        }
-        Image->gdImage = gdImageCreateFromPng(fd);
-        fclose(fd);
+       char *f_ptr = strstr(file, "/dev/fb");
+       if (f_ptr) {
+               int retval = create_image_from_framebuffer(file, Image);
+               if (retval) {
+                       error("Warning: get frame from %s failed", file);
+                       return;
+               }
+       } else {
+               fd = fopen(file, "rb");
+               if (fd == NULL) {
+                       error("Warning: Image %s: fopen(%s) failed: %s", Name, file, strerror(errno));
+                       return;
+               }
+               Image->gdImage = gdImageCreateFromPng(fd);
+               fclose(fd);
+       }
 
         if (Image->gdImage == NULL) {
             fd = fopen(file, "rb");
@@ -293,6 +411,9 @@ static void widget_image_update(void *Self)
         property_eval(&Image->visible);
         property_eval(&Image->inverted);
         property_eval(&Image->center);
+       property_eval(&Image->fb_width);
+       property_eval(&Image->fb_height);
+       property_eval(&Image->fb_bpp);
 
         /* render image into bitmap */
         widget_image_render(W->name, Image);
@@ -343,6 +464,9 @@ int widget_image_init(WIDGET * Self)
         property_load(section, "visible", "1", &Image->visible);
         property_load(section, "inverted", "0", &Image->inverted);
         property_load(section, "center", "0", &Image->center);
+       property_load(section, "fb_width", "480", &Image->fb_width);
+       property_load(section, "fb_height", "320", &Image->fb_height);
+       property_load(section, "fb_bpp", "32", &Image->fb_bpp);
 
         /* sanity checks */
         if (!property_valid(&Image->file)) {
@@ -389,6 +513,10 @@ int widget_image_quit(WIDGET * Self)
                 property_free(&Image->visible);
                 property_free(&Image->inverted);
                 property_free(&Image->center);
+               property_free(&Image->fb_width);
+               property_free(&Image->fb_height);
+               property_free(&Image->fb_bpp);
+
                 free(Self->data);
                 Self->data = NULL;
             }
diff --git a/widget_image.h b/widget_image.h
index 6ead2b4..4d64a9a 100644
--- a/widget_image.h
+++ b/widget_image.h
@@ -46,6 +46,9 @@ typedef struct WIDGET_IMAGE {
     PROPERTY visible;           /* image visible? */
     PROPERTY inverted;          /* image inverted? */
     PROPERTY center;            /* image centered? */
+    PROPERTY fb_width;         /* size of the framebuffer width */
+    PROPERTY fb_height;                /* size of the framebuffer height */
+    PROPERTY fb_bpp;           /* bits per pixel */
 } WIDGET_IMAGE;
 
 extern WIDGET_CLASS Widget_Image;

如上述修改所示,我们可以通过配置文件dpf_480_320.conf里Bgnd widget的文件名参数 file 来指定要使用哪个framebuffer设备。想要使用fb0就配置file为“/dev/fb0”, 想使用fb1就配置为"/dev/fb1"。这样可以兼容输出png图片到LCD的功能。

配置文件解析:

  1. dpf_480_320.conf里Bgnd widget的fb_width和fb_height分别表示AX206 LCD分辨率的宽和高。
  2. dpf_480_320.conf里Bgnd widget的fb_bpp参数根据你系统内framebuffer的bpp(bits per pixel)来决定。
    • 如果framebuffer的bpp为32(RGBA), 则fb_bpp参数配置为32。如果framebuffer的bpp为24(RGB888),则fb_bpp参数配置为24。

framebuffer的bpp可以使用fbset工具来设置,具体使用方法如下:

fbset -fb /dev/fb1 -g 480 320 480 320 32

上面的命令是设置fb1的bpp为32, width为480,height为320。

我们可以通过dpf_480_320.conf里Bgnd widget的update参数调整LCD刷新的间隔,单位为ms。

上述 obtain_frame_from_framebuffer 函数实现从framebuffer里获取RGB raw数据。

由于GD库没有API直接实现把RGB raw数据生成gdImage的功能,我这里写了两个函数 createImageFromRgb32 和 createImageFromRgb24 来实现。

经过上述对lcd4linux源码的改动,我们已经可以输出framebuffer图像到AX206 LCD了。

 

标签:widget,Image,LCD,bpp,fb,lcd4linux,framebuffer,property,image
From: https://www.cnblogs.com/wanglouxiaozi/p/18102315

相关文章

  • Proteus8.0仿真应用设计(十七)基于FreeRTOS、STM32F103C8、HAL库、DHT11、LCD12864的温
    一、简介:        DHT11是一款湿、温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个NTC测温元件。DHT11与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O口。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。传感器内部......
  • 超抗干扰/高抗噪LCD液晶段码屏显示驱动芯片VK2C22A/B LQFP52/48适用于单相电表,水表,瓦
    VK2C22A/B概述:      VK2C22A/B是一个点阵式存储映射的LCD驱动器,可支持最大176点(44SEGx4COM)的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据,也可通过指令进入省电模式。其高抗干扰,低功耗的特性适用于水电气表以及工控仪表类产品。特点:•  工作电压2.4-5.5V......
  • 基于51单片机的空调【DS18B20,LCD1602,3模式】(仿真)
    设三个按键,不同的按键对应不同的模式第一种模式空调控制温度在27°,窗帘关闭灯光关闭。第二种模式空调控制温度在25°,窗帘打开灯光部分打开。第三种模式空调控制温度在26°,窗帘打开灯光全部打开。#include"lcd1602.h"voiddelay_uint(uinti){ while(i--);}......
  • 基于51单片机的灌溉系统【温湿度,定时,水量,LCD1602】(仿真)
    自动灌溉系统1、系统分为湿度控制模式和定时模式2、湿度控制模式下,当湿度低于下限时启动水泵,高于上限时停止水泵3、定时模式下,当计时时间到达设定值时,启动水泵。水量可设置4、设置湿度上下限、加水水量#include"lcd1602.h"voiddelay_uint(uinti){ while(i--);}......
  • 基于51单片机的教室灯控制【光照,手动自动,LCD1602】(仿真)
    教室光控1、系统分为自动模式和手动模式2、自动模式:根据光照强度调节亮灯的数量3、手动模式:按键控制灯的亮灭4、LCD1602显示系统状态#include"lcd1602.h"voiddelay_uint(uinti){ while(i--);}/*************************************************************......
  • 高抗干扰/抗噪液晶驱动芯片VK2C23A/B 永嘉原厂LCD液晶段码屏驱动芯片适用于导轨电表,早
    VK2C23A/B概述:      VK2C23A/B是一个点阵式存储映射的LCD驱动器,可支持最大224点(56SEGx4COM)或者最大416点(52SEGx8COM)的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据,也可通过指令进入省电模式。其高抗干扰,低功耗的特性适用于水电气表以及工控仪表类产品。特点:•......
  • STM32G431RBT6之LCD03
    导入三个文件lcd.c&&lcd.h&&fonts.h  初始化&&界面显示LCD_Init();LCD_Clear(Black);LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);chartemp[20];LCD_DisplayStringLine(Line1,(u8)"DATA");spri......
  • RGBLCD基本知识
    学习资料来源于网络https://www.bilibili.com/video/BV1yE411h7uQ?p=55&spm_id_from=pageDriver&vd_source=432ba293ecfc949a4174ab91ccc526d6https://doc.embedfire.com/linux/imx6/driver/zh/latest/bare_metal/elcdif.html# 基础概念:LCD:LiquidCrystalDisplay液晶是一......
  • 【永嘉原厂】LCD抗干扰液晶段码屏显示驱动芯片VK2C22A/B 适用于单相电表,水表,瓦斯表,热
    I²C 接口LCD 控制及驱动IC型号:VK2C22A:RAM 映射 44*4封装(LQFP-52) LCD液晶显示驱动VK2C22B:RAM 映射 40*4封装(LQFP-48) LCD液晶显示驱动裸片:DICE(邦定COB)/COG(绑定玻璃用)原厂直销,工程服务,技术支持,价格最具优势!VK2C22A/B概述:      VK2C22A/B是一个点阵......
  • 692、基于51单片机的自行车(调速,LCD1602)
    毕设帮助、开题指导、技术解答(有偿)见文末。目录一、设计功能二、proteus仿真三、原理图四、程序源码五、资料包括一、设计功能自行车调速系统1、使用LCD1602显示当前速度和设置速度2、使用电位器设置当前速度,模拟把手调速3、按键启停系统4、速度控制......