通信原理课设(gec6818) 003:LCD显示bmp
1、BMP
普通文件一般分为两种
文本文件:按照ASCII码去解析的文件(.txt .c .h .cpp .hpp.....)
二进制文件:存储二进制,直接通过ASCII去解析出现的就乱码,必须通过程序的开发者发布的格式去完成这个解析格式,必须要按照这个规则走你才能解析出这个文件( .mp3 .mp4 .jpg .bmp......)
图片文件分为很多种格式:
无压缩的:以bmp为代表,每一个像素点都完整的保存下来。
有压缩的:jpeg为代表,将它的数据进行压缩,用更小的存储空间表示更多的内容。
以下就是BMP文件的格式:
2、练习
在屏幕上面循环刷新图片注意:各种不同的像素都要能刷新,并且将其居中,图片没有覆盖到的地方用一个什么颜色的底色去补齐。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <math.h>
int lcd_fd = -1; // Global LCD file descriptor
unsigned int *plcd = NULL; // Global mapping base address
void LcdInit(void) {
lcd_fd = open("/dev/fb0", O_RDWR);
if (-1 == lcd_fd) {
perror("open fb0 error");
exit(1);
}
plcd = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
if (MAP_FAILED == plcd) {
perror("mmap lcd error");
exit(2);
}
}
void LcdDestory(void) {
munmap(plcd, 800 * 480 * 4);
close(lcd_fd);
}
//绘制一个点
void Display(int x, int y, unsigned int color) {
if (x >= 0 && x < 800 && y >= 0 && y < 480) {
*(plcd + y * 800 + x) = color;
}
}
//绘制一个方块
void Displaysql(int w, int h, int x0, int y0, unsigned int color) {
int x, y;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
Display(x + x0, y + y0, color);
}
}
}
//居中显示
void DisplayBmpPic(const char* pic)
{
//1、打开文件
int fd = open(pic , O_RDONLY);
if( fd == -1)
{
perror("open bmp error");
return;
}
//2、判断这个文件是不是真的bmp图片
//暂时省略
//读取bmp文件头相关信息:
int width,height,depth=0;
//读取宽度、高度
lseek(fd,0x12,SEEK_SET);
read(fd,&width,4);
read(fd,&height,4); //高度和宽度连在一起
//读取色深
lseek(fd,0x1c,SEEK_SET);
read(fd,&depth,2);
printf("width= %d height= %d depth= %d\n",width,height,depth);
//为了凑4的倍数,需要在每一行的后面加1/2/3/0个字节
int n =(4 - width * (depth / 8) % 4) % 4;
//计算像素数组 w*h*(depth/8) 由于数组较大,故采用动态内存分配
unsigned char *coclorbuf = malloc((width*(depth/8)+n)*height);
//读取像素数组,偏移过头部
lseek(fd,0x36,SEEK_SET);
read(fd,coclorbuf,(width*(depth/8)+n)*height);
//拿到每一个像素点的rgb
unsigned char c_a,c_r,c_g,c_b;
unsigned int color;
int i=0;//coclorbuf的下标
int x=400-(width/2),y=240+(height/2);//坐标
for(y=240+(height/2)-1 ; y>=240-(height/2) ; y--)//列
{
for(x=400-(width/2) ; x<width+400-(width/2) ; x++)//行
{
c_b = coclorbuf[i++];
c_g = coclorbuf[i++];
c_r = coclorbuf[i++];
if( 32 == depth) // 32/8=4 说明存储的是argb
{
c_a = coclorbuf[i++];
}
color = c_a<<24 | c_r<<16 | c_g<<8 | c_b;
Display(x,y,color);
}
i += n;//每走完一行都要跳过后面补的没用的n个字节
}
//释放动态分配内存 free只能释放动态内存空间
free(coclorbuf);
//3、关闭文件
close(fd);
}
int main() {
LcdInit();
//显示白色
Displaysql(800, 480, 0, 0, 0xffffff);
//显示图片
DisplayBmpPic("1.bmp");
LcdDestory();
return 0;
}