目录
1.介绍
2.代码
2.1 定义
2.2 图片显示
2.3 格式转换
3.实现效果
4.源码地址
1.介绍
使用stm32单片机将bmp格式的图片显示在屏幕上,如果图片尺寸大于屏幕就将其缩放,图片文件存储在sd卡中,因此显示图片需要首先实现文件系统的移植及lcd屏幕的驱动(本文不涉及这一部分),本文主要实现图片处理这一部分。图片显示的原理就是通过文件系统打开图片文件,读取各像素点的颜色值进行处理后,使用屏幕显示出来。
注:文末给出的例程,部分驱动代码参考了正点原子的代码,例程仅供参考,如有问题,请自行修改。
2.代码
2.1 定义
主要定义了结构体Picture,用来存放图片的宽度,高度等相关信息。
#define P_LEN 240//屏幕宽度;
#define P_HEN 320//屏幕高度;
struct picture
{
uint8_t bmphead[54]; //图片头信息;
uint16_t offset; //图像数据在文件中的偏移量;
uint16_t hight; //图片高度(像素点的个数);
uint16_t weight; //图片宽度;
uint32_t size; //图片的大小;
uint32_t count; //几位色彩;
uint32_t color[P_LEN]; //处理后的像素的颜色值;
uint8_t rgba[4 * P_LEN];//处理前的像素的颜色值;
}Picture;
2.2 图片显示
函数LCD_Show_Bmp,就是实现图片显示的主要函数,只需要在主函数中调用该函数传入图片名,就能将图片显示在屏幕上。
void LCD_Show_Bmp(char *pn)
{
uint8_t kes = 0, ucRes;
FIL ftp;//文件指针;
char pname[100];//打开的图片文件名;
int i = 0;
uint32_t brt;
uint32_t Pb = 0;//需要的像素点索引;
uint32_t P_L = 0;//缩放后的图片宽度(即实际屏幕上显示的);
uint32_t P_H = 0;//缩放后的图片高度;
uint32_t P_X = 0;//显示图片的X起始坐标;
uint32_t P_Y = 0;//显示图片的Y起始坐标;
uint32_t pl = 0; //行像素;
uint32_t len1 = 0, len2 = 0;//图片的宽度可能很宽,每次只取240个像素点,
//len1表示取的次数,len2表示剩下不足240的像素数;
float P_mag;//缩放比例;
uint32_t mt1 = 0, mt2 = 0;//与缩放比例有关;
pname[0] = '0';//存储的路径;
pname[1] = ':';
while(pn[i] != '\0')
{
pname[i + 2] = pn[i];
i++;
}
pname[i + 2] = '\0';
kes = PutGetFile_Sys(); //挂载文件系统;
if(kes == 0)
{
printf("文件系统挂载失败!\n");
return;
}
ucRes = f_open(&ftp, pname, FA_OPEN_ALWAYS | FA_READ | FA_WRITE);//打开bmp格式的图片文件;
if(ucRes != 0)
{
printf("图片文件打开失败!\n");
return;
}
f_lseek(&ftp, 0);
f_read(&ftp, Picture.bmphead, 54, &brt);//读取文件头信息;
//计算偏移量,宽度,高度等;
Picture.offset = Picture.bmphead[10] + Picture.bmphead[11] * 256 + Picture.bmphead[12] * 256 * 256 + Picture.bmphead[13] * 256 * 256 * 256;
Picture.weight = Picture.bmphead[18] + Picture.bmphead[19] * 256 + Picture.bmphead[20] * 256 * 256 + Picture.bmphead[21] * 256 * 256 * 256;
Picture.hight = Picture.bmphead[22] + Picture.bmphead[23] * 256 + Picture.bmphead[24] * 256 * 256 + Picture.bmphead[25] * 256 * 256 * 256;
Picture.size = Picture.bmphead[2] + Picture.bmphead[3] * 256 + Picture.bmphead[4] * 256 * 256 + Picture.bmphead[5] * 256 * 256 * 256;
Picture.count = Picture.bmphead[28] / 8;
len1 = Picture.weight / P_LEN;
len2 = Picture.weight % P_LEN;
if(Picture.weight > P_LEN || Picture.hight > P_HEN)
{
if(((float)Picture.weight / (float)P_LEN) >= ((float)Picture.hight / (float)P_HEN))
{
P_mag = ((float)Picture.weight / (float)P_LEN);
P_L = P_LEN;
P_H = P_rand((float)Picture.hight / P_mag);
P_X = 0;
P_Y = P_HEN - ((P_HEN - P_H) / 2);
mt1 = Picture.weight;
mt2 = P_LEN;
}
else
{
P_mag = ((float)Picture.hight / (float)P_HEN);
P_H = P_HEN;
P_L = P_rand((float)Picture.weight / P_mag);
P_X = ((P_LEN - P_L) / 2);
P_Y = P_HEN;
mt1 = Picture.hight;
mt2 = P_HEN;
}
}
else
{
P_mag = 1;
P_L = Picture.weight;
P_H = Picture.hight;
P_X = ((P_LEN - P_L) / 2);
P_Y = P_HEN - ((P_HEN - P_H) / 2);
mt1 = 1;
mt2 = 1;
}
for(int k = P_H; k > 0; k --)
{
pl = 0;
for(int m = 0; m < len1; m++)
{
f_lseek(&ftp, Picture.offset + (P_mand(mt1, mt2, (k - 1)) * Picture.weight + m * P_LEN)* Picture.count);
f_read(&ftp, Picture.rgba, Picture.count * P_LEN, &brt);
for(int j = pl; j < P_L; j ++)
{
Pb = P_mand(mt1, mt2, j);
if(Pb < (m + 1) * P_LEN)
{
Picture.color[j] = P_TranColor(Picture.rgba[(Pb % P_LEN) * Picture.count + 0], Picture.rgba[(Pb % P_LEN) * Picture.count + 1 ], Picture.rgba[(Pb % P_LEN) * Picture.count + 2]);
}
else
{
pl = j;
break;
}
}
}
f_lseek(&ftp, Picture.offset + (P_mand(mt1, mt2, (k - 1)) * Picture.weight + len1 * P_LEN) * Picture.count);
f_read(&ftp, Picture.rgba, Picture.count * len2, &brt);
for(int j = pl; j < P_L; j ++)
{
Pb = P_mand(mt1, mt2, j);
if(Pb < (len1 * P_LEN + len2))
{
Picture.color[j] = P_TranColor(Picture.rgba[(Pb % P_LEN) * Picture.count + 0], Picture.rgba[(Pb % P_LEN) * Picture.count + 1 ], Picture.rgba[(Pb % P_LEN) * Picture.count + 2]);
}
else
{
pl = j;
break;
}
}
LCD_SetCursor(P_X, P_Y - 1 - (k - 1));
LCD_WriteRAM_Start();
for(int kt = 0; kt < P_L; kt++)
{
LCD_SendData(Picture.color[kt]);
}
}
f_close(&ftp);
}
2.3 格式转换
uint16_t P_TranColor(uint8_t P_Blue, uint8_t P_Green, uint8_t P_Red)//24位(RGBA格式实际为32位,最后8位舍弃)转为16位颜色;
{
uint16_t P_Color = 0;
P_Color = (uint16_t)(P_Blue >> 3) | ((uint16_t)(P_Green >> 2) << 5) | ((uint16_t)(P_Red >> 3) << 11);
return P_Color;
}
/*缩放图片(通过四舍五入找出需要的像素点)*/
int P_mand(int len1, int len2, int num) //原始图片像素数/屏幕实际像素数 * 第几个像素;
{
int sum = 0;
sum = (len1 * num) / len2;
if( 2 * ((len1 * num) % len2) >= len2)
{
sum += 1;
}
return sum;
}
int P_rand(float temp)//将小数四舍五入成整数;
{
int kemp = 0;
float memp = 0;
kemp = (int)temp;
memp = temp - kemp;
if(memp >= 0.5)
{
kemp = kemp + 1;
}
return kemp;
}
3.实现效果
将图片拷贝到sd卡,插入开发板中,然后将程序下载到开发板中,本文中使用的正点原子的stm32mini板,其他开发板视情况自行修改,效果如下:
文章来源:https://www.toymoban.com/news/detail-517364.html
4.源码地址
百度网盘地址:https://pan.baidu.com/s/1eMTKy2vSxBybVcjuAfkY5Q?pwd=31ji 提取码: 31ji文章来源地址https://www.toymoban.com/news/detail-517364.html
到了这里,关于stm32显示bmp图片的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!