vs2019开发,还是有点不方便,图片还要编码,然后显示,着实不方便,下一步搞搞freetype也可以显示。
1、添加LV_PNG
官网上的lv_png拉取,但需要做些修改,静态画面显示没问题,但是让图标动起来,那就“出问题”,显示太慢了。分析源码,可以看出是直接读取文件在解码。
看源码lodepng.c line:418左右。
#ifdef LODEPNG_COMPILE_DISK//从硬盘读取文件并解码
/* returns negative value on error. This should be pure C compatible, so no fstat. */
static long lodepng_filesize(const char* filename)
{
#if LV_PNG_USE_LV_FILESYSTEM
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return -1;
uint32_t size = 0;
lv_fs_size(&f, &size);
lv_fs_close(&f);
return size;
#else
if (!strcmp(&filename[strlen(filename) - 3], "png"))
{
long size;
FILE* file;
file = fopen(filename, "rb");
if (!file) return -1;
if (fseek(file, 0, SEEK_END) != 0)
{
fclose(file);
return -1;
}
size = ftell(file);
/* It may give LONG_MAX as directory size, this is invalid for us. */
if (size == LONG_MAX) size = -1;
fclose(file);
return size;
}
#endif
}
/* load file into buffer that already has the correct allocated size. Returns error code.*/
static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename)
{
#if LV_PNG_USE_LV_FILESYSTEM
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return 78;
uint32_t br;
res = lv_fs_read(&f, out, size, &br);
if(res != LV_FS_RES_OK) return 78;
if (br != size) return 78;
lv_fs_close(&f);
return 0;
#else
if (!strcmp(&filename[strlen(filename) - 3], "png"))
{
FILE* file;
size_t readsize;
file = fopen(filename, "rb");
if (!file) return 78;
readsize = fread(out, 1, size, file);
fclose(file);
int tuyp = size;
if (readsize != size) return 78;
return 0;
}
return 0;
#endif
}
unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename)
{
long size = lodepng_filesize(filename);
if (size < 0) return 78;
*outsize = (size_t)size;
*out = (unsigned char*)lodepng_malloc((size_t)size);
if(!(*out) && size > 0) return 83; /*the above malloc failed*/
return lodepng_buffer_file(*out, (size_t)size, filename);
}
#endif /*LODEPNG_COMPILE_DISK*/
问:那有没有办法可以提前解码,后显示呢!
答:可以!
在lodepng.h中 line:71 添加 #define LODEPNG_NO_COMPILE_DISK ,我们不需要这段代码。
修改lv_png.c,需要大改,有需要的可以备份一个原版。
修改如下:
/**********************
* TYPEDEFS
**********************/
PNG_Decode_Struct PNG_DS[PNG_MAX_NUM];
static lv_res_t decoder_info(struct _lv_img_decoder * decoder, const void * src, lv_img_header_t * header)
{
(void) decoder; /*Unused*/
lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/
/*If it's a PNG file...*/
if(src_type == LV_IMG_SRC_FILE)
{
const char * fn = src;
if (atoi(fn) < PNG_MAX_NUM)//20210324修改 by ly
{
header->always_zero = 0;
header->cf = LV_IMG_CF_RAW_ALPHA;
/*The width and height are stored in Big endian format so convert them to little endian*/
header->w = PNG_DS[atoi(fn)].Width;//直接赋值,不需要运算
header->h = PNG_DS[atoi(fn)].Height;
return LV_RES_OK;
}
else
{
printf("Exceed the maximum: %d",PNG_MAX_NUM);
return LV_RES_INV;
}
}
return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/
}
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
(void) decoder; /*Unused*/
/*If it's a PNG file...*/
if(dsc->src_type == LV_IMG_SRC_FILE) {
const char * fn = dsc->src;
if (atoi(fn) < PNG_MAX_NUM) { //20210324 修改 by ly
dsc->img_data = PNG_DS[atoi(fn)].img_data;
dsc->user_data = 0;
return LV_RES_OK; /*The image is fully decoded. Return with its pointer*/
}
}
return LV_RES_INV; /*If not returned earlier then it failed*/
}
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
(void) decoder; /*Unused*/
// if(dsc->img_data) free((uint8_t *)dsc->img_data);//不在这里释放图片
}
修改OK!
添加自定义解码程序
/**
* 解析PNG文件
*/
void load_png_file(const char* filename, uint32_t index)
{
FILE* file;
uint32_t error; /*For the return values of PNG decoder functions*/
uint8_t* buf_data = NULL;
/*Decode the PNG image*/
uint32_t png_width; /*Will be the width of the decoded image*/
uint32_t png_height; /*Will be the width of the decoded image*/
size_t png_size; //图片大小
uint32_t W_H[2];
file = fopen(filename, "rb");//打开文件
if (!file)
{
fclose(file);
return -1;
}
if (fseek(file, 16, SEEK_SET) != 0)//文件开头偏移16字节
{
fclose(file);
return -1;
}
size_t rn = fread(W_H, 1, 8, file);//获取高度、宽度
if (rn != 8)
{
fclose(file);
return -1;
}
PNG_DS[index].Width = (lv_coord_t)((W_H[0] & 0xff000000) >> 24) + ((W_H[0] & 0x00ff0000) >> 8);//获得宽度
PNG_DS[index].Height = (lv_coord_t)((W_H[1] & 0xff000000) >> 24) + ((W_H[1] & 0x00ff0000) >> 8);//获得高度
png_size = ftell(file);//获得文件大小
if (fseek(file, 0, SEEK_END) != 0)//文件偏移至结尾
{
fclose(file);
return -1;
}
png_size = ftell(file);//获得文件大小
buf_data = malloc(png_size);//分配空间
if (buf_data == NULL)
{
fclose(file);
return -1;
}
if (fseek(file, 0, SEEK_SET) != 0)//文件偏移至开头
{
fclose(file);
return -1;
}
size_t len = fread(buf_data, 1, png_size, file);//读取整个图片
/* Decode the loaded image in ARGB8888 */
error = lodepng_decode32(&PNG_DS[index].img_data, &png_width, &png_height, buf_data, png_size);
free(buf_data);
if (error) {
printf("error %u: %s\n", error, lodepng_error_text(error));
return LV_RES_INV;
}
convert_color_depth(PNG_DS[index].img_data, png_width * png_height);
fclose(file);
}
lv_png.h
#define PNG_MAX_NUM 50//PNG图片最大同时载入数量
//PNG解码格式
typedef struct {
uint8_t* img_data;//图形数据
uint32_t Width;//图片的宽度
uint32_t Height;//图片的高度
}PNG_Decode_Struct;
extern PNG_Decode_Struct PNG_DS[PNG_MAX_NUM];
使用方法:
example.c
……
load_png_file("F:\\03-lv_png\\0.png",0);
load_png_file("F:\\03-lv_png\\1.png", 1);
lv_png_init();
lv_obj_t* imgbtn2 = lv_imgbtn_create(parent, NULL);//创建图片按键
lv_imgbtn_set_src(imgbtn2, LV_BTN_STATE_PRESSED, "0");//按下
lv_imgbtn_set_src(imgbtn2, LV_BTN_STATE_RELEASED, "0");//抬起
lv_obj_align(imgbtn2, NULL, LV_ALIGN_IN_TOP_LEFT, 150, 25);//左上角对齐
2、添加LV_GIF
直接拉取lvgl在github的代码,添加即可,有些地方要改,时间长了忘了,好像是文件函数。也可以直接用我提供的代码。
3、让背景动起来?
背景么,静态的、动态的,静态的资源多,动态的难找哦,一些动态壁纸还要会员,要么就是不能下载,但还是有方法的,只是怕侵权,学习的话还是可以的。有需要的话私聊。
现在直接用gif作为背景图,一个字,酷。
static void action_task_cb(lv_task_t* t)
{
lv_obj_t* img = t->user_data;
lv_gif_restart(img);
}
//菜单页
void Home_Page_Create(void)
{
/*Create a Tab view object*/
lv_obj_t* tabview;
lv_obj_t* bg_img = lv_gif_create_from_file(lv_scr_act(), "F:\\03-lv_png\\back.gif");
lv_task_create(action_task_cb, 9000, LV_TASK_PRIO_HIGH, bg_img);
lv_style_init(&env_set.page_style);//初始化风格
lv_style_set_bg_opa(&env_set.page_style, LV_STATE_DEFAULT, LV_OPA_TRANSP);//设置背景为透明
tabview = lv_tabview_create(lv_scr_act(), NULL);//创建一个tabview
lv_obj_set_size(tabview, LV_HOR_RES_MAX, LV_VER_RES_MAX);//设置大小
lv_obj_align(tabview, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);//对齐
lv_tabview_set_btns_pos(tabview, LV_TABVIEW_TAB_POS_NONE);//不显示btns
lv_obj_add_style(tabview, LV_PAGE_PART_BG, &env_set.page_style);//添加风格
lv_obj_t* tab1 = lv_tabview_add_tab(tabview, "Tab 1");//创建第一页
lv_obj_t* tab2 = lv_tabview_add_tab(tabview, "Tab 2");//创建第二页
notice_board(tabview);//创建通知栏
First_Page_Create(tab1);//第一页
Second_Page_Create(tab2);//第二页
}
改好的VS2019工程,注意文件名不要有中文,有需要的自己下载:
链接:https://pan.baidu.com/s/12Kv1XdKe18FWf-F4DHYWlQ
提取码:wdnm