通过Framebuffer刷屏使得屏幕显示红色

文章的开始,想要申明一下:我的目的是在整个屏幕上显示红色。关于Framebuffer的原理知识我很少涉及,请读者自己查阅相关书籍或者上网查找资料。

开发环境:

物理机(不是虚拟机)Ubuntu 11.04


最近在作一个视频采集显示的东西,要用到Framebuffer,就看了点相关的知识。在这里稍微总结一下。

       Framebuffer对应的文件是/dev/fb0。

       这里我说明两点:

       1.如果在/dev目录下没有fb0文件,那就重新启动试试。一开始我的电脑上也没有fb0文件,我就瞎捣鼓了一下Nvidia X Server Settings,修改了显示器设置参数,又重新启动了电脑就出现fb0文件了,具体原因我不知道(根据我的做事原则-用最简单、最有效、最直接的方法解决问题。我的目的是要显示器显示红色,既然我搞出来fb0文件了,离目的又进了一步,也就没有深究为什么)。

        2.修改下fb0文件的权限,否则会在以后运行程序时出现无法打开文件的错误。

           sudo chmod 666 /dev/fb0


       操作Framebuffer的步骤如下:

       1.打开文件:open函数

       2.映射帧缓冲到应用程序空间:mmap函数

       3.操作映射后的内存空间,在这里就是将红色对应的RGB和透析度的数值写到相关的内存空间内。

       4.释放映射空间和关闭文件描述符。


    程序总共两个:

  

1.第一个程序如下:

很简单的一个程序,就是打印出Framebuffer的一些相关信息,就是fb_var_screeninfo 和fb_fix_screeninfo 两个结构体主要成员的打印。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

int 
main (int argc,char **argv ){
	int fb_fd=-1;
	struct fb_var_screeninfo vinfo;
	struct fb_fix_screeninfo finfo;
	fb_fd = open("/dev/fb0",O_RDWR);
	if (fb_fd < 0){
		printf("Error : Can not open framebuffer device\n");
		exit(EXIT_FAILURE);
	}

	if(ioctl(fb_fd,FBIOGET_FSCREENINFO,&finfo)){
		printf("Error reading fixed information\n");
		exit(EXIT_FAILURE);
	}

	if (ioctl(fb_fd,FBIOGET_VSCREENINFO,&vinfo)){
		printf("Error reading variable information\n");
		exit(3);
	}

	printf("the fixed information is as follow:\n");
	printf("id=%s\n",finfo.id);
	printf("sem_start=%lx\n",finfo.smem_start);
	printf("smem_len=%u\n",finfo.smem_len);
	printf("type=%u\n",finfo.type);
	printf("line_length=%u\n",finfo.line_length);
	printf("mmio_start=%lu\n",finfo.mmio_start);
	printf("mmio_len=%d\n",finfo.mmio_len);

	printf("variable information is as follow:\n");
	printf("The xres is :%u\n",vinfo.xres);
	printf("The yres is :%u\n",vinfo.yres);
	printf("xres_virtual=%u\n",vinfo.xres_virtual);
	printf("yres_virtual=%u\n",vinfo.yres_virtual);
	printf("xoffset=%u\n",vinfo.xoffset);
	printf("yoffset=%u\n",vinfo.yoffset);
	printf("bits_per_pixel is :%u\n",vinfo.bits_per_pixel);
	printf("red.offset=%u\n",vinfo.red.offset);
	printf("red.length=%u\n",vinfo.red.length);
	printf("red.msb_right=%u\n",vinfo.red.msb_right);
	printf("green.offset=%d\n",vinfo.green.offset);
	printf("green.length=%d\n",vinfo.green.length);
	printf("green.msb_right=%d\n",vinfo.green.msb_right);
	printf("blue.offset=%d\n",vinfo.blue.offset);
	printf("blue.length=%d\n",vinfo.blue.length);
	printf("blue.msb_right=%d\n",vinfo.blue.msb_right);
	printf("transp.offset=%d\n",vinfo.transp.offset);
	printf("transp.length=%d\n",vinfo.transp.length);
	printf("transp.msb_right=%d\n",vinfo.transp.msb_right);
	printf("height=%x\n",vinfo.height);
	printf("width=%x\n",vinfo.width);
	
	close (fb_fd);
	return 0;
}

输出结果如下:


the fixed information is as follow:
id=VESA VGA
sem_start=cf000000
smem_len=1245184
type=0
line_length=2560
mmio_start=0
mmio_len=0
variable information is as follow:
The xres is :640
The yres is :480
xres_virtual=640
yres_virtual=480
xoffset=0
yoffset=0
bits_per_pixel is :32
red.offset=16
red.length=8
red.msb_right=0
green.offset=8
green.length=8
green.msb_right=0
blue.offset=0
blue.length=8
blue.msb_right=0
transp.offset=24
transp.length=8
transp.msb_right=0
height=ffffffff
width=ffffffff

有几个输出要重视:

The xres is :640

The yres is :480//虚拟控制台屏幕的分辨率(虚拟控制台,即:Ctrl+Alt+Fn(n=1,2,3,4,5,6)时进入的控制台。我的机器是物理机,虚拟机没有尝试过)


bits_per_pixel is :32//一个像素点占用32位,也就是说明像素点对应的内存中存放的RGB32(R、G、B各占8位,剩下的八位用来存放透析度(不知道是什么东西,也没管它))数据。这里有个问题很重要啊:到底这32位的数据怎么存放的的呢?????最低的八位放R、G、B还是透析度数据呢。。。。。。接着往下看---------


red.offset=16//看来R数据放在32数据中的16-23上

red.length=8

red.msb_right=0//指的是数据的最高有效位在最左边


green.offset=8//看来G数据放在32数据中的8-15上

green.length=8

green.msb_right=0


blue.offset=0//看来B数据放在32数据中的0-7上

blue.length=8

blue.msb_right=0


transp.offset=24//看来透析度数据放在32数据中的24-31上

transp.length=8

transp.msb_right=0


以上内容一定要明白,否则先别往下看,查查资料先把理论搞明白再说。



2.第二个程序如下:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#define IMAGE_W 640  //对应上一个程序的xres
#define IMAGE_H 480   //对应上一个程序的yres

typedef struct {
	char red;
	char blue;
	char green;
	char trans;
} PIXEL;         //自定义的结构体用于存放一个像素点的颜色数据,这里比较简单就是存放红色的RGB和透析度数据

int 
main(){
	PIXEL pixel;
	pixel.trans=0;
	pixel.red=255;
	pixel.green=0;
	pixel.blue=0;   //查表得到。。。。程序后面有插图



	int fb_fd=0,i=0,j=0;
	unsigned long int *fbp,*mmap_start;
	unsigned long buffersize;
	char * cur_pix;

	struct fb_var_screeninfo vinfo;
	struct fb_fix_screeninfo finfo;
	fb_fd = open("/dev/fb0",O_RDWR);
	if (fb_fd < 0){
		printf("Error : Can not open framebuffer device\n");
		exit(1);
	}

	if(ioctl(fb_fd,FBIOGET_FSCREENINFO,&finfo)){
		printf("Error reading fixed information\n");
		exit(2);
	}

	if (ioctl(fb_fd,FBIOGET_VSCREENINFO,&vinfo)){
		printf("Error reading variable information\n");
		exit(3);
	}

	/*
	printf("The xres is :%d\n",vinfo.xres);
	printf("The yres is :%d\n",vinfo.yres);
	printf("bits_per_pixel is :%d\n",vinfo.bits_per_pixel);
	*/
	buffersize=vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;
	mmap_start=(unsigned long int *)mmap(0,buffersize,PROT_READ | PROT_WRITE,MAP_SHARED,fb_fd,0);
	
	if((long int )mmap_start==-1){
		perror("mmap error!\n");
		exit(EXIT_FAILURE);
	}
	fbp=mmap_start;
	for(i=0;i<IMAGE_H;i++){
		for(j=0;j<IMAGE_W;j++){
			cur_pix=(char *)fbp;
			cur_pix[0]=pixel.blue;
			cur_pix[1]=pixel.green;
			cur_pix[2]=pixel.red;
			cur_pix[3]=pixel.trans;
			fbp++;
		}
	}

	munmap(mmap_start,buffersize);
	close (fb_fd);
	return 0;
	}
}



查表可得红色对应的RGB数据是0xFF0000 。


现在请按下组合键(Ctrl+Alt+Fn(n=1,2,3,4,5,6))进入虚拟控制台,通过cd命令转到存放源程序的目录下,编译后运行,是不是屏幕全变成红色了呢?



  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Linux上,您可以使用framebuffer来显示字符打印。Framebuffer是一种在内存中维护图形缓冲区的设备,它可以直接访问和控制显示器的像素。 要通过应用程序使用framebuffer显示字符打印,您可以按照以下步骤进行操作: 1. 打开framebuffer设备:使用`open()`函数打开framebuffer设备文件。通常,framebuffer设备文件的路径是`/dev/fb0`。 2. 获取framebuffer信息:使用`ioctl()`函数和`FBIOGET_VSCREENINFO`命令来获取framebuffer的信息结构体。您可以使用`struct fb_var_screeninfo`类型的结构体来存储此信息。 3. 设置终端模式:如果您正在从终端登录并且需要在终端模式下显示字符打印,可以使用`ioctl()`函数和`KDSETMODE`命令将终端模式设置为`KD_GRAPHICS`。 4. 映射framebuffer内存:使用`mmap()`函数将framebuffer设备文件映射到内存中。您可以使用`struct fb_fix_screeninfo`类型的结构体来获取framebuffer内存地址和长度。 5. 编写字符打印代码:您可以使用映射的framebuffer内存地址来直接操作像素,从而实现字符打印。您可以选择使用ASCII表中的字符,并将它们绘制到适当的位置上。 6. 刷新屏幕:在完成字符打印后,使用`ioctl()`函数和`FBIO_REFRESH_RATE`命令来刷新屏幕。 7. 关闭framebuffer设备:最后,使用`close()`函数关闭framebuffer设备。 请注意,使用framebuffer直接操作像素是一种底层的方法,需要对图形编程和硬件进行一定的了解。此外,不同的嵌入式系统和显示设备可能有不同的framebuffer实现和操作方式。 以上是一个简单的概述,实际操作中可能需要更多的细节和代码。如果您想了解更多关于使用framebuffer显示字符打印的详细信息,建议查阅相关的文档或参考示例代码。 希望这些信息对您有所帮助!如有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coffee_baba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值