荔枝派Zero(全志V3S)驱动开发之RGB LCD屏幕显示jpg图片

简介: 由于从上篇博文 “荔枝派Zero(全志V3S)驱动开发之RGB LCD屏幕显示bmp图片” 中只实现了显示 bmp 图片,实际上我们很常用到的图片多数是 jpg 格式图片,因此我们需要折腾一下,实现 jpg 文件的显示。

前言


由于从上篇博文 “荔枝派Zero(全志V3S)驱动开发之RGB LCD屏幕显示bmp图片” 中只实现了显示 bmp 图片,实际上我们很常用到的图片多数是 jpg 格式图片,因此我们需要折腾一下,实现 jpg 文件的显示。


一、jpeglib 库移植


1、jpeglib 库下载


下载网址:http://www.ijg.org/files

这里我选择最新的一个版本,即 jpegsrc.v9e.tar.gz 这个 jpeglib 库


2、安装 jpeglib 库


源码的安装一般由3个步骤组成:配置(configure)、编译(make)、安装(make install)。

<1>、创建安装目录

在 Linux PC 机上新建一个文件夹,用于存放安装文件,并将 jpegsrc.v9e.tar.gz 拷贝到当前目录下:

mkdir /home/Gnep/licheepi_zero/tools
cd tools/
cp /home/share/jpegsrc.v9e.tar.gz ./
ls

<2>、解压 jpegsrc.v9e.tar.gz 到安装目录

tar -xf jpegsrc.v9e.tar.gz
ls

<3>、配置

进入其目录,执行:

cd jpeg-9e/
./configure --prefix=/home/Gnep/licheepi_zero/tools CC=arm-linux-gnueabihf-gcc --host=arm-linux --enable-shared --enable-static

其中 --prefix 选项是配置安装的路径,如果不配置该选项,安装后可执行文件默认放在 /usr/local/bin,库文件默认放在 /usr/local/lib,配置文件默认放在/usr/local/etc,其它的资源文件放在/usr/local/share,比较凌乱。

用 --prefix 选项的另一个好处是卸载软件或移植软件。当某个安装的软件不再需要时,只须简单的删除该安装目录,就可以把软件卸载得干干净净;移植软件只需拷贝整个目录到另外一个机器即可(相同的操作系统)。

其中 CC 选项是用来选择你想使用的 C 编译器的绝对路径

其中 --host 选项指需要运行的位置,默认为 build,也就是本机编译出来的程序,由本机使用;当本机编译出来的程序要在 arm 板子上运行时,就要设置为 arm-linux

--enable-shared:生成动态链接库

--enable-static:生成静态链接库

<4>、编译

make

<5>、安装

make install

tools 目录下的文件为现在如下:

后面我们需要将 lib 目录下的 libjpeg.so.9 和 libjpeg.so.9.5.0 拷贝到开发板的 /usr/lib 目录中,将 include 目录下的头文件拷贝到我们需要编译的 C 代码的目录下

以上 jpeglib 库移植完成。


二、jpeg 图片解压缩过程和压缩过程


jpeg/jpg 格式图片显示,经过有损压缩的图片文件格式,文件较小,获取颜色数据需要解压


1、jpeg 解压缩过程


打开设备文件和图片文件

int lcd_fd = open(“/dev/fb0”, O_RDWR);

FILE *infile = fopen(argv[1], “r+”);

为jpeg对象分配空间并初始化

jpeg_create_decompress(&cinfo);

指定解压缩数据源

jpeg_stdio_src(&cinfo, infile);

为解压缩设定参数,包括图像大小,颜色空间

cinfo.scale_num = 1; //分子

cinfo.scale_denom = n; //分母

开始解压缩

jpeg_start_decompress(&cinfo);

取出数据(做相关的应用)

jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&buffer, 1);

将每行数据显示到LCD

解压缩完毕

jpeg_finish_decompress(&cinfo);

释放资源

jpeg_destroy_decompress(&cinfo);

munmap(p, lcd_wlcd_hlcd_b);

close(lcd_fd);

fclose(infile);

free(buffer);


2、jpeg 压缩过程


为jpeg对象分配空间并初始化

指定图像输出目标

为压缩设定参数,包括图像大小,颜色空间

开始压缩

写入数据(做相关的应用)

压缩完毕

释放资源


三、编译 C 源码


1、源码展示


imageshow.c

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include "jpeglib.h"
int main(int argc, char const *argv[])
{
  if (argc != 2)
  {
    printf("./可执行文件 <jpeg格式图片文件>\n");
    return -1;
  }
  //打开液晶屏
  int lcd_fd = open("/dev/fb0", O_RDWR);
  if (lcd_fd == -1)
  {
    perror("open");
    return -1;
  }
  //获取液晶屏信息
  struct fb_var_screeninfo vinfo;
  ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo); // 获取可变属性
  int lcd_w = vinfo.xres;
  int lcd_h = vinfo.yres;
  int lcd_b = vinfo.bits_per_pixel/8;
  printf("该液晶屏宽:%d,高:%d, 每个像素点%d个字节\n", lcd_w, lcd_h, lcd_b);
  //进行内存映射
  int *p = mmap(NULL, lcd_w * lcd_h * lcd_b, PROT_WRITE | PROT_READ, MAP_SHARED, lcd_fd, 0);
  if (p == (void *)-1)
  {
    perror("mmap");
    return -2;
  }
    // 刷黑屏幕
    memset(p, 0x00, 800 * 480 * 4); 
  //(1)为jpeg对象分配空间并初始化
  struct jpeg_decompress_struct cinfo;  //解压jpeg的对象结构体
  struct jpeg_error_mgr jerr;       //定义错误结构体
  cinfo.err = jpeg_std_error(&jerr);    //错误处理结构体绑定
  jpeg_create_decompress(&cinfo);     //初始化jpeg的对象结构体
  //(2)指定解压缩数据源
  FILE *infile = fopen(argv[1], "r+");
  if (infile == NULL)
  {
    perror("fopen jpeg");
    return -3;
  }
  jpeg_stdio_src(&cinfo, infile);//指定解压缩数据源
  //(3)获取文件信息
  jpeg_read_header(&cinfo, true);
  //(4)为解压缩设定参数,包括图像大小,颜色空间
  int n = 1;      //缩小倍数
  while(cinfo.image_width/n>lcd_w || cinfo.image_height/n>lcd_h)
  {
    n *= 2;
  }
  //设定的缩小倍数
  cinfo.scale_num = 1;    //分子
  cinfo.scale_denom = n;    //分母
  // cinfo.out_color_space = JCS_GRAYSCALE; //颜色空间
  printf("width1:%d height1:%d\n", cinfo.image_width, cinfo.image_height);//设定之前的宽高
  //(5)开始解压缩
  jpeg_start_decompress(&cinfo);
  printf("width:%d height:%d\n", cinfo.output_width, cinfo.output_height);//设定解压缩之后的宽高
  //(6)取出数据(做相关的应用),安装一行一行去读取的
  //output_components像素点大小
  //申请能够存放一行数据的缓冲区
  int row_size = cinfo.output_width*cinfo.output_components;
  char *buffer = (char *)malloc(row_size);
  //output_scanline当前读取行数
  while(cinfo.output_scanline < cinfo.output_height)
  {
    //按行读取数据
    jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&buffer, 1);
    //将读取到的一行数据进行显示
    int i = 0, j = 0;
    for (;j< cinfo.output_width; i+=3, j++)
    {
      //内存映射的方式
      *(p+(cinfo.output_scanline-1)*lcd_w + j) = buffer[i+0]<<16| buffer[i+1]<<8| buffer[i+2];
    }
  }
  //(7)解压缩完毕
  jpeg_finish_decompress(&cinfo);
  //(8)释放资源
  jpeg_destroy_decompress(&cinfo);
  munmap(p, lcd_w*lcd_h*lcd_b);
  close(lcd_fd);
  fclose(infile);
  free(buffer);
  return 0;
}


2、拷贝需要用到的头文件


C 代码中包含了 jpeglib.h 头文件(#include “jpeglib.h”),因此我们需要拷贝库安装目录下的四个头文件(jconfig.h jerror.h jmorecfg.h jpeglib.h,路径:/home/Gnep/licheepi_zero/tools/include/),到自己应用程序的目录下。

cp /home/Gnep/licheepi_zero/tools/include/* ./


3、编译 C 代码


编译应用程序时,要增加动态库的链接-ljpeg 选项

arm-linux-gnueabihf-gcc imageshow.c -o imageshow -L /home/Gnep/licheepi_zero/tools/lib/ -ljpeg


四、验证测试


1、拷贝相关文件到开发板


①、将 imageshow、libjpeg.so.9、libjpeg.so.9.5.0拷贝到 tftpboot 目录中

cp imageshow /tftpboot/
cp /home/Gnep/licheepi_zero/tools/lib/*.so.* /tftpboot/

②、将 imageshow 、777.jpg、888.jpeg 拷贝到开发板上,将库安装目录下的 lib 目录下的 libjpeg.so.9 和 libjpeg.so.9.5.0 拷贝到开发板的 /usr/lib 目录中

tftp -g -l 777.jpg 192.168.25.25
tftp -g -l 888.jpeg 192.168.25.25
tftp -g -l imageshow 192.168.25.25
tftp -g -l libjpeg.so.9 192.168.25.25
tftp -g -l libjpeg.so.9.5.0 192.168.25.25
cp libjpeg.so.9 /usr/lib
cp libjpeg.so.9.5.0 /usr/lib


2、显示图片


①、雪山照(800 * 480)

./imageshow 777.jpg

②、风景照(480* 272)

./imageshow 888.jpeg


五、资源自取


方式1:github 链接


https://github.com/Gnepuil79/licheepi.git


方式2:百度网盘


链接:https://pan.baidu.com/s/1GWuML5BpRJZ0MneXq9u2Gw

提取码:td2e

目录
相关文章
|
传感器 Shell 数据处理
一起玩转树莓派(11)——使用LCD屏(一)
一起玩转树莓派(11)——使用LCD屏
662 0
一起玩转树莓派(11)——使用LCD屏(一)
|
1月前
|
内存技术
基于Micropython利用ESP32-C3驱动墨水屏显示图片
基于Micropython利用ESP32-C3驱动墨水屏显示图片
48 0
|
7月前
|
传感器 Linux 开发工具
开源项目-十六进制协议传感器自适应缩放曲线显示终端(百问网imx6ull & 小熊派结合)
开源项目-十六进制协议传感器自适应缩放曲线显示终端(百问网imx6ull & 小熊派结合)
59 0
|
9月前
|
存储 编解码 Linux
荔枝派Zero(全志V3S)驱动开发之RGB LCD屏幕显示bmp图片
了解 framebuffer 字符设备 了解 bmp图片格式 通过操作 /dev/fb0 字符设备来实现在 RGB LCD 屏幕上显示 bmp 图片。
261 0
|
9月前
|
Linux
荔枝派Zero(全志V3S)基于QT实现在LCD显示图片
有这样一个需求,通过配置 QT,在 linux 下实现显示我所想要显示的图片,实现的方式是我可以在命令行将图片的路径作为入参传入进去,从而对其进行显示,在之前的文章中已实现了在板子上运行 QT5 程序,此需求要自己写个 QT 程序,且需要对 buildroot 进行裁剪支持一些常用的图片格式即可。
263 2
|
9月前
|
Shell 芯片
荔枝派Zero(全志V3S)驱动开发之RGB LED灯
查看 V3S 原理图,查看 RGB LED对应的引脚 PG0 -> green LED PG1 -> blue LED PG2 -> red LED
296 0
|
9月前
|
Ubuntu Linux Windows
荔枝派Zero(全志V3S)制作 IMG 镜像文件
之前在玩板子时每次烧录镜像都是先烧录 uboot 到 SD 卡 8k 偏移处,再拷贝 zImage 镜像文件和 sun8i-v3s-licheepi-zero-dock.dtb 设备树文件到 sd 卡的 kernel 分区,再把 rootfs.tar 解压到 SD 卡的 rootfs 分区,总的来说感觉有些麻烦,因此本文将制作一个 img 镜像文件可以在 windows 下直接用 Win32DiskImager 一键烧录,或者在 linux 下直接使用 dd 烧录。
191 0
|
传感器 C语言 芯片
东芝开发板驱动OLED模块显示LOGO图片
东芝开发板驱动OLED模块显示LOGO图片
116 0
东芝开发板驱动OLED模块显示LOGO图片
|
数据格式
基于STM32+Qt上位机的RGB调色器,全开源!
基于STM32+Qt上位机的RGB调色器,全开源!
211 0
基于STM32+Qt上位机的RGB调色器,全开源!
|
数据格式
基于uFUN开发板的RGB调色器
基于uFUN开发板的RGB调色器
99 0
基于uFUN开发板的RGB调色器