linux屏幕显示

.像素(pixel)图像显示的基本单位
2.分辨率(image resolution)分辨率是指单位面积显示像素的数量
3.色彩深度(BPP,bits per pixel)一个像素所能表达的不同颜色数取决于比


特每像素。
常见的取值有:
8bpp:256色;16 bpp:2^16=65535色;24 bpp:2^24=1600万色
一个16位的深度通常分为5位红色,5位蓝色,6位绿色(眼睛对于绿色更为敏


感)24位的一般都是每个分量8位,而32位的颜色深度也是常见的,这意味着


除了24位的像素,还有8位的额外数位来描述透明度。
一个像素点所对应的字节数目越多,其色彩深度越深,表现力就越细腻。


        LCD显示器一般对应的设备节点文件是/dev/fb0在编写程序之前,我们还需要理解一下framebuffer,    



framebuffer机制模仿显卡的功能,将显卡硬件结构抽象为一系列的数据结构,可以通过framebuffer的读写直接对显存进行操作。用户可以将framebuffer看成是显存的一个映像,将其映射到进程空间后,就可以直接进行读写操作,写操作会直接反映在屏幕上。


了解framebuffer一些结构体

//struct fb_fix_screeninfo用于描述显卡的属性
    struct fb_fix_screeninfo {
    char id[16]; /* identification string eg "TT Builtin" */
    unsigned long smem_start; /* 显存起始地址*/
    /* 实际物理地址 */
    __u32 smem_len; /* 显存大小 */
    __u32 type; /* see FB_TYPE_* */
    __u32 type_aux; /* Interleave for interleaved Planes */
    __u32 visual; /* see FB_VISUAL_* */
    __u16 xpanstep; /* zero if no hardware panning */
    __u16 ypanstep; /* zero if no hardware panning */
    __u16 ywrapstep; /* zero if no hardware ywrap */
    __u32 line_length; /* length of a line in bytes */
    unsigned long mmio_start; /* Start of Memory Mapped I/O */
    /* (physical address) */
    __u32 mmio_len; /* Length of Memory Mapped I/O */
    __u32 accel; /* Type of acceleration available */
    __u16 reserved[3]; /* Reserved for future compatibility */
};
以上结构体是由驱动程序根据硬件配置决定的,不能修改,我们要根据该结构
体提供的具体信息来构建和操作frame-buffer映射内存。
//显卡的特性
struct fb_var_screeninfo
{
    __u32 xres; /* visible resolution */
    __u32 yres;
    __u32 xres_virtual; /* virtual resolution */
    __u32 yres_virtual;
    __u32 xoffset; /* offset from virtual to visible resolution */
    __u32 yoffset;
    __u32 bits_per_pixel; /* guess what */
    __u32 grayscale; /* != 0 Gray levels instead of colors */
    struct fb_bitfield red; /* bitfield in fb mem if true color, */
    struct fb_bitfield green; /* else only length is significant */
    struct fb_bitfield blue;
    struct fb_bitfield transp; /* transparency */
    __u32 nonstd; /* != 0 Non standard pixel format */
    __u32 activate; /* see FB_ACTIVATE_* */
    __u32 height; /* height of picture in mm */
    __u32 width; /* width of picture in mm */
    __u32 accel_flags; /* acceleration flags (hints) */
    /* Timing: All values in pixclocks, except pixclock (of course) 


*/
    __u32 pixclock; /* pixel clock in ps (pico seconds) */
    __u32 left_margin; /* time from sync to picture */
    __u32 right_margin; /* time from picture to sync */
    __u32 upper_margin; /* time from sync to picture */
    __u32 lower_margin;
    __u32 hsync_len; /* length of horizontal sync */
    __u32 vsync_len; /* length of vertical sync */
    __u32 sync; /* see FB_SYNC_* */
    __u32 vmode; /* see FB_VMODE_* */
    __u32 reserved[6]; /* Reserved for future compatibility */
};
xres_virtual和yres_virtual决定了虚拟区的大小,而xres和yres是实际屏幕


的大小,xoffset和yoffset是偏移量,是xres和yres相对于xres_virtual和


yres_virtual区域上的偏移(一般来说xres_virtual和yres_virtual比xres和


yres要大)。

下面是屏幕显示单色的c例程。


#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <linux/fb.h>


#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
enum color{red,green,blue};


unsigned long * create_color(struct fb_var_screeninfo *pinfo,enum color c)
{
unsigned long *three_color = calloc(1,pinfo->bits_per_pixel/8);
unsigned long *mask = calloc(1,pinfo->bits_per_pixel/8);


int i;
*mask |= 1;
switch(c)
{
//创建红色,根据pinfo所提供的信息,往表示红色的位置写1,
//其他的为0,同理创建出另外两种颜色
case red:
for(i=0;i<pinfo->red.length-1;i++)
{
*mask <<= 1;
*mask |= 0x1;
}
*three_color |= *mask<<pinfo->red.offset;
break;
case green:
for(i=0;i<pinfo->green.length-1;i++)
{
*mask <<= 1;
*mask |= 0x1;
}
*three_color |= *mask<<pinfo->green.offset;
break;
case blue:
for(i=0;i<pinfo->blue.length-1;i++)
{
*mask <<= 1;
*mask |= 0x1;
}
*three_color |= *mask<<pinfo->blue.offset;
break;
}
return three_color;
}


int main(void)
{
int lcd = open("/dev/fb0",O_RDWR);
if(lcd < 0)
{
perror("lcd open failed:\n");
exit(1);
}
//定义两个结构体分别用来存储显存的信息
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;


//用ioctl函数根据命令字FBIOGET_FSCREENINFO和
//FBIOGET_VSCREENINFO来获取显存的信息
ioctl(lcd,FBIOGET_FSCREENINFO,&finfo);
ioctl(lcd,FBIOGET_VSCREENINFO,&vinfo);

//设置偏移量为0
vinfo.xoffset = 0;
vinfo.xoffset = 0;
ioctl(lcd,FBIOPAN_DISPLAY,&vinfo);


//因为RGB三原色在每个像素点的位置是固定的,所以要显示
//出这三种单色,就必须往每个像素点对应的字节写1,其他
//为0,这样就可以显示出这三种颜色了,我们要一个函数来
//创造出这三种颜色


//用n来保存每个像素点用多少位表示,申请内存的时候会用到
unsigned long n = vinfo.bits_per_pixel;


//创建出三种颜色
unsigned long *three_color[3] = {0};
three_color[0] = create_color(&vinfo,red);
three_color[1] = create_color(&vinfo,green);
three_color[2] = create_color(&vinfo,blue);


//映射一片内存,第一个参数为null时表示系统自动分配
//映射的内存的大小跟屏幕大小一样大
char *show=mmap(NULL,vinfo.xres*vinfo.yres*n/8,
PROT_READ | PROT_WRITE,MAP_SHARED,lcd,0) ;
//每秒钟显示一种颜色
while(1)
{
int i,k;
for(k=0;k<3;k++)
{


for(i=0;i<vinfo.xres*vinfo.yres;i++)
memcpy(show+i*n/8,three_color[k],n/8);
sleep(1);
}
}
return 0;

}

如果没有开发板的话,也可以在ubuntu下试验,按ctl+alt+f5进入屏幕终端,然后运行编译出来的文件。按ctl+alt+f7退出黑色终端。

这个程序只是简单的显示单色,要显示一张图片例如jpg,还要用到一些解码库。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭