ubuntu中使用 控制显存方法 绘制简单形状。
- ubuntu版本U20.04,不同版本的显示宽度可能不同
- ubuntu自带桌面会影响绘图,可以使用
sudo init 3
老版可用:ctrl+alt+F1切换到字符界面,F1-F6是六个字符界面,F7是图形界面,ctrl+alt+F7返回图形界面。
基本显示原理:显示器会自动将显存中的数据输出到屏幕上(不同位置的数据对应不同的坐标点),数据格式是:四个字节:(不透明度、R、G、B) 如:0xffff0000,表示的是这个不透明的红色点、坐标和在显存中的地址有关系。
1.获取(0,0)的点的显示地址;
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
完整代码如下:
/*===============================================
* 文件名称:mycat.c
* 创 建 者:
* 创建日期:2022年06月24日
* 描 述:
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define OUTINFO 1
//显示器显示宽度
#define LINE_LENGTH 1176
int *addr = NULL;
void drawing_round(int x, int y, int r, int color);
void drawing_wire(int x1, int y1, int x2, int y2, unsigned int color);
void drawing_H(int x1, int x2, int y, int color);
void drawing_V(int y1, int y2, int x, int color);
void draw_rect(int x, int y, int w, int h);
void draw_rect_color(int x, int y, int w, int h, int color, int icolor);
void draw_point(int x, int y, int color);
int main(int argc, char *argv[])
{
int ret;
struct fb_var_screeninfo fbi_var; //定义可变参数
struct fb_fix_screeninfo fbi_fix; //定义固定参数
struct fb_cmap cmap;
//打开屏幕设备
int fd = open("/dev/fb0", O_RDWR);
if (fd < 0)
{
perror("open");
close(fd);
}
// 得到虚拟屏幕参数 ret = ioctl(fd, FBIOGET_VSCREENINFO, &fbi_var);
if (ret < 0)
{
perror("ioctl");
return NULL;
}
#if OUTINFO
printf("fbi.var.xres:%u ,fbi.var.yres:%u ,var.bpp:%d\n", fbi_var.xres, fbi_var.yres, fbi_var.bits_per_pixel);
printf("fbi.var.xoffset:%u ,fbi.var.yoffset:%u\n", fbi_var.xoffset, fbi_var.yoffset);
#endif
//得到实际屏幕参数
ret = ioctl(fd, FBIOGET_FSCREENINFO, &fbi_fix);
if (ret < 0)
{
perror("ioctl");
return NULL;
}
#if OUTINFO
printf("fbi.fix.smem_start:%lu,fbi.fix.smem_len:%u\n", fbi_fix.smem_start, fbi_fix.smem_len);
printf("line_length: %u\n", fbi_fix.line_length);
#endif
//获取显存起始地址
addr = mmap(NULL, fbi_fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == NULL)
{
perror("mmap");
ret = munmap(addr, fbi_fix.smem_len);
return NULL;
}
#if 0
puts("Please enter the starting position and the length and width (both are shaped and separated by Spaces):");
int x, y, w, h;
scanf("%d %d %d %d", &x, &y, &w, &h);
getchar();
puts("Please enter the border color and fill color: HEX value. (Space separated) Enter the default");
char buf[128] = {0};
fgets(buf, sizeof(buf), stdin);
int color = 0xffff0000, icolor = 0xff0000ff;
if (strlen(buf) > 1)
{
sscanf(buf, "%x %x", &color, &icolor);
}
draw_rect_color(x, y, w, h, color, icolor);
#endif
#if 0
drawing_wire(200, 200, 350, 250, 0xff00ff00);
drawing_wire(200, 200, 150, 250, 0xff00ff00);
drawing_wire(150, 250, 350, 250, 0xff00ff00);
#endif
#if 1
int r = 100;
drawing_round(300, 300, 100, 0xff00ff00);
for (int i = 0; i < 100; i++)
{
drawing_round(300, 300, i + 10, i * 0xff | 0xff00ff00);
}
#endif
close(fd);
return 0;
}
void drawing_round(int x1, int y1, int r, int color)
{
int x;
int y = sqrt(r * r - (x - x1) * (x - x1)) + y1;
int temp;
for (x = x1 - r; x <= x1 + r; x++)
{
// y = sqrt(r * r - (x - x1) * (x - x1)) + y1;
temp = sqrt(r * r - (x - x1) * (x - x1));
draw_point(x, temp + y1, color);
draw_point(x, y1 - temp, color);
}
}
void draw_rect_color(int x, int y, int w, int h, int color, int icolor)
{
drawing_H(x, x + w, y, color);
for (int i = 1; i < h; i++)
{
drawing_H(x, x + w, y + i, icolor);
}
drawing_H(x, x + w, y + h, color);
drawing_V(y, y + h, x, color);
drawing_V(y, y + h, x + w, color);
}
void draw_rect(int x, int y, int w, int h)
{
drawing_H(x, x + w, y, 0xff00ff00);
drawing_V(y, y + h, x, 0xff00ff00);
drawing_H(x, x + w, y + h, 0xff00ff00);
drawing_V(y, y + h, x + w, 0xff00ff00);
}
void drawing_H(int x1, int x2, int y, int color)
{
int width = x2 - x1;
int *addrH = addr + y * LINE_LENGTH + x1;
while (width > 0)
{
*addrH = color;
addrH++;
width--;
}
}
void drawing_V(int y1, int y2, int x, int color)
{
//画竖线
int *addr_h = addr + y1 * LINE_LENGTH + x;
int length = y2 - y1;
for (int i = 0; i < length; i++)
{
*addr_h = color;
addr_h += LINE_LENGTH;
}
}
void draw_point(int x, int y, int color)
{
int *addr_temp = addr + y * LINE_LENGTH + x;
*addr_temp = color;
}
void drawing_wire(int x1, int y1, int x2, int y2, unsigned int color)
{
if (x2 == x1)
{
drawing_V(y1, y2, x1, color);
}
if (y2 == y1)
{
drawing_H(x1, x2, y2, color);
}
double k = (double)(y2 - y1) / (x2 - x1);
int x = x1 > x2 ? x2 : x1;
int y;
for (x = (x1 > x2 ? x2 : x1); x < (x1 > x2 ? x1 : x2); x++)
{
y = k * (x - x1) + y1;
draw_point(x, y, color);
}
}
运行结果:
注:本片中可能存在一些错误,自行甄别,