Linux下的lcd屏幕显示操作

发布于:2025-07-24 ⋅ 阅读:(19) ⋅ 点赞:(0)

1.lcd屏幕显示的基本原理

  • 像素:
    屏幕上显示颜色的最小单位,英文叫 pixel。注意,位图(如jpg、bmp等格式的常见图片)也是由一个个的像素点构成的,跟屏幕的像素点的概念一样。原理上讲,将一张位图显示到屏幕上,就是将图片上的像素点一个个复制到屏幕像素点上。

  • 分辨率:
    • 宽、高两个维度上的像素点数目。
    • 分辨率越高,所需要的显存越大。

  • 色深:
    • 每个像素所对应的内存字节数,一般有8位、16位、24位或32位
    • GEC6818开发板的屏幕的色深是32位的
    • 32位色深的屏幕一般被称为真彩屏,或1600万色屏。

色深决定了一个像素点所能表达的颜色的丰富程度,色深越大,色彩表现力越强。

 2. mmap映射

虽然LCD设备本质上也可以看作是一个文件,在文件系统中有其对应的设备节点,可以像普通文件一样对其进行读写操作(read/write),但由于对字符设备的读写操作是以字节流的方式进行的,因此除非操作的图像尺寸刚好与屏幕尺寸完全一致,如下图所示,图片的宽高与LCD的宽高完全一致,否则将会画面会乱。并且效率相对较低

图像的尺寸大小是随机的,因此更方便的做法是为LCD做内存映射,将屏幕的每一个像素点跟映射内存一一对应,而映射内存可以是二维数组,因此就可以非常方便地通过操作二维数组中的任意元素,来操作屏幕中的任意像素点了。这里的映射内存,有时被称为显存。

  1. LCD上面显示的图像色彩,由其对应的内存的数据决定
  2. 映射内存的大小至少得等于LCD的真实尺寸大小
  3. 映射内存的大小可以大于LCD的真实尺寸,有利于优化动态画面(视频)体验

bmp格式

文件组成

        特征是都没有任何的压缩,因此文件尺寸都比较大,不适合在互联网上传播,优点是数据读取出来即可使用,无需任何解码器支持。

数据段名称 对应大小
bmp头文件 14
信息头

40

调色板 从54开始,有像素点的大小决定

注意 

a. 4字节倍数行距
BMP图片文件的一个重要规则是,每行数据字节数必须是4的倍数,假设某BMP图片的分辨率是 65 × 200,也就是说宽是 65 像素,假设每个字节色深是24bits(即3字节),那么这张图片一行的实际数据量是 65×3=195个字节,但195不是4的倍数,因此在每一行的末尾都会添加一个无效字节,将行距尺寸补到196个字节。

int pad = ((4-( width * bpp/8 ) % 4)) % 4;//计算增加的无效字节

其次,在处理图像数据的时候,直接跳过这些无效字节就好了。

 b. 上下颠倒
BMP图片中的RGB数据是上下颠倒的,因此文件数据中的最后一行是图像的最上面第一行。需要注意的是,上下是颠倒的,但是左右是正常的,因此在处理数据的时候不能从最后一个字节开始,而是从最末一行的首字节开始。

3.jpg格式

在bmp格式下可以直接读文件中RGB值进行显示,但是在jpg格式下的文件必须先进行解码

 jpg第三方开源解码器下载与配置使用

在嵌入式来发中,运用第三方库套路基本一致,所以在这详细介绍一下

(1)下载

直接官方进行下载Independent JPEG Group

不要在Windows下进行解压,会导致问价损坏,将压缩包放在Linux下进行解压

可以阅读README了解开发原理

如何安装

如何使用和例程

在install.txt中

移植三件套./config make makefile

当运行config的时候会检查各种配置,配置检查完成会生成makefile
在开发板中使用的编译工具为gcc

在install,txt中说明需要使用CC=命令进行改变便以及

 将所有的编译命令的前缀改为arrch64-linux

 生成makefile

指定其他路径 

 开启4条线程

 

 提取

提取完成后需要将。文件夹中的lib 与include 中的文件导入到所要使用的文件对应目录中使用一下命令进行编译

 -L:指定库路径    -l指定库名称 -I(i)指定头文件路径 

需要将lib的函数库文件拷贝到开发板的/lib/里面  解决掉找不到库文件的问题

用于指明编译工具

--host=编译工具 

用于指明存放路径

--prifix=存放路径                                         

 ​​​​​

(2)通过官方例程example进行修改 

以下为例程

METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  my_error_ptr myerr = (my_error_ptr) cinfo->err;

  /* Always display the message. */
  /* We could postpone this until after returning, if we chose. */
  (*cinfo->err->output_message) (cinfo);

  /* Return control to the setjmp point */
  longjmp(myerr->setjmp_buffer, 1);
}

struct RGB
{
    char rad;
    cahr green;
    char blue;
};



int read_JPEG_file(char *filename, int *screen_buf)
{

    struct jpeg_decompress_struct cinfo;
     struct my_error_mgr jerr;
    FILE *infile;       /* source file */
    struct RGB *buffer; /* Output row buffer */
    int row_stride;     /* physical row width in output buffer */

    if ((infile = fopen(filename, "rb")) == NULL)
    {
        fprintf(stderr, "can't open %s\n", filename);
        return 0;
    }

    /* Step 1: allocate and initialize JPEG decompression object */

    /* We set up the normal JPEG error routines, then override error_exit. */
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    /* Establish the setjmp return context for my_error_exit to use. */
    if (setjmp(jerr.setjmp_buffer))
    {
        /* If we get here, the JPEG code has signaled an error.
         * We need to clean up the JPEG object, close the input file, and return.
         */
        jpeg_destroy_decompress(&cinfo);
        fclose(infile);
        return 0;
    }

    if ((infile = fopen(filename, "r")) == NULL) // 打开源文件
    {
        fprintf(stderr, "can't open %s\n", filename);
        return 0;
    }

    /* Step 1: allocate and initialize JPEG decompression object */
    jpeg_create_decompress(&cinfo);

    /* Step 2: specify data source (eg, a file) */
    jpeg_stdio_src(&cinfo, infile);

    /* Step 3: read file parameters with jpeg_read_header() */
    (void)jpeg_read_header(&cinfo, TRUE);

    /*开始解码*/
    (void)jpeg_start_decompress(&cinfo);
    row_stride = cinfo.output_width * cinfo.output_components;
    /* Make a one-row-high sample array that will go away when done with image */
    buffer = malloc(row_stride);

    int x, y;
    int calor;
    /*逐行进行数据读取 */
    for (y = 0; cinfo.output_scanline < cinfo.output_height; y++)
    {
        /*将数据的一行读取出来方入buffer中 */
        (void)jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&buffer, 1);

        for (x = 0; x < cinfo.output_width; x++)
        {
            calor = (buffer[x].rad << 16) | (buffer[x].green << 8) | (buffer[x].blue);
            screen_disp(x, y, screen_buf, calor);
        }
        /* Assume put_scanline_someplace wants a pointer and sample count. */
        // put_scanline_someplace(buffer[0], row_stride);
    }

    (void)jpeg_finish_decompress(&cinfo);

    jpeg_destroy_decompress(&cinfo);

    fclose(infile);
    return 1;
}