模拟智能家居项目Part6

来自于两周的粤嵌实习,主要是网络编程和线程控制部分比较重要,贯穿了常用的C语言用法,值得做一个复盘,共有11个部分,本节介绍了图片的显示。

Posted by LJJ on July 2, 2020

模拟智能家居项目

基本原理

  • 什么是bmp格式的图片?

    • bmp类型的图片是windows下最常见、最基本的图片类型是没有经过任何算法压缩的,所以它所占内存一般比较 大
  • 大小端模式
    • 小端模式:低地址存低字节,高地址存高字节
    • 大端模式:低地址存高字节,高地址存低字节
  • 使用函数介绍

       read函数
       1.1头文件
       #include <unistd.h>
       1.2函数原型
       ssize_t read(int fd, void *buf, size_t count);
       1.3函数的功能
       就是将fd所代表的文件中的内容读取count个字节数据到buf所指向的区域中
       1.4函数的参数
       int fd			//代表你要读取的文件
       void *buf		//代表你要将读取的数据存储到空间中的首地址
       size_t count	//代表你要从文件中读取的字节数	
       1.5函数的返回值
       成功:返回你读取到的字节数
       失败:返回-1
    

任务要求

  • 将一张bmp格式的图片,图片的分辨率为(800480),显示到模拟屏上

  • 实现步骤

    1.制作一张分辨率为800*480的bmp格式的图片
    2.将这个图片文件放到一个目录下面(最好放到程序的working_dir,执行程序的目录)./test.bmp
    3.打开图片文件
    4.从图片文件中读取数据到buf所指向的空间(buf所指向的空间是你自己定义的空间)
    5.r g b  -》 a r  g  b  将读取到的数据转换成开发板上32位色深的格式
    6.将转换以后的数据写入到帧缓冲设备文件中去
    

代码实现

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int *p = NULL;

void draw_point(int x, int y, int color)
{	
	if(x >= 0 && x < 800 && y >=0 && y < 480)
	{
		*(p + x + y * 800) = color;
	}
}

//显示图片

void show_bmp(char *path, int x, int y)
{
	//3.打开图片文件
	int picture_fd = open(path,O_RDWR);
	if(picture_fd < 0)
	{
		perror("open picture_fd error\n");
	}
	//4.从图片文件的头获取图片文件的信息
		//从文件的头获取像素点的宽度
	int locat = lseek(picture_fd,0x12,SEEK_SET);
	if(locat == -1)
	{
		perror("lseek picture_fd error\n");
	}
	printf("location is %d\n",locat);
	int wide = 0; //保存像素点宽度
	int ret = read(picture_fd, &wide,4);
	if(ret == -1)
	{
		perror("read picture_fd error\n");
	}
	printf("read's byte is %d\n", ret);
	printf("picture's wide is %d\n", wide);
	
	//从文件的头获取像素点的高度
	locat = lseek(picture_fd,0x16,SEEK_SET);
	if(locat == -1)
	{
		perror("lseek picture_fd error\n");
	}
	printf("location is %d\n",locat);
	int height = 0; //保存像素点的高度
	ret = read(picture_fd, &height,4);
	if(ret == -1)
	{
		perror("read picture_fd error\n");
	}
	printf("read's byte is %d\n", ret);
	printf("picture's height is %d\n", height);
	
	//从文件的头获取像素点的色深
	locat = lseek(picture_fd,0x1C,SEEK_SET);
	if(locat == -1)
	{
		perror("lseek picture_fd error\n");
	}
	printf("location is %d\n",locat);
	short int colordeep = 0; //保存像素点的色深
	ret = read(picture_fd, &colordeep,2);
	if(ret == -1)
	{
		perror("read picture_fd error\n");
	}
	printf("read's byte is %d\n", ret);
	printf("picture's colordeep is %d\n", colordeep);
	
	int perlinebyte = 0; 	//每行的实际字节数
	int laizi = 0; 			//表示每行补的字节数
	if(wide * colordeep /8 % 4 != 0)
	{
		perlinebyte = wide * colordeep / 8 + 4 - (wide * colordeep /8 % 4 );
		laizi = 4 - (wide * colordeep /8 % 4 );
	}
	else
	{
		perlinebyte = wide * colordeep / 8;
		laizi = 0;
	}
	
	printf("laizi is %d\n",laizi);
	//5.从图片文件中读取数据到buf所指向的空间(buf所指向的空间是你自己定义的空间)
		//略过文件的头54个字节
	locat = lseek(picture_fd, 54, SEEK_SET);
	if(locat == -1)
	{
		perror("lseek picture_fd error\n");
	}
	printf("location is %d\n",locat);	
		//从图片文件中读取数据
	unsigned char buf[800*480*3] = {0};
	ret = read(picture_fd, buf,perlinebyte * height);
	if(ret == -1)
	{
		perror("read picture_fd error\n");
	}
	printf("read's yanse byte is %d\n", ret);

	//5.r g b  -》 a  r  g  b  将读取到的数据转换成开发板上32位色深的格式
	unsigned char a = 0; 
	int color = 0;
	int num = 0;
				 // buf[0]   b
				 // buf[1]   g     int
				 // buf[2]   r
	int i,j;
	
	for(i = 0; i < height; i++)	//行
	{
		for(j = 0; j < wide; j++) //列
		{	
			//将读取到的数据转换成开发板上32位色深的格式
			color  = a << 24 | buf[2 + num] << 16 |  buf[1 + num] << 8 | buf[0 + num];      //第0个像素点
							//  buf[5]		   buf[4]		 buf[3]	  	  //..1........
							// 8				7				6	      //..2........
							// 11				10				9
			//6.将转换以后的数据写入到帧缓冲设备文件中去
			draw_point(x + j, y + height - 1 - i, color);
			num = num + 3;			
		}
		num = num + laizi;
	}
	
	//关闭图片文件
		close(picture_fd);
	
}





int main()
{
	//1.打开帧缓冲设备文件
	int lcd_fd = open("/dev/ubuntu_lcd",O_RDWR);
	if(lcd_fd < 0)
	{
		perror("open lcd_fd error\n");
	}
	//2.映射 
	p = mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
	if(p == MAP_FAILED)
	{
		perror("mmap error\n");
	}
	//图片显示模块代码
	show_bmp("./test.bmp",0,0);
	show_bmp("./www.bmp",200,150);	
	//7.收尾工作
		//解映射
		munmap(p, 800*480*4);
		//关闭帧缓冲设备文件(关闭显示屏)
		close(lcd_fd);
	return 0;
}