嵌入式 在开发板显示bmp图片、jpeg图片

2023-11-08

嵌入式 在开发板显示bmp图片、jpeg图片

一、简述

        记--在GEC6818开发板(800W*480H)显示24位的bmp图片、使用开源的jpeg库显示jpeg图片。

        代码:链接: https://pan.baidu.com/s/1G3jzvdncocDMRbwCvsmSlg 密码: gz6m

二、效果

        执行开始显示bmp图片,回车后显示jpg图片。

 三、工程结构

 

四、源代码

        display_bmp.c文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
 
#include "lcd.h"
#include "freetype.h"
#include "to_wchar.h"
#include "display_bmp.h"
 
/*display_bmp:显示bmp图片
 *pathname:图片的路径名
 *lcd_ptr:指向LCD映射首地址
 *x_s,y_s:左上角起始点
 */
int display_bmp(const char *pathname, unsigned int *lcd_ptr,unsigned int x_s, unsigned int y_s)
{
	unsigned int bmp_width,bmp_height;
	unsigned int x, y, color;
	unsigned char *pic_buf_ptr, *ptr_save;
	
	if( get_bmp_width_and_height( pathname, &bmp_width, &bmp_height) != 0 )//获取图片的宽高
	{
		fprintf(stderr, "get bmp width and height failed!\n");
		return -1;
	}
 
	if( get_pic_data_to_buffer(pathname, &pic_buf_ptr) == -1 )//获取图片的像素数据
	{
	    fprintf(stderr, "get picture data error\n");
		return -1;
	}
	ptr_save = pic_buf_ptr;
	
	for(y=y_s; y<y_s+bmp_height && y< LCD_HEIGHT; y++)
	{  
		for(x=x_s; x< x_s+bmp_width ; x++)
		{  
			if(x>=0 && x< LCD_WIDTH)
			{	    
				//将RGB的3个字节颜色数据装到4字节  RGB:红绿蓝
				color = (*(pic_buf_ptr+2)<<16) | (*(pic_buf_ptr+1)<<8) | (*pic_buf_ptr);
				lcd_draw_point(x, LCD_HEIGHT-y-1, color, lcd_ptr);//LCD_HEIGHT-y-1:镜像翻转
			}
			pic_buf_ptr += 3;//三个字节一个颜色像素点
		}
		
	}   
 
	//显示图片路径名	
	wchar_t *w_pathname = NULL;
	if( mchars_to_wchars(pathname, &w_pathname) == 0)//将多字节转换为宽字符(汉字未能转换成功)
	{
		//显示字体
		Lcd_Show_FreeType(w_pathname,32,0x00,x_s+10,y_s+50, lcd_ptr);
		free(w_pathname);
	}
	
	free( ptr_save );
	return 0;
}
 
/*get_pic_data_to_buffer:获取图片的像素数据
 *pathname:图片的路径名
 *pic_buf_ptr:用来指向 存放图片的像素数据缓冲区
 */
int get_pic_data_to_buffer(const char *pathname, unsigned char **pic_buf_ptr)
{
    FILE *pic_fp;
	off_t file_size;
	struct stat file_info;
        
	pic_fp = fopen(pathname, "r");
	if(pic_fp == NULL)
	{
		perror("open %s error\n");
		return -1;
	}
 
	if( stat(pathname, &file_info) == -1)
	{
		perror("get file info error\n");
		return -1;
	}
	
	file_size = file_info.st_size;//获取图片大小
	*pic_buf_ptr = (unsigned char *)malloc(file_size-54);
 
	fseek(pic_fp, 54,SEEK_SET);//跳过文件头(存在内存对齐,可能是56字节)
	
	fread(*pic_buf_ptr, file_size-54, 1, pic_fp);//读取图片颜色数据
	if(ferror(pic_fp))
	{
			perror("read picture data error\n");
			return -1; 
	}
 
	return fclose(pic_fp);
    
}
 
/*get_bmp_width_and_height:获取bmp图片的宽高信息
 *pathname:图片路径名
 *width:图片的宽度
 *height:图片的高度
 */
int get_bmp_width_and_height(const char *pathname, unsigned int *width, unsigned int *height)
{
	FILE *pic_fp;
	unsigned char file_head[54];
 
	pic_fp = fopen(pathname, "r");
	if(pic_fp == NULL)
	{
		perror("open %s error\n");
		return -1;
	}
 
	fread( file_head, 54, 1, pic_fp);
	if( ferror( pic_fp ) )
	{
		perror("read picture head error\n");
		return -1;
	}
	fclose(pic_fp);
	
	*width = *((int*)&file_head[18]);//宽:18~21共4个字节
	*height = file_head[22] | file_head[23]<<8;//高:22~23共两个字节
 
	return 0;
}
 
 

      display_jpeg.c文件

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <jpeglib.h>
#include <jerror.h>
 
#include "lcd.h"
#include "to_wchar.h"
 
extern JSAMPLE * image_buffer;	/* Points to large array of R,G,B-order data */
extern int image_height;	/* Number of rows in image */
extern int image_width;
 
struct my_error_mgr 
{
	struct jpeg_error_mgr pub;	/* "public" fields */
	jmp_buf setjmp_buffer;	/* for return to caller */
};
 
typedef struct my_error_mgr * my_error_ptr;
 
METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
	my_error_ptr myerr = (my_error_ptr) cinfo->err;
	(*cinfo->err->output_message) (cinfo);
 
	longjmp(myerr->setjmp_buffer, 1);
}
 
/*display_jpeg:显示jpeg图片
 *filename:图片的路径名
 *lcd_ptr:指向LCD映射首地址
 *x_s,y_s:左上角起始点
 */
int display_jpeg (char * filename, unsigned int *lcd_ptr,unsigned int x_s, unsigned int y_s)
{
 
	struct my_error_mgr jerr;
	struct jpeg_decompress_struct cinfo;
	int row_stride;		/* physical row width in output buffer */
	FILE * infile;		/* source file */
 
	if((infile = fopen(filename, "rb")) == NULL) 
	{
		fprintf(stderr, "can't open %s\n", filename);
		return -1;
	}
 
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
  
	if(setjmp(jerr.setjmp_buffer)) 
	{    
		jpeg_destroy_decompress(&cinfo);
		fclose(infile);
		return -1;
	}
 
	jpeg_create_decompress(&cinfo);
 
	jpeg_stdio_src(&cinfo, infile);
	
	jpeg_read_header(&cinfo, TRUE);
    
	jpeg_start_decompress(&cinfo);
  
	row_stride = cinfo.output_width * cinfo.output_components;
 
	char *buffer;  
	buffer = (char*)(*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
 
	unsigned int x, y;
	unsigned int color;
	char * ptr_save = buffer; 
 
	y = y_s;
	while(cinfo.output_scanline < cinfo.output_height && y < cinfo.output_height) 
	{    
		buffer = ptr_save;
		jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&buffer, 1);
		
		for(x=x_s; x< x_s+cinfo.output_width && x<LCD_WIDTH; x++)
		{
			color = buffer[2] | buffer[1]<<8 | buffer[0]<<16;
			lcd_draw_point(x, y, color, lcd_ptr);
 
			buffer += 3;
		}
 
		y++;
	}
	
	//显示图片路径
	wchar_t *w_pathname = NULL;
	if( mchars_to_wchars(filename, &w_pathname) == 0)
	{
		//显示图片路径
		Lcd_Show_FreeType(w_pathname,32,0x00,x_s+10,y_s+50, lcd_ptr);
		free(w_pathname);
	}
 
 
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	fclose(infile);
	return 0;
}

      freetype.c文件

#include <sys/mman.h>
#include <stdio.h>
#include <linux/fb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wchar.h>
#include <string.h>
#include <ft2build.h>
#include FT_FREETYPE_H
 
#include <lcd.h>
 
 
#define	SIM_TTY_PATH	"font/simsun.ttc"
/*	
	功能:根据得到的RGB24数据,进行图像任意位置显示
	(主要是迎合上面的各种转换函数的显示测试)
	x:显示的x轴起点
	y:显示的y轴起点
	w:显示图像宽度。
	h:显示图像高度。
	bit_dept:要显示的图像位深 24/32
	pbmp_data:要进行显示的RGB24_buf
*/
int Show_FreeType_Bitmap(FT_Bitmap*  bitmap,int start_x,int start_y,int color, unsigned int *lcd_buf_ptr)
{
	int  buff_x, buff_y;	//遍历bitmap时使用
	int  x,y;	//循环遍历使用
	int  end_x = start_x + bitmap->width;	//图像宽度
	int  end_y = start_y + bitmap->rows;	//图像高度
 
	for ( x = start_x, buff_x = 0; x < end_x; buff_x++, x++ )	//y表示起点y,x表示起点x
	{
		for ( y = start_y, buff_y = 0; y < end_y; buff_y++, y++ )	//y表示起点y,x表示起点x
		{
			//LCD边界处理
			if ( x < 0 || y < 0 || x >=800   || y >= 480 )
				continue;
 
			if(bitmap->buffer[buff_y * bitmap->width + buff_x] )	//判断该位上是不是为1,1则表明需要描点
				lcd_draw_point(start_x+buff_x , start_y+buff_y ,  color, lcd_buf_ptr);		//在当前x位置加上p的偏移量(p表示buff中列的移动)
				//在当前y位置加上q的偏移量(q表示buff中行的移动)
			
		}
	}
} 
 
void Lcd_Show_FreeType(wchar_t *wtext, int size, int color, int start_x, int start_y, unsigned int *lcd_buf_ptr)
{
 
	//1.定义库所需要的变量
	FT_Library    library;
	FT_Face       face;
	FT_GlyphSlot  slot;	//用于指向face中的glyph
	FT_Vector     pen;                    
	FT_Error      error;
 
	int n;
 
	
	//2.初始化库
	error = FT_Init_FreeType( &library );            
 
	//3.打开一个字体文件,并加载face对象:
	error = FT_New_Face( library, SIM_TTY_PATH, 0, &face ); 
	slot = face->glyph;
	
	//4.设置字体大小
	error = FT_Set_Pixel_Sizes(face, size, 0); 
	
	//x起点位置:start_x。需要*64
	pen.x = start_x * 64;	
	//y起点位置:LCD高度 - start_y。需要*64
	pen.y = ( 480 - start_y ) * 64;
	
	//每次取出显示字符串中的一个字
	for ( n = 0; n < wcslen( wtext ); n++ )	
	{
		//5.设置显示位置和旋转角度,0为不旋转,pen为提前设置好的坐标
		FT_Set_Transform( face, 0, &pen );
		
		
		//将字形槽的字形图像,转为位图,并存到 face->glyph->bitmap->buffer[],并且更新bitmap下的其他成员,
		//	face->glyph->bitmap.rows:图像总高度
		//	face->glyph->bitmap.width:图像总宽度
		//	face->glyph->bitmap.pitch:每一行的字节数
		//	face->glyph->bitmap.pixel_mode:像素模式(1单色 8反走样灰度)
		//	face->glyph->bitmap.buffer:点阵位图的数据缓冲区
	
 
		
		error = FT_Load_Char( face, wtext[n], FT_LOAD_RENDER );
			//FT_LOAD_RENDER表示转换RGB888的位图像素数据
			
		//出错判断	
		if ( error )
		  continue;                
		
		
		Show_FreeType_Bitmap(&slot->bitmap, slot->bitmap_left, 480 - slot->bitmap_top, color, lcd_buf_ptr);
		
		//增加笔位
		pen.x += slot->advance.x;
		
	}	
	
	FT_Done_Face(face);
	FT_Done_FreeType(library);
	
}
 
 
 
 
 
 

        lcd.c文件

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
 
#include "lcd.h"
 
/*lcd_draw_point:在lcd上画一个点
 *x:x轴坐标   (左上角为原点,x轴分别向右,y轴下递增)
 *y:y轴坐标
 *color:点的颜色
 *lcd_ptr:LCD的操作指针
 */
void lcd_draw_point(unsigned int x, unsigned int y, unsigned int color, unsigned int *lcd_ptr)
{
	if( x>=0 && x<LCD_WIDTH && y>=0 && y<LCD_HEIGHT )
	{
		*(lcd_ptr+LCD_WIDTH*y+x) = color;
	}
}
 
/*lcd_draw_full_srceen_single_color:用一种颜色画满整个屏幕
 *color:点的颜色
 *lcd_ptr:LCD的操作指针
 */
void lcd_draw_full_srceen_single_color(unsigned int color, unsigned int *lcd_ptr)
{
	int x, y;
	for(y=0;y<LCD_HEIGHT;++y)
	{
		for(x=0;x<LCD_WIDTH;++x)
		{
			lcd_draw_point(x, y, color, lcd_ptr);
		}
	}
}
 
/*open_lcd_device:打开LCD
 *lcd_ptr:LCD的内存映射首地址
 *返回值:lcd_fd:LCD的描述符
 */
int open_lcd_device(unsigned int **lcd_ptr)
{
 
	int lcd_fd;
	lcd_fd = open("/dev/fb0", O_RDWR);//打开LCD设备
	if(lcd_fd == -1)
	{
		perror("open lcd device failed\n");
		return -1;
	}
 
	//内存映射
	*lcd_ptr = mmap( NULL, LCD_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
	if(lcd_ptr == MAP_FAILED)
	{
		perror("map lcd_fb error\n");
		return -1;
	}
 
	return lcd_fd;
}
 
/*close_lcd_device:关闭LCD
 *lcd_fd:LCD的描述符
 *lcd_ptr:LCD的内存映射首地址
 */
int close_lcd_device(int lcd_fd, unsigned int *lcd_ptr)
{
	munmap(lcd_ptr, LCD_SIZE);
	return close(lcd_fd);
}

main.c文件

#include <stdio.h>
#include <stdlib.h>
 
#include "lcd.h"
#include "freetype.h"
#include "display_bmp.h"
#include "display_jpeg.h"
 
int main(int argc, char *argv[])
{
	int lcd_fd;
	int dis_ret;
	unsigned int *lcd_ptr;
 
	//打开LCD
	lcd_fd = open_lcd_device(&lcd_ptr);
	if(lcd_fd == -1)
	{
		return -1;
	}
 
	//显示bmp图片
	dis_ret = display_bmp("pic/test.bmp", lcd_ptr, 0, 0);
	if(dis_ret != 0)
	{
		printf("display bmp error\n");
	}
 
	printf("please enter any key continue!\n");
	getchar();
 
	//显示jpeg图片
	dis_ret = display_jpeg("pic/bird.jpg", lcd_ptr, 0, 0);
	if(dis_ret != 0)
	{
		printf("display jpeg error\n");
        }
	//关闭LCD
	close_lcd_device(lcd_fd, lcd_ptr);
 
	return 0;
}

to_wchar.c文件

#include <wctype.h>
#include <locale.h>
#include <wchar.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
/*mchars_to_wchars:多字节转宽字符
 *mbs_char:多字节字符串
 *w_char:宽字符
 */
int mchars_to_wchars(const char *mbs_char, wchar_t **w_char)
{
	int mbslen = mbstowcs(NULL, mbs_char, 0);
	if (mbslen == (size_t) -1) 
	{
		perror("mbstowcs");
		return -1;
    }
    *w_char = NULL;
/*	if (setlocale(LC_CTYPE, "zh_CN.utf8") == NULL) 
	{
               perror("setlocale");
	       return -1;
        }
*/
	*w_char = calloc(mbslen + 1, sizeof(wchar_t));
	if(*w_char == NULL )
	{
		perror("calloc\n");
		return -1;
	}
	if (mbstowcs(*w_char, mbs_char, mbslen + 1) == (size_t) -1)
	{
		perror("mbstowcs");
		free(*w_char);
		return -1;
	}
	//printf("Wide character string is: %ls (%zu characters)\n", *w_char, mbslen);
	return 0;
}

Makefile文件

make:
	arm-linux-gcc src/*.c -o lcd -I include -I include/freetype2 -L lib -ljpeg -lfreetype

转自:嵌入式 在开发板显示bmp图片、jpeg图片_Genven_Liang的博客-CSDN博客_粤嵌arm开发板显示bmp图片

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式 在开发板显示bmp图片、jpeg图片 的相关文章

  • 设计模式-多业务,统一入口

    比如对接一些第三方 会有异步通知 或者在第三方设置唯一回调接口 或者统一验签等场景 这个时候可能就需要我们搞一个统一入口来处理不同的业务 1 定义统一入口 RestController RequestMapping value notify

随机推荐

  • GitHub和Gitee的源码下载

    1 使用clone命令下载 如果本地安装了Git环境的话 可以直接在命令行中使用git clone命令把仓库中的文件全部下载到本地 通过GitHub下载源码 执行如下命令 git clone https github com git 其中后
  • BigDecimal详解

    文章目录 前言 一 BigDecimal类 二 常用方法 1 构造方法 2 基本的运算 加法 减法 乘法 除法 3 保留小数 精确到几位 4 舍入的类型 ROUND UP向上舍入 ROUND DOWN向下舍入 ROUND CEILING正向
  • iOS import包

    Frameworks Frameworks 顾名思义就是框架 是第三方打包完成看不到源码 可以直接使用的 在项目中引用方式 OC 引用某一个文件 Frameworks一般会提供一个h文件引用全部其他文件 import
  • 【100天精通python】Day27:文件与IO操作_CSV文件处理

    目录 专栏导读 1 CSV文件格式简介 2 csv模块的使用方法 3 读写CSV文件的示例 3 1 读取CSV文件示例 3 2 写入CSV文件示例 4 CSV文件的常用数据处理 4 1 读取CSV文件的特定列 4 2 读取CSV文件的特定行
  • maven打包时和 deploy时候将不会 依赖包含在生成的项目 jar中方法

    用 provided
  • Python模块学习:glob 文件路径查找

    文章转载自 伯乐在线 原文出处 Darkbull Python模块学习 glob 文件路径查找 glob模块是最简单的模块之一 内容非常少 用它可以查找符合特定规则的文件路径名 跟使用windows下的文件搜索差不多 查找文件只用到三个匹配
  • 第2.2章 使用两个“半加器”实现一个“全加器”

    刚才的电路考虑了加法的运算结果可能会有进位 当A和B都为1时 可以作为最低位的运算电路 但不能计算其他位 十位 百位等 因为没有考虑低位的进位结果 因此 只能叫做半加器 Half Adder 实际上 一个完整的加法器的输入端有3个 A B和
  • 04-3. Huffman Codes (30)

    04 3 Huffman Codes 30 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN Yue In 1953 David A Huffman publishe
  • 1、若依VUE代码结构:官方文档+资料+总结

    来自官方文档 build 构建相关 bin 执行脚本 public 公共文件 favicon ico favicon图标 index html html模板 robots txt 反爬虫 src 源代码 api 所有请求 assets 主题
  • js实现数组扁平化的几种方式

    数组扁平化 数组的扁平化就是将一个嵌套多层的数组转换为只有一层的数组 扁平化也是面试中常见的考题 举个简单的例子 假设有个名为 flatDeep 的函数能实现数组扁平化效果 代码运行效果如下面 var array 1 2 3 4 5 con
  • 大模型攻防|Prompt 提示词攻击

    前言 本文介绍大模型攻防领域中 Prompt提示词攻击 的相关知识 目录 Prompt 提示词攻击 提示词注入攻击 提示词泄露攻击 提示词越狱攻击 假装 其他 越狱 方法 AI 的进步 防御方法 Prompt 提示词攻击 提示词作为人和大语
  • 尚硅谷 Vue2.0 + Vue3.0 入门到精通教程学习笔记 (一)

    目录 第1章 Vue 核心 1 1 Vue 简介 1 1 1 官网 1 1 2 介绍与描述 1 1 3 Vue 的特点 1 1 4 与其他 JS 框架的关联 1 1 5 Vue 周边库 1 2 初始 Vue 1 3 模板语法 1 4 数据绑
  • Qt学习笔记八 二维图形(2) 坐标系统变换

    在 Qt 中 可以改变系统默认的屏幕坐标系 在 QPainter 默认的坐标系中 点 0 0 位于屏幕的左上角 X 轴向右 Y 轴向下 每个像素占 1x1 大小 1 移动坐标系 改变坐标系原点 0 0 位置 通过 QPainter setW
  • 搭建一个基于https://www.zuoye.com:22222访问的web网站

    创建目录 编辑网站内容 接下来定义配置文件 etc httpd conf d https conf vim etc httpd conf d https conf 分别在虚拟机和Windows主机上添加域名 关闭selinux和防火墙 重启
  • 决策树与随机森林

    首先 在了解树模型之前 自然想到树模型和线性模型有什么区别呢 其中最重要的是 树形模型是一个一个特征进行处理 之前线性模型是所有特征给予权重相加得到一个新的值 决策树与逻辑回归的分类区别也在于此 逻辑回归是将所有特征变换为概率后 通过大于某
  • Python_selenium之获取页面上的全部邮箱

    Python selenium之获取页面上的全部邮箱 一 思路拆分 获取网页 这里以百度的 联系我们 为例 网址http home baidu com contact html 获取页面的全部内容 driver page source 运用
  • SOTA机制详解

    1 SOTA的定义 SOTA即软件在线升级 Software updates Over The Air 是指在不连接烧写器的情况下 通过CAN UART或其它通讯方式 实现应用程序的更新 在进行SOTA时 需要把旧的应用程序擦除 把新的应用
  • 使用pytorch的错误整理

    1 Using home liao cache torch extensions py38 cu102 as PyTorch extensions root 程序卡在Using home liao cache torch extension
  • The GPG keys listed for the “packages for the GitHub CLI” repository are already installed

    在Fedora36执行sudo dnf update遇到这个错误 The GPG keys listed for the packages for the GitHub CLI repository are already installe
  • 嵌入式 在开发板显示bmp图片、jpeg图片

    嵌入式 在开发板显示bmp图片 jpeg图片 一 简述 记 在GEC6818开发板 800W 480H 显示24位的bmp图片 使用开源的jpeg库显示jpeg图片 代码 链接 https pan baidu com s 1G3jzvdnc