1.什么是BMP图片
1.1bmp概念
- BMP是英文Bitmap(位图)的简写,它是(Windows操作系统)中的标准(图像文件格式),能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP(位图)格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱生来的缺点--占用(磁盘)空间过大。所以,目前BMP在单机上比较流行。
- bmp图片像素排列方式为BGR
- bmp文件的图像深度可选1bit、4bit、8bit、24bit。bmp格式图片的扫描方式为从左到右,从上到下
- 使用bmp格式图片优点是可以很方便的得到图片像素数据,而jpg/jpeg格式需要先解压图像数据之后才可得到像素数据
- 本平台在显示图片时选择24位位图格式
- bmp图片前54字节不是图片数据,而是保存图片信息,例如图片名称,尺寸等
- 所以一张bmp图片大小为800*480*3+54=1152054字节,没有透明度选项
- 更多详细信息
1.2制作bmp图片
- 首先下载图片,使用win自带的画图软件打开
- 设置图片大小为800*480
- 另存为bmp格式图片
- 查看图片信息,可看到图片大小为1152054字节
1.3将bmp图片整到开发板上
- 按照传统代码烧写方法,通过SecureCRT将bmp图片传输到开发板上,理论可行,然现实却需要等待若干小时。因为串口波特率为115200,即115200bit/s=112.5Byte/s=0.1kB/s,一张bmp图片大小在1M左右,可看出传输时间会非常慢
- 鉴于以上原因,可通过U盘将图片传输到开发板上。前提是开发板已经安装好对应USB驱动
- 将事先准备好的bmp图片拷贝到U盘上,再将U盘插到开发板上,可看到有以下信息,证明有USB设备插入且成果识别USB设备信息
[root@GEC6818 /IOT/home]#[ 1981.712000] usb 1-1.2: new high-speed USB device number 3 using nxp-ehci
[ 1981.789000] usb 1-1.2: New USB device found, idVendor=048d, idProduct=1234
[ 1981.790000] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1981.798000] usb 1-1.2: Product: UDisk
[ 1981.802000] usb 1-1.2: Manufacturer: General
[ 1981.806000] usb 1-1.2: SerialNumber: Љ
[ 1981.813000] scsi0 : usb-storage 1-1.2:1.0
[ 1982.819000] scsi 0:0:0:0: Direct-Access General UDisk 5.00 PQ: 0 ANSI: 2
[ 1982.825000] sd 0:0:0:0: [sda] 32768000 512-byte logical blocks: (16.7 GB/15.6 GiB)
[ 1982.827000] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 1982.835000] sd 0:0:0:0: [sda] Write Protect is off
[ 1982.840000] sd 0:0:0:0: [sda] No Caching mode page present
[ 1982.844000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 1982.855000] sd 0:0:0:0: [sda] No Caching mode page present
[ 1982.856000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 1982.863000] sda:
[ 1982.868000] sd 0:0:0:0: [sda] No Caching mode page present
[ 1982.870000] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 1982.875000] sd 0:0:0:0: [sda] Attached SCSI removable disk
[root@GEC6818 /IOT/home]#cd /mnt/
[root@GEC6818 /mnt]#ls
sd udisk
[root@GEC6818 /mnt]#
[root@GEC6818 /mnt]#ls -l sd
total 0
[root@GEC6818 /mnt]#ls -l udisk/
total 0
[root@GEC6818 /mnt]#
# 创建挂载文件夹
[root@GEC6818 /mnt]#mkdir usb
[root@GEC6818 /mnt]#ls
sd udisk usb
# 挂载U盘,将dev目录下的设备文件sda映射到刚刚创建的usb文件夹下
[root@GEC6818 /mnt]#mount /dev/sda /mnt/usb/
# 此处进入usb文件下面,就可看到U盘内文件了
[root@GEC6818 /mnt]#cd usb/
[root@GEC6818 /mnt/usb]#ls
1.bmp
2.bmp
201730133027
3.bmp
????.pdf
????2020
?????
???????.pdf
????????.doc
??????????.docx
??Arduino.pdf
AT89C51 ?????????????
Alarms
Android
Bandicam???
Chinatelecom_JSPortal
DCIM
Download
EasyX_2018???.exe
Fritzing0.9.3b.dmg
LOST.DIR
Movies
Music
Notifications
Pictures
Podcasts
Processing.app
RavV17std.exe
Ringtones
System Volume Information
Wireless LAN_Atheros_12.0.0.191_W10x64_A.zip
[Beginning.Arduino].Michael.McRoberts.???.pdf
arduino-1.8.7-macosx.zip
arduino??????.pdf
hq.txt
liz.txt
processing-3.4-macosx.zip
processing-3.4-windows64.zip
record
video
[root@GEC6818 /mnt/usb]#
- 最终通过
cp
指令就可随心所欲地copy了哈
- 取消挂载指令为
umount /mnt/usb
,类似win上的弹出U盘
2.屏幕适配bmp图片
2.1适配方法
- 由于bmp图片像素排列方式不为RGB,所以需要我们通过移位操作完成像素重新排列的操作
- LCD屏像素排列为ARGB,bmp图片像素排列为BGR
- 针对一个像素点,可通过移位操作将bmp像素排列改为LCD屏像素排列
/*bmp格式*/
B G R
/*LCD排列*/
A R G B
/*bmp--->LCD*/
(R<<16)|(G<<8)|(B)
2.2示例代码
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
/*全局变量,保存内存映射后的地址*/
int *p = NULL;
/*全局变量,保存驱动文件设备描述符*/
int fd;
/*二维数组,保存图片名称*/
char pic[3][10] = {"1.bmp", "2.bmp", "3.bmp"};
/*LCD屏幕初始化,即进行打开显示驱动文件、内存映射等工作*/
int lcd_init(void)
{
fd = open("/dev/fb0", O_RDWR);
if(fd == -1)
{
printf("open file error\n");
return -1;
}
/*内存映射*/
p = mmap(NULL, 800 * 480 * 4, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
if(p == NULL)
{
printf("mmap error\n");
close(fd);
return -1;
}
return 0;
}
/*描绘像素点,即告诉每个像素点对应该显示的色域值*/
void lcd_draw_point(int x, int y, int color)
{
*(p + y * 800 + x) = color;
}
/*将图片从bmp格式转换为LCD屏的显示格式,操作单位是像素点*/
int lcd_draw_bmp(char *pic_name)
{
/*打开bmp图片文件*/
int pic_fd = open(pic_name, O_RDWR);
/*给每张图片申请缓存地址,注意申请大小*/
char pic_buff[800 * 480 * 3] = {0};
/*保存R、G、B像素值,单位是1字节*/
char red, green, blue;
int color;
int p = 0;
if(pic_fd < 0)
{
printf("open picture error\n");
return -1;
}
/*根据bmp格式,应该跳过前54字节的内容*/
lseek(pic_fd, 54, SEEK_SET);
/*将bmp图片中的像素内容写入缓存区*/
read(pic_fd, pic_buff, 800 * 480 * 3);
/*像素点移位,适配LCD屏幕格式*/
for(int i = 0; i < 480; i++)
{
for(int j = 0; j < 800; j++)
{
/*读bmp像素点中的B色域*/
blue = pic_buff[p++];
/*读bmp像素点中的G色域*/
green = pic_buff[p++];
/*读bmp像素点中的R色域*/
red = pic_buff[p++];
/*移位操作将BGR转RGB,将转换后结果保存到color(4字节)中间变量中*/
color = (blue) | (green<<8) | (red<<16);
/*将移动好的像素值写入对应位置*/
//lcd_draw_point(j, i, color);//BUG版本,此举图像将按照镜面方式显示
lcd_draw_point(j, 479 - i, color);//修复版本,更改刷新方式为从左到右,从下往上
}
}
close(pic_fd);
}
int main()
{
if(lcd_init() != 0)
{
printf("lcd init error\n");
close(fd);
return -1;
}
while (1)
{
/*循环显示3张图片*/
for(int i = 0; i < 3; i++)
{
lcd_draw_bmp(pic[i]);
sleep(1);
}
}
/*解除映射*/
munmap(p, 800 * 480 * 4);
/*指针置空,防止野指针出现*/
p = NULL;
return 0;
}