一、基本概念
framebuffer: 帧缓存、帧缓存(显示设备)
Linux内核为显示提供的一套应用程序接口。(驱动内核支持)
分辨率:
像素点
显示屏:800 * 600(横向有800个像素点,纵向有600个像素点)
显卡(显存(保存像素点的值))
RGB
888(8个bitR,8个bit G,8个bit B)
PC ,4412(RGB888)
RGB565(S3C2440)
为了提高代码的书写效率(将RGB扩充到4字节)
二、解决显存空间不能直接被用户访问
根据显存的大小的多少,来申请空间
1、打开显示设备(/dev/fb0)
2、获取显示设备相关参数(分辨率、位深度......)
3、建立内存映射
4、写入RGB颜色值
5、解除映射
6、关闭显示设备
三、framebuffer常问话术
framebuff(是什么,具体原理、怎么做、)
是什么:Linux内核为显示提供的一套应用程序接口。(驱动内核支持)
具体原理:通过内存映射技术向显存空间写入RGB值
1、打开显示设备(/dev/fb0)
2、获取显示设备相关参数(分辨率、位深度......)
3、建立内存映射
4、写入RGB颜色值
5、解除映射
6、关闭显示设备
四、framebuffer绘制图片
jpg png(已压缩、有损的图像处理)
bmp:位图(未压缩的,无损的)
位图格式,通常未压缩,因此文件较大,保存了图像的所有细节。
用途:常用于Windows操作系统中的图像存储,适合不需要压缩的场合。
缺点:由于文件大小较大,不适合网络传输。
54个字节是头部信息,前14字节是文件相关信息,40字节是图像相关信息。
修改为bmp
用画图工具另存为.bmp格式,不要修改文件的后缀名,每一个格式都有自己的具体格式。
每一个格式都有自己的具体格式
标准IO fseek
文件IO seek
为了提升效率直接将想要读的数据直接读到内存中
bmp里面存储的数据是 rgb实际上是bgr,所以我们需要进行数据转换,所以我们需要进行数据的格式进行向前移动。
指针进行偏移,进行指向,第一个是b,g,r
向将高位进行移动,然后将后面的格式向前移动,进行拼接,按位或,根据不同的格式,进行不同的移动,对于不同 的格式,我们进行不同的位运算
显示文字
我们的文字显示是在矩阵当中,所以进行矩阵进行点亮
显示文字的时候我们用行的话字节进行提取,按位进行判断那一位应该备置起来
四、常见画图操作
1、画一个点
void draw_point(int x, int y, unsigned int col)
{
if (x >= vinf.xres || y >= vinf.yres)
{
return ;
}
if (vinf.bits_per_pixel == RGB888_FMT)
{
unsigned int *p = pmem;
*(p + y * vinf.xres_virtual + x) = col;
}
else if (vinf.bits_per_pixel == RGB565_FMT)
{
unsigned short *p = pmem;
*(p + y * vinf.xres_virtual + x) = col;
}
return ;
}
2 横线
void draw_h_line(int x, int y, int len, unsigned int col)
{
for (int i = x; i < x+len; i++)
{
draw_point(i, y, col);
}
}
3 数线
void draw_s_line(int x, int y, int len, unsigned int col)
{
for (int i = y; i < y+len; i++)
{
draw_point(x, i, col);
}
}
4 斜线
void draw_x_line(int x1, int y1, int x2, int y2, unsigned int col)
{
int x = 0;
int y = 0;
if (x1 == x2)
{
if (y2 > y1)
{
draw_s_line(x1, y1, y2-y1, col);
}
else
{
draw_s_line(x2, y2, y1-y2, col);
}
}
double k = (double)(y2-y1)/(double)(x2-x1);
double b = y1 - k*x1;
for (int x = (x1 > x2 ? x2 : x1); x <= (x1 > x2 ? x1 : x2); x++)
{
y = x * k + b;
draw_point(x, y, col);
}
return ;
}
5 矩形
void draw_rectangle(int x, int y, int w, int h, unsigned int col)
{
draw_h_line(x, y, w, col);
draw_s_line(x, y, h, col);
draw_s_line(x+w, y, h, col);
draw_h_line(x, y+h, w, col);
}
6 圆
void draw_circle(int x0, int y0, int r, unsigned int col)
{
int x = 0;
int y = 0;
for (double si = 0; si <= 360; si+=0.01)
{
x = r * cos(2 * 3.14159/360 *si) + x0;
y = r * sin(2 * 3.14159/360 *si) + y0;
draw_point(x, y, col);
draw_point(x-1, y, col);
draw_point(x+1, y, col);
draw_point(x, y-1, col);
draw_point(x, y+1, col);
}
}
7 图片
void draw_bmp(int x, int y, char *picname, int w, int h)
{
int fd = open(picname, O_RDONLY);
if (-1 == fd)
{
perror("fail open bmp");
return ;
}
lseek(fd, 54, SEEK_SET);
unsigned char r, g, b;
unsigned char *buff = malloc(w*h*3);
read(fd, buff, w*h*3);
unsigned char *p = buff;
for (int j = h-1; j >= 0; j--)
{
for (int i = 0; i < w; i++)
{
b = *p; p++;
g = *p; p++;
r = *p; p++;
if (vinf.bits_per_pixel == RGB888_FMT)
{
unsigned int col = (r << 16) | (g << 8) | (b << 0);
draw_point(i+x, j+y, col);
}
else if (vinf.bits_per_pixel == RGB565_FMT)
{
unsigned short col = ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0);
draw_point(i+x, j+y, col);
}
}
}
free(buff);
close(fd);
}
8 文字
void draw_word(int x,int y,unsigned char *word,int w,int h,unsigned int col)
{
for(int j = 0;j < h;j++)
{
for(int i = 0;i < w;i++)
{
unsigned char tmp = word[i + j*w];
for(int k = 0;k < 8;k++)
{
if(tmp & 0x80)
{
draw_point(i*8 + k + x,j + y,col);
}
tmp = tmp << 1;
}
}
}
}
9 清屏
void draw_clear(unsigned int col)
{
for (int j = 0; j < vinf.xres; j++)
{
for (int i = 0; i < vinf.yres; i++)
{
draw_point(i, j, col);
}
}
}