图片显示与数码相框:
图片的格式有很多种,但最常用的有不外乎这3种,即JPEG(或 JPG)、BMP 和 GIF。其中JPEG(或 JPG)和 BMP 是静态图片,而 GIF 则可实现动态图片。
(1)BMP 格式
它的全称 Bitmap,是 Window 操作系统中的标准图像文件格式,文件后缀名为“.bmp”,使用范围非常广泛。它采用的是位映射式的存储格式,除图像深度可选以外,未采用其他的压缩,因此,BMP文件所占用的空间很大,但是它不存在失真。
BMP 文件的图像深度可选1bit、4bit、8bit、16bit、24bit 及 32bit,BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。
(2)JPEG格式
它是 Joint Photographic Experts Group(联合图像专家组)的缩写,文件后辍名为“.jpg”或“.jpeg”,是最常用的图像文件格式,是由一个软件开发联合会组织所制定。同 BMP 格式不同,JPEG 是一种有损压缩格式,能将图像压缩在一个很小的储存空间,图像中重复或不重要的资料会被丢去,因而容易造成图像数据的损伤(BMP 不会,但是 BMP 占用空间大)。尤其是在使用过高压缩比例的情况下,将使最终解压缩后所恢复的图像质量明显降低。如果追求高品质图像,不宜采用过高压缩比例的方式。但是 JPEG 压缩技术很先进,它以有损压缩的方式去除了冗余的图像数据,在获得极高压缩率的同时,能展现十分丰富且生动的图像。换句话说,就是它可以用最少的磁盘空间得到较好的图像品质。此外,JPEG 也是一种很灵活的格式,具有调节图像质量的功能,允许用不同的压缩比对文件进行压缩,支持多种压缩级别,压缩比率通常在 10:1 到 40:1 之间,压缩比越大,品质就越低;相反地,压缩比越小,品质就越好。
(3)GIF
它是Graphics Interchange Format的缩写,是 CompuServe 公司开发的一种图像文件存储格式,1987 年开发的 GIF 文件格式版本号是 GIF87a,1989 年进行了扩充,扩充后的版本号定义为 GIF89a。
GIF 图像文件以数据块(block)为单位来存储图像的相关信息。一个 GIF 文件由表示图形/图像的数据块、数据子块以及显示图形/图像的控制信息块组成,称为 GIF 数据流(DataStream)。数据流中的所有控制信息块和数据块都必须在文件头(Header)和文件结束块(Trailer)之间。
GIF 文件格式采用了 LZW(Lempel-ZivWalch)压缩算法来存储图像数据,定义了允许用户为图像设置背景的透明(transparency)属性。此外,GIF 文件格式可在一个文件中存放多幅彩色图形/图像。如果在 GIF 文件中存放了多幅图,则它们可以像演幻灯片那样显示或者像动画那样演示。
STM32H7R3开发板所配置的图片显示主程序为:
int main(void)
{
uint8_t t = 0;
uint8_t key;
uint8_t res;
DIR picdir;
uint16_t totpicnum;
FILINFO *picfileinfo;
char *pname;
uint32_t *picoffsettbl;
uint16_t curindex;
uint16_t temp;
sys_mpu_config();
sys_cache_enable();
HAL_Init();
sys_stm32_clock_init(300, 6, 2);
delay_init(600);
usart_init(115200);
led_init();
key_init();
hyperram_init();
lcd_init();
my_mem_init(SRAMIN);
my_mem_init(SRAMEX);
my_mem_init(SRAM12);
my_mem_init(SRAMDTCM);
my_mem_init(SRAMITCM);
exfuns_init();
f_mount(fs[0], "0:", 1);
f_mount(fs[1], "1:", 1);
f_mount(fs[2], "2:", 1);
while (fonts_init() != 0)
{
lcd_show_string(30, 30, 200, 16, 16, "STM32", RED);
while (sd_init() != 0)
{
lcd_show_string(30, 30, 200, 16, 16, "SD Card Error!", RED);
delay_ms(500);
lcd_show_string(30, 30, 200, 16, 16, "Please Check! ", RED);
delay_ms(500);
LED0_TOGGLE();
}
lcd_show_string(30, 50, 200, 16, 16, "SD Card OK", RED);
lcd_show_string(30, 70, 200, 16, 16, "Font Updating...", RED);
res = fonts_update_font(30, 90, 16, (uint8_t *)"0:", RED);
while (res != 0)
{
lcd_show_string(30, 90, 200, 16, 16, "Font Update Failed!", RED);
delay_ms(200);
lcd_show_string(30, 90, 200, 16, 16, "Please Check! ", RED);
delay_ms(200);
}
lcd_show_string(30, 90, 200, 16, 16, "Font Update Success! ", RED);
delay_ms(1500);
lcd_clear(WHITE);
}
text_show_string(30, 30, 200, 16, "正点原子STM32开发板", 16, 0, RED);
text_show_string(30, 50, 200, 16, "图片显示实验", 16, 0, RED);
text_show_string(30, 70, 200, 16, "ATOM@ALIENTEK", 16, 0, RED);
text_show_string(30, 90, 200, 16, "WKUP: PREV", 16, 0, RED);
text_show_string(30, 110, 200, 16, "KEY0: NEXT", 16, 0, RED);
while (f_opendir(&picdir, "0:/PICTURE") != FR_OK)
{
text_show_string(30, 130, 200, 16, "PICTURE文件夹错误!", 16, 0, RED);
delay_ms(200);
lcd_fill(30, 130, 200, 16, WHITE);
delay_ms(200);
}
totpicnum = pic_get_tnum("0:/PICTURE");
while (totpicnum == 0)
{
text_show_string(30, 130, 200, 16, "没有图片文件!", 16, 0, RED);
delay_ms(200);
lcd_fill(30, 130, 200, 16, WHITE);
delay_ms(200);
}
picfileinfo = (FILINFO *)mymalloc(SRAMIN, sizeof(FILINFO));
pname = (char *)mymalloc(SRAMIN, FF_MAX_LFN * 2 + 1);
picoffsettbl = (uint32_t *)mymalloc(SRAMIN, 4 * totpicnum);
while ((picfileinfo == NULL) || (pname == NULL) || (picoffsettbl == NULL))
{
text_show_string(30, 130, 200, 16, "内存分配失败!", 16, 0, RED);
delay_ms(200);
lcd_fill(30, 130, 200, 16, WHITE);
delay_ms(200);
}
res = (uint8_t)f_opendir(&picdir, "0:/PICTURE");
if (res == 0)
{
curindex = 0;
while (1)
{
temp = picdir.dptr;
res = (uint8_t)f_readdir(&picdir, picfileinfo);
if ((res != 0) || (picfileinfo->fname[0] == 0))
{
break;
}
res = exfuns_file_type(picfileinfo->fname);
if ((res & 0xF0) == 0x50)
{
picoffsettbl[curindex] = temp;
curindex++;
}
}
}
text_show_string(30, 130, 200, 16, "开始显示...", 16, 0, RED);
delay_ms(1500);
piclib_init();
curindex = 0;
res = (uint8_t)f_opendir(&picdir, (const TCHAR *)"0:/PICTURE");
while (res == 0)
{
dir_sdi(&picdir, picoffsettbl[curindex]);
res = (uint8_t)f_readdir(&picdir, picfileinfo);
if ((res != 0) || (picfileinfo->fname[0] == 0))
{
break;
}
strcpy((char *)pname, "0:/PICTURE/");
strcat((char *)pname, (const char *)picfileinfo->fname);
lcd_clear(BLACK);
piclib_ai_load_picfile(pname, 0, 0, lcddev.width, lcddev.height, 1);
text_show_string(2, 2, lcddev.width, 16, (char *)pname, 16, 1, RED);
while (1)
{
key = key_scan(0);
if (key == KEY0_PRES)
{
if (curindex != 0)
{
curindex--;
}
else
{
curindex = totpicnum - 1;
}
break;
}
else if (key == WKUP_PRES)
{
curindex++;
if (curindex >= totpicnum)
{
curindex = 0;
}
break;
}
if (++t == 20)
{
t = 0;
LED0_TOGGLE();
}
delay_ms(10);
}
}
myfree(SRAMIN, picfileinfo);
myfree(SRAMIN, pname);
myfree(SRAMIN, picoffsettbl);
while (1);
}
值得指出的是,该程序并不是一个单纯显示图片的程序,它是建立在基于U盘的文件管理系统之上,当把存有.bmp、.jpg及.gif这3种格式的图片文件的U盘插入开发板的卡槽后,它能在按键的配合下实现自主的浏览,即起到了数码相册的作用。
经程序的编译与下载,其显示效果如图1和图2所示。此外,可使用 WKUP 和 KEY0 键进行上一张或下一张图片的快速切换。

图1 显示bmp图片

图2 显示jpg图片