练习: 完成一张图片在板子上的显示
要求: 任意路径的图片
任意大小的图片
在板子上的任意位置显示
void show_bmp (char * pathname , int x,int y)
{
第一步:打开图片 ,读取宽度 高度 色深
第二步: 确定总字节数 然后malloc对应大小的内来保存这些颜色。unsigned char * p = malloc(total_bytes);
//第三步: 打开帧缓冲设备 映射 init(); end();
第四步: 把颜色的值写进去 要一个字节一个字节地写入 为什么呢?
因为32位和24位地A是不一样的。
unsigned char a,r,g,b ;
我们把前面保存的像素数组的对应内容 一个一个字节地给我的argb 。
24位的像素数组只有RGB a直接给0
32位的像素数组有a 需要给一个字节给a
每写完四个字节 写完一个argb 。 这四个字节是不是就是组成一个color ?
这个时候是不是就该调用我们draw_point函数。
注意: 每行跳过癞子。
第五步: 关闭图片 //关闭帧缓冲 解除映射
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <math.h>
#include <stdlib.h>
int * p = NULL ;
void draw_point(int x,int y,int color)
{
if(x>=0 && x<800 && y>=0 && y<480 )
{
*(p+800*y+x) = color ;
}
}
/*
函数功能:在屏幕的任意一个位置 显示任意一张 任意大小的bmp图片
函数参数:
@pathname : 要显示的图片 的路径名
@x : 在屏幕X轴值为x的地方开始显示
@y : 在屏幕Y轴值为y的地方开始显示
*/
void show_bmp (char * pathname ,int x ,int y)
{
int fd = open(pathname,O_RDONLY);
if(fd == -1)
{
perror("open error\n");
return ;
}
int fd1 = open("/dev/fb0",O_RDWR);
if(fd1 == -1)
{
perror("open error\n");
return ;
}
printf("open success\n");
p = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED ,fd1,0);
if(p == NULL )
{
perror("mmap error\n");
return ;
}
int width,height;
short depth;
unsigned char buf[4] ;
//读取宽度
lseek(fd,0x12,SEEK_SET);
read(fd,buf,4);
width = buf[3]<<24 | buf[2]<< 16 | buf[1] << 8 | buf[0];
//读取高度
read(fd,buf,4);
height = buf[3]<<24 | buf[2]<< 16 | buf[1] << 8 | buf[0];
//读取色深
lseek(fd,0x1c,SEEK_SET);
read(fd,buf,2);
depth = buf[1] << 8 | buf[0];
//打印信息
printf("width = %d height = %d depth = %d \n",width,height,depth);
//像素数组
int line_valid_bytes = abs(width) * depth / 8 ; //一行本有的有效字节
int laizi=0;//填充字节
if( (line_valid_bytes % 4) !=0 )
{
laizi = 4 - line_valid_bytes%4;
}
int line_bytes = line_valid_bytes + laizi ;//一行所有的字节数
int total_bytes = line_bytes * abs(height) ; //整个像素数组的大小
unsigned char * p1 = malloc(total_bytes);
lseek(fd,54,SEEK_SET);
read(fd,p1,total_bytes);
//调用draw_point 函数 。
unsigned char a ,r ,g, b ;
int i = 0;//用来做指针运动的
int x0=0,y0=0; //用来循环计数
int color ;
for(y0=0;y0<abs(height);y0++)//画满每一列
{
for(x0=0;x0<abs(width);x0++)//画满每一行
{
//现在开始一个字节一个字节写入颜色
// i++ 先用后加
// ++i 先加后用
b = p1[i++];
g = p1[i++];
r = p1[i++];
if(depth == 32)
{
a=p1[i++];
}
if(depth == 24)
{
a = 0;
}
color = a << 24 | r << 16 | g << 8 | b ;
draw_point(width>0?x+x0:abs(width)+x-1-x0,
height>0? y+height-1-y0 : y+y0,color);
}
i = i +laizi ;//每一行后面的癞子数 跳过去。
}
free(p1);
close(fd1);
munmap(p,800*480*4);
close(fd);
}
int main()
{
show_bmp("1.bmp",-100 ,-100);
//show_bmp("3.bmp",0,0);
return 0;
}
int fd = open(pathname,O_RDONLY);
if(fd == -1)
{
perror("open error\n");
return ;
}
int fd1 = open("/dev/fb0",O_RDWR);
if(fd1 == -1)
{
perror("open error\n");
return ;
}
printf("open success\n");
p = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED ,fd1,0);
if(p == NULL )
{
perror("mmap error\n");
return ;
}
int width,height;
short depth;
unsigned char buf[4] ;
//读取宽度
lseek(fd,0x12,SEEK_SET);
read(fd,buf,4);
width = buf[3]<<24 | buf[2]<< 16 | buf[1] << 8 | buf[0];
//读取高度
read(fd,buf,4);
height = buf[3]<<24 | buf[2]<< 16 | buf[1] << 8 | buf[0];
//读取色深
lseek(fd,0x1c,SEEK_SET);
read(fd,buf,2);
depth = buf[1] << 8 | buf[0];
//打印信息
printf("width = %d height = %d depth = %d \n",width,height,depth);
- BMP图片的显示 :
bmp:bit map picture 位图
bmp文件格式的图片, 没有经过任何压缩技术生成的图片。
无压缩:保存了图片的每一个像素点的rgb颜色分量的值。
我们按照bmp图片文件的固定的内容格式将他的数据读出来,进行一些简单的操作。我们就可以完成这个图片的显示。
BMP图片文件格式:
头两个字节 BM 我们是自己用BMP图片 所以就不用判定。
宽度: 一行有多少个像素点:
偏移量:0x12
大小: 4个字节
可正可负
正负只表示一行像素点的存储方式
为正说明行像素点是从左到右排列
为负说明行像素点是从右往左排列
高度: 一列有多少个像素点
偏移量:0X16
大小 : 4个字节
可正可负
正负只表示一列像素点的存储方式
为正说明行像素点是从下到上排列
为负说明行像素点是从上往下排列
色深: 每个像素所占的位数 bit
怎么求每个像素的大小?字节
色深/8
24
32
偏移量:0x1c
大小: 2个字节
小端模式和大端模式
小端模式: 存储器(内存)的低地址 存放 寄存器(数据)的低地址字节
大端模式: 存储器(内存)的低地址 存放 寄存器(数据)的高地址字节
两者的区别就是 高字节位、低字节位存放次序不同;小端先存低,大端先存高,大端模式用于比较高端的场景,处理速度快。
获取图片的宽度 高度 色深信息。
思路:
int width,height;
short depth;
unsigned char buf[4];
第一步: 打开图片 open("./1.bmp")
第二步: lseek 偏移对应偏移量大小
read 读取对应数据大小的内容
。。。。。
第三步: 关闭图片
buf[4]
buf[0] buf[1] buf[2] buf[3]
我们真正想要的正确的数据是多少
buf[3] buf[2] buf[1] buf[0]
buf[0] buf[1] buf[2] buf[3] ---> buf[3] buf[2] buf[1] buf[0]
buf[3] << 24 buf[3] _______ ________ _________
buf[2] << 16 _________ buf[2] __________ ___________
buf[1] << 8 __________ _______ buf[1] ____________
buf[0] _________ _________ ________ buf[0]
width = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]
//像素数组
int line_valid_bytes = abs(width) * depth / 8 ; //一行本有的有效字节
int laizi=0;//填充字节
if( (line_valid_bytes % 4) !=0 )
{
laizi = 4 - line_valid_bytes%4;
}
int line_bytes = line_valid_bytes + laizi ;//一行所有的字节数
int total_bytes = line_bytes * abs(height) ; //整个像素数组的大小
unsigned char * p1 = malloc(total_bytes);
像素数组: 保存了图片像素点的所有argb颜色分量的值
偏移量: 54
大小: ???
大小需要根据宽度和高度和色深来求 。
格式规定图片每行的字节数为4字节的倍数
大小: 图片的宽度的绝对值 * 图片的高度的绝对值 * 色深/ 8
if(depth == 32)
{
(图片的宽度的绝对值 * 32/ 8) % 4 一定为0 ;
}
if(depth == 24 )
{
(图片的宽度的绝对值 * 24 / 8) % 4 不一定为 0 ;
}
是不是我们24位的图片就需要填充若干个字节 来满足每行大小为4字节倍数要求
这些填充的字节数 我们叫癞子。
那我们怎么求出每行的填充的字节数呢?癞子?
int laizi;
if ( ( 宽度*色深/8 ) %4 !=0 )
{
laizi = 4 - 宽度*色深/8 ) %4 ;
}
我真正意义上一行的字节数 是多少? line_bytes = ( 宽度*色深/8 ) %4 + laizi ;
总共的字节数呢? total_bytes = line_bytes * height
unsigned char * p = malloc(total_bytes);
void draw_point(int x,int y,int color)
{
if(x>=0 && x<800 && y>=0 && y<480 )
{
*(p+800*y+x) = color ;
}
}
lseek(fd,54,SEEK_SET);
read(fd,p1,total_bytes);
//调用draw_point 函数 。
unsigned char a ,r ,g, b ;
int i = 0;//用来做指针运动的
int x0=0,y0=0; //用来循环计数
int color ;
for(y0=0;y0<abs(height);y0++)//画满每一列
{
for(x0=0;x0<abs(width);x0++)//画满每一行
{
//现在开始一个字节一个字节写入颜色
// i++ 先用后加
// ++i 先加后用
b = p1[i++];
g = p1[i++];
r = p1[i++];
if(depth == 32)
{
a=p1[i++];
}
if(depth == 24)
{
a = 0;
}
color = a << 24 | r << 16 | g << 8 | b ;
draw_point(width>0?x+x0:abs(width)+x-1-x0,
height>0? y+height-1-y0 : y+y0,color);
}
i = i +laizi ;//每一行后面的癞子数 跳过去。
}
模块化思想:
。。。
只有一个唯一的main函数‘
一个或者多个功能函数
main.c
lcd.c lcd.h
bmp.c bmp.h
led.c led.h
beef.c beef.h
.....
.h怎么写?
例:led.h
#ifndef __LED_H__
#define __LED_H__
// 变量的定义
// 函数的声明
//。。。
#endif
功能函数: 封装一个函数
/*
功能函数:对一个坐标点为(x,y)的像素点上色。
参数:
@x : 像素点的X轴坐标值
@y :像素点的Y轴坐标值
@color : 要画的颜色
*/
void draw_point ( int x, int y, int color )
{
if(x>=0 && x<800 && y>=0 && y<480)
*(p + 800*y +x ) = 0x00ff0000 ;//p定义成全局变量
}
BMP图片的显示 :
bmp:bit map picture 位图
bmp文件格式的图片, 没有经过任何压缩技术生成的图片。
无压缩:保存了图片的每一个像素点的rgb颜色分量的值。
我们按照bmp图片文件的固定的内容格式将他的数据读出来,进行一些简单的操作。我们就可以完成这个图片的显示。
BMP图片文件格式
见图:
头两个字节 BM 我们是自己用BMP图片 所以就不用判定。
宽度: 一行有多少个像素点:
偏移量:0x12
大小: 4个字节
可正可负
正负只表示一行像素点的存储方式
为正说明行像素点是从左到右排列
为负说明行像素点是从右往左排列
高度: 一列有多少个像素点
偏移量:0X16
大小 : 4个字节
可正可负
正负只表示一列像素点的存储方式
为正说明行像素点是从下到上排列
为负说明行像素点是从上往下排列
色深: 每个像素所占的位数 bit
怎么求每个像素的大小?字节
色深/8
24
32
偏移量:0x1c
大小: 2个字节
小端模式和大端模式
小端模式: 存储器(内存)的低地址 存放 寄存器(数据)的低地址字节
大端模式: 存储器(内存)的低地址 存放 寄存器(数据)的高地址字节
练习: 获取图片的宽度 高度 色深信息。
思路:
int width,height;
short depth;
unsigned char buf[4];
第一步: 打开图片 open("./1.bmp")
第二步: lseek 偏移对应偏移量大小
read 读取对应数据大小的内容
。。。。。
第三步: 关闭图片
buf[4]
buf[0] buf[1] buf[2] buf[3]
我们真正想要的正确的数据是多少
buf[3] buf[2] buf[1] buf[0]
buf[0] buf[1] buf[2] buf[3] ---> buf[3] buf[2] buf[1] buf[0]
buf[3] << 24 buf[3] _______ ________ _________
buf[2] << 16 _________ buf[2] __________ ___________
buf[1] << 8 __________ _______ buf[1] ____________
buf[0] _________ _________ ________ buf[0]
width = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]
同样的方法求高度 色深...
见code :
像素数组: 保存了图片像素点的所有argb颜色分量的值
偏移量: 54
大小: ???
大小需要根据宽度和高度和色深来求 。
大小: 图片的宽度的绝对值 * 图片的高度的绝对值 * 色深/ 8
if(depth == 32)
{
(图片的宽度的绝对值 * 32/ 8) % 4 一定为0 ;
}
if(depth == 24 )
{
(图片的宽度的绝对值 * 24 / 8) % 4 不一定为 0 ;
}
是不是我们24位的图片就需要填充若干个字节 来满足每行大小为4字节倍数要求
这些填充的字节数 我们叫癞子。
那我们怎么求出每行的填充的字节数呢?癞子?
int laizi;
if ( ( 宽度*色深/8 ) %4 !=0 )
{
laizi = 4 - 宽度*色深/8 ) %4 ;
}
我真正意义上一行的字节数 是多少? line_bytes = ( 宽度*色深/8 ) %4 + laizi ;
总共的字节数呢? total_bytes = line_bytes * height
unsigned char * p = malloc(total_bytes);
练习: 完成一张图片在板子上的显示
要求: 任意路径的图片
任意大小的图片
在板子上的任意位置显示
void show_bmp (char * pathname , int x,int y)
{
第一步:打开图片 ,读取宽度 高度 色深
第二步: 确定总字节数 然后malloc对应大小的内来保存这些颜色。unsigned char * p = malloc(total_bytes);
//第三步: 打开帧缓冲设备 映射 init(); end();
第四步: 把颜色的值写进去 要一个字节一个字节地写入 为什么呢?
因为32位和24位地A是不一样的。
unsigned char a,r,g,b ;
我们把前面保存的像素数组的对应内容 一个一个字节地给我的argb 。
24位的像素数组只有RGB a直接给0
32位的像素数组有a 需要给一个字节给a
每写完四个字节 写完一个argb 。 这四个字节是不是就是组成一个color ?
这个时候是不是就该调用我们draw_point函数。
注意: 每行跳过癞子。
第五步: 关闭图片 //关闭帧缓冲 解除映射
}