之前的两篇帖子分别搞定了MAX78000开发板读取SD卡和驱动TFT液晶屏。这次将SD卡和液晶屏结合起来制作一个电子相册。
一、图片格式预处理:这个2.4寸SPI液晶屏模块240*320TFT模块,主控芯片为ILI9341。电脑中的图片是以jpg方式保存的图片。显示图片的第一步,就是要将jpg图片转换为位图形式,一种方法是在MAX78000开发板上解码jpg图片,需要用到jepg图片解码库。我这里是在电脑上预先将jpeg图片,转换为320X240大小的bmp(位图)的格式,保存在SD卡上。
# 将jpeg图片转换为bmp图片,并限定尺寸
import os
import time
import cv2 as cv
filePath = os.path.dirname(os.path.abspath(__file__))
# 获取当前文件夹下的文件名列表
def readfilename(filepath):
names = None
try:
names = os.listdir(filepath)
except Exception as e:
print(e)
else:
return names
# 图片转换
def handleImage(filepath,names):
for name in names:
suffixs = name.split('.')
suffix = suffixs.pop()
if suffix in ['jpg']:
img = cv.imread(filepath+"//"+name)
# 调整图像大小
res = cv.resize(img, (320, 240),interpolation=cv.INTER_CUBIC)
cv.imwrite(f'{filepath}/{suffixs[0]}.bmp', res)
if __name__ == "__main__":
filelist=readfilename("g://")
print(filelist)
handleImage("g://",filelist)二、读取SD卡文件,并过滤bmp格式文件。
系统首先初始化各个硬件,然后从SD卡上读取文件,并将以“bmp”为后缀名的文件进行过滤。这里偷了个懒,SD卡中所有图片都以数字命名,从1开始,这样后边循环播放图片时,只需要简单地将文件名加一即可。首先统计出SD卡上有多少张图片。
//获取文件列表 返回获取到文件的个数
int ls_bmp(char cwd[]) {
DIR dir;
FILINFO fno;
uint8_t num=0;
if (!mounted) {
mount();
}
if ((err = f_opendir(&dir, cwd)) == FR_OK) {
while (1) {
err = f_readdir(&dir, &fno);
if (err != FR_OK || fno.fname[0] == 0) {
break;
}
printf("%s\n", fno.fname);
if(strstr(fno.fname, ".bmp")){
num++;
}
}
f_closedir(&dir);
} else {
printf("Error opening directory!\n");
return err;
}
return num;
}三、将RGB888格式数据转换为RGB565格式数据。
SD卡中读取到的bmp文件的数据,每个像素点是RGB888格式数据,即每个像素点由8X3位数据构成,分别记录红绿蓝三种颜色的信息。MAX78000开发板在TFT屏幕上显示时,使用的是RGB565格式数据,即每个像素点由8X2位数据构成,前5位为红色数据,中间6位为绿色数据,后边5位为蓝色数据。所以需要对每个点数据进行转换。
#define IMAGE_SIZE_X 320
#define IMAGE_SIZE_Y 240
uint8_t data565[IMAGE_SIZE_X * 2];
//step为传入数据中每个像素点所占字节数 3、4
void cover_rgb888_rgb565(uint8_t *data, uint8_t step) {
uint8_t r, g, b;
uint16_t rgb;
uint16_t offset = 0;
for (int i = 0; i < step * IMAGE_SIZE_X; i += step) {
if (step == 4) {
r = data[i];
g = data[i + 1];
b = data[i + 2];
}
if (step == 3) {
b = data[i];
g = data[i + 1];
r = data[i + 2];
}
rgb = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3);
data565[offset++] = (rgb >> 8) & 0xFF;
data565[offset++] = rgb & 0xFF;
}
}四、显示图片数据。
MAX78000开发板因为内存有限,与电脑处理图片不同,不能一次将整个图片文件载入内存进行处理。这里我采用每次读取一行(320个像素点)数据来进行处理,处理后在屏幕上绘制改行数据,然后继续后边一行的图片数据,如此循环,直至一张图片处理完毕。

//绘制SD卡图片到屏幕
void draw_sdimg_tft(uint8_t i) {
FIL file; //FFat File Object
FRESULT err; //FFat Result (Struct)
char filename[7];
int row = 0;
UINT bytes_read;
uint8_t imgdata[IMAGE_SIZE_X * 3] = { 0 }; //全彩图
sprintf(filename, "/%d.bmp", i);
printf("read img %s\n", filename);
if ((err = f_open(&file, filename, FA_READ)) != FR_OK) {
f_mount(NULL, "", 0);
return err;
}
// Image data begins at 0x54 跳过文件头
if ((err = f_lseek(&file, 54)) != FR_OK) {
printf("Error seeking file: %d\n", err);
f_mount(NULL, "", 0);
return err;
}
do {
// 每次读取320个像素
if ((err = f_read(&file, imgdata, IMAGE_SIZE_X * 3, &bytes_read))
!= FR_OK) {
printf("Error reading file: %d\n", err);
f_mount(NULL, "", 0);
return err;
}
cover_rgb888_rgb565(imgdata, 3); //转换rgb格式
MXC_TFT_ShowImageCameraRGB565(0, row, data565,IMAGE_SIZE_X, 1);
row++;
} while (bytes_read == IMAGE_SIZE_X * 3); // bytes_read<255 means the cursor reached EOF
if ((err = f_close(&file)) != FR_OK) {
printf("Error closing file: %d\n", err);
f_mount(NULL, "", 0);
return err;
}
}四、效果展示。
RGB565对图片还是有损失的,图片细腻程度还是有所下降。


五、源码。
我要赚赏金
