[size=6][color=Red]特別鳴謝 star316 對(duì)本貼做出的錯(cuò)誤指正[/color][/size]
做了很長(zhǎng)時(shí)間的圖形開(kāi)發(fā),自己打算把相關(guān)的技術(shù)重頭屢屢,一點(diǎn)一點(diǎn)的寫(xiě),不著急,先發(fā)一篇入門(mén)的
1:搭建Linux下的圖形系統(tǒng)開(kāi)發(fā)環(huán)境
圖形輸出在嵌入式開(kāi)發(fā)中,多數(shù)是向FrameBuffer中寫(xiě)數(shù)據(jù),然后會(huì)顯示在LCD中,在Linux下做圖形開(kāi)發(fā)的時(shí)候,需要模擬各種環(huán)境,比如16位色的環(huán)境,32位色的環(huán)境等,這個(gè)時(shí)候需要在Linux中做一個(gè)配置的修改:
[root@localhost root]# vi /boot/grub/grub.conf
上面這條命令是用來(lái)編輯grub引導(dǎo)配置文件。該配置文件原來(lái)的內(nèi)容為:
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/sda2
# initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=10
splashimage=(hd0,0)/grub/splash.xpm.gz
title Red Hat Linux (2.6.26)
root (hd0,0)
kernel /vmlinuz-2.6.26
initrd /initrd-2.6.26.img
將其修改為:
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/sda2
# initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=10
splashimage=(hd0,0)/grub/splash.xpm.gz
title Red Hat Linux (2.6.26)
root (hd0,0)
kernel /vmlinuz-2.6.26 vga=0x314
initrd /initrd-2.6.26.img
其實(shí)僅僅是在kernel /vmlinuz-2.6.26這一行末尾處加了一個(gè)vga=0x314,將Framebuffer設(shè)置為800x600x16的顯示模式,其中800x600是屏幕分辨率,16表示顯示的是16bit的彩色。下面詳細(xì)的說(shuō)一下關(guān)于vesa vga參數(shù)的含義:
4bit 8bit 15bit 16bit 24bit 32bit
640x400 x 0x300 x x x x
640x480 x 0x301 0x310 0x311 0x312 x
800x600 0x302 0x303 0x313 0x314 0x315 x
1024x768 x 0x305 0x316 0x317 0x318 x
1280x1024 x 0x307 0x319 0x31A 0x31B x
1600x1200 x 0x31C 0x31D 0x31E 0x31F x
而在現(xiàn)在的開(kāi)發(fā)環(huán)境中,和嵌入式平臺(tái)中,用16bit的顏色的還是主流,所以,主要介紹一下16bit的顏色的類(lèi)型,而顏色是由RGB組成:
常見(jiàn)16位顏色的類(lèi)型分為:
(1)565:依次排列為Red,Green,Blue,二進(jìn)制表示為:
Red Green Blue
RRRRR GGGGGG BBBBB
(2)1555:依次排列為Alpha,Red,Green,Blue
Alpha Red Green Blue
A RRRRR GGGGG BBBBB
565排列的顏色:
0xFFFF的顏色是白色,在RGB565中排列形式為:
R G B
11111 111111 111111
0xF800的顏色是紅色,在RGB565中排列的形式為:
R G B
11111 000000 000000
0X7e0的顏色是綠色,在RGB565中排列的形式為:
R G B
00000 111111 000000
假設(shè)Alpha值為1的1555排列的顏色:
0XFC00的顏色是紅色,在ARGB1555中排列形式為:
A R G B
1 11111 00000 00000
0X83E0的顏色是綠色,在ARGB1555中排列形式為:
A R G B
1 00000 11111 00000
其他顏色就不在這里一一贅述,需要在實(shí)踐中慢慢累積與總結(jié)。
RGB簡(jiǎn)介
前面介紹了做了很多表來(lái)體現(xiàn)的就是RGB顏色排列形式,那么什么是RGB呢?
概述
RGB色彩模式是工業(yè)界的一種顏色標(biāo)準(zhǔn),是通過(guò)對(duì)紅(R)、綠(G)、藍(lán)(B)三個(gè)顏色通道的變化以及它們相互之間的疊加來(lái)得到各式各樣的顏色的,RGB即是代表紅、綠、藍(lán)三個(gè)通道的顏色,這個(gè)標(biāo)準(zhǔn)幾乎包括了人類(lèi)視力所能感知的所有顏色,是目前運(yùn)用最廣的顏色系統(tǒng)之一。
RGB色彩模式使用RGB模型為圖像中每一個(gè)像素的RGB分量分配一個(gè)0~255范圍內(nèi)的強(qiáng)度值。例如:純紅色R值為255,G值為0,B值為0;灰色的R、G、B三個(gè)值相等(除了0和255);白色的R、G、B都為255;黑色的R、G、B都為0。RGB圖像只使用三種顏色,就可以使它們按照不同的比例混合,在屏幕上重現(xiàn)16777216種顏色。
在 RGB 模式下,每種 RGB 成分都可使用從 0(黑色)到 255(白色)的值。 例如,亮紅色使用 R 值 246、G 值 20 和 B 值 50。 當(dāng)所有三種成分值相等時(shí),產(chǎn)生灰色陰影。 當(dāng)所有成分的值均為 255 時(shí),結(jié)果是純白色;當(dāng)該值為 0 時(shí),結(jié)果是純黑色。
應(yīng)用
目前的顯示器大都是采用了RGB顏色標(biāo)準(zhǔn),在顯示器上,是通過(guò)電子槍打在屏幕的紅、綠、藍(lán)三色發(fā)光極上來(lái)產(chǎn)生色彩的,目前的電腦一般都能顯示32位顏色,約有一百萬(wàn)種以上的顏色。
原理
RGB是從顏色發(fā)光的原理來(lái)設(shè)計(jì)定的,通俗點(diǎn)說(shuō)它的顏色混合方式就好像有紅、綠、藍(lán)三盞燈,當(dāng)它們的光相互疊合的時(shí)候,色彩相混,而亮度卻等于兩者亮度之總和(兩盞燈的亮度嘛?。交旌狭炼仍礁?,即加法混合。
有色光可被無(wú)色光沖淡并變亮。如藍(lán)色光與白光相遇,結(jié)果是產(chǎn)生更加明亮的淺藍(lán)色光。知道它的混合原理后,在軟件中設(shè)定顏色就容易理解了。
紅、綠、藍(lán)三盞燈的疊加情況,中心三色最亮的疊加區(qū)為白色,加法混合的特點(diǎn):越疊加越明亮。
紅、綠、藍(lán)三個(gè)顏色通道每種色各分為255階亮度,在0時(shí)“燈”最弱——是關(guān)掉的,而在255時(shí)“燈”最亮。當(dāng)三色數(shù)值相同時(shí)為無(wú)色彩的灰度色,而三色都為255時(shí)為最亮的白色,都為0時(shí)為黑色。
RGB 顏色稱(chēng)為加成色,因?yàn)槟ㄟ^(guò)將 R、G 和 B 添加在一起(即所有光線反射回眼睛)可產(chǎn)生白色。 加成色用于照明光、電視和計(jì)算機(jī)顯示器。 例如,顯示器通過(guò)紅色、綠色和藍(lán)色熒光粉發(fā)射光線產(chǎn)生顏色。絕大多數(shù)可視光譜都可表示為紅、綠、藍(lán) (RGB) 三色光在不同比例和強(qiáng)度上的混合。 這些顏色若發(fā)生重疊,則產(chǎn)生青、洋紅和黃。
在嵌入式設(shè)備圖形系統(tǒng)開(kāi)發(fā)中,常用到的設(shè)備就是Framebuffer,所以,本書(shū)介紹的圖形系統(tǒng)開(kāi)發(fā),主要是針對(duì)Framebuffer的操作進(jìn)行。
首先打開(kāi)framebuffer設(shè)備,framebuffer設(shè)備可以根據(jù)環(huán)境變量FRAMEBUFFER來(lái)獲得,也可以手動(dòng)輸入下面是一個(gè)打開(kāi)設(shè)備的里子:
1 /**************************************************
2 * example1.c
3 * Author: T-bagwell
4 *
5 * Compile:gcc -Wall example1.c -o example1
6 *************************************************/
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12
13 int main(int argc, char *argv[])
14 {
15 int screen_fbd=0;
16 char *env=NULL;
17
18 if(!(env = getenv("FRAMEBUFFER")))
19 {
20 env = "/dev/fb0";
21 }
22
23 screen_fbd = open(env, O_RDWR);
24
25 if(screen_fbd < 0)
26 {
27 printf("Error Opening FrameBuffer Device:%s\r\n", env);
28 return 0;
29 }
30 else
31 {
32 printf("Success Opening FrameBuffer Device:%s\r\n",env);
33 }
34
35 return 0;
36 }
打開(kāi)設(shè)備成功以后會(huì)輸出:
Success Opening FrameBuffer Device:/dev/fb0
framebuffer設(shè)備打開(kāi)成功,接著需要獲得framebuffer的相關(guān)參數(shù),framebuffer對(duì)應(yīng)的參數(shù)不多,如下:
struct fb_fix_screeninfo {
char id[16]; /* 用來(lái)辨認(rèn)的字符串,例如 "TT Builtin" */
unsigned long smem_start; /* framebuffer的內(nèi)存起始地址*/
/* (物理地址) */
__u32 smem_len; /* framebuffer內(nèi)存的長(zhǎng)度 */
__u32 type; /* 類(lèi)型描述*/
__u32 type_aux; /*插入?yún)^(qū)域 */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /*沒(méi)有硬件設(shè)備,這里就是0*/
__u16 ypanstep;
__u16 ywrapstep;
__u32 line_length; /*字節(jié)在一行的表示*/
unsigned long mmio_start; /* 內(nèi)存io映射的開(kāi)始*/
/* (物理地址) */
__u32 mmio_len; /* 內(nèi)存io映射的長(zhǎng)度*/
__u32 accel; /*可用的加速類(lèi)型 */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
struct fb_var_screeninfo {
__u32 xres; /*可視區(qū)域*/
__u32 yres;
__u32 xres_virtual; /*虛擬區(qū)域*/
__u32 yres_virtual;
__u32 xoffset; /* 從虛擬到可視區(qū)域的偏移 */
__u32 yoffset;
__u32 bits_per_pixel; /*每一像素的bit數(shù)*/
__u32 grayscale; /* 如果這里設(shè)置為0就是黑白色的 */
struct fb_bitfield red; /*如果是真彩澀就在這里添紅色*/
struct fb_bitfield green; /* 否則只有長(zhǎng)度是有意義的 */
struct fb_bitfield blue;
struct fb_bitfield transp; /* 通明色處理*/
__u32 nonstd; /* != 0這里就是非標(biāo)準(zhǔn)格式 */
__u32 activate; /* see FB_ACTIVATE_**/
__u32 height; /* 圖象高度*/
__u32 width; /*圖象寬度*/
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* 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; /*水平可視區(qū)域*/
__u32 vsync_len; /*垂直可視區(qū)域*/
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 reserved[5]; /* Reserved for future compatibility */
};
struct fb_cmap {
__u32 start; /*入口地址*/
__u32 len;
__u16 *red; /* 紅色值*/
__u16 *green;
__u16 *blue;
__u16 *transp; /*透明色, 可以為NULL */
};
通過(guò)Linux系統(tǒng)中的ioctl來(lái)獲得framebuffer的參數(shù),代碼如下:
1 /**************************************************
2 * example1.c
3 * Author: T-bagwell
4 *
5 * Compile:gcc -Wall example2.c -o example2
6 *************************************************/
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <linux/fb.h>
13 int main(int argc, char *argv[])
14 {
15 int screen_fbd=0;
16 struct fb_fix_screeninfo fb_fix;
17 struct fb_var_screeninfo fb_var;
18 char *env=NULL;
19
20 if(!(env = getenv("FRAMEBUFFER")))
21 {
22 env = "/dev/fb0";
23 }
24
25 screen_fbd = open(env, O_RDWR);
26
27 if(screen_fbd < 0)
28 {
29 printf("Error Opening FrameBuffer Device:%s\r\n", env);
30 return 0;
31 }
32 else
33 {
34 printf("Success Opening FrameBuffer Device:%s\r\n",env);
35 }
36
37 if(ioctl(screen_fbd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
38 {
39 printf("Error Reading Screen Info FSCREENINFO.\n");
40
41 close(screen_fbd);
42
43 return 0;
44 }
45
46 printf("fb_fix.id=\"%s\"\r\n",fb_fix.id);
47 printf("fb_fix.smem_start=%#x\r\n",fb_fix.smem_start);
48 printf("fb_fix.mem_len=%d\r\n",fb_fix.smem_len);
49 printf("fb_fix.type=%d\r\n",fb_fix.type);
50 printf("fb_fix.type_aux=%d\r\n",fb_fix.type_aux);
51 printf("fb_fix.visual=%d\r\n",fb_fix.visual);
52 printf("fb_fix.xpanstep=%s\r\n",fb_fix.xpanstep);
53 printf("fb_fix.ypanstep=%d\r\n",fb_fix.ypanstep);
54 printf("fb_fix.ywrapstep=%d\r\n",fb_fix.ywrapstep);
55 printf("fb_fix.line_length=%d\r\n",fb_fix.line_length);
56 printf("fb_fix.mmio_start=%#x\r\n",fb_fix.mmio_start);
57 printf("fb_fix.mmio_len=%#x\r\n",fb_fix.mmio_len);
58 printf("fb_fix.accel=%d\r\n",fb_fix.accel);
59 printf("fb_fix.reserved[0]=%d\r\n",fb_fix.reserved[0]);
60 printf("fb_fix.reserved[1]=%d\r\n",fb_fix.reserved[1]);
61 printf("fb_fix.reserved[2]=%d\r\n",fb_fix.reserved[2]);
62 if(ioctl(screen_fbd, FBIOGET_VSCREENINFO, &fb_var) == -1)
63 {
64 printf("Error Reading Screen Info VSCREENINFO.\n");
65
66 close(screen_fbd);
67
68 return 0;
69 }
70 printf("fb_var.xres=%d\r\n",fb_var.xres);
71 printf("fb_var.yres=%d\r\n",fb_var.yres);
72 printf("fb_var.xres_virtual=%d\r\n",fb_var.xres_virtual);
73 printf("fb_var.yres_virtual=%d\r\n",fb_var.yres_virtual);
74 printf("fb_var.xoffset=%d\r\n",fb_var.xoffset);
75 printf("fb_var.yoffset=%d\r\n",fb_var.yoffset);
76 printf("fb_var.bits_per_pixel=%d\r\n",fb_var.bits_per_pixel);
77 printf("fb_var.grayscale=%d\r\n",fb_var.grayscale);
78 printf("fb_var.red=%#x\r\n",fb_var.red);
79 printf("fb_var.green=%#x\r\n",fb_var.green);
80 printf("fb_var.blue=%#x\r\n",fb_var.blue);
81 printf("fb_var.transp=%#x\r\n",fb_var.transp);
82 printf("fb_var.nonstd=%d\r\n",fb_var.nonstd);
83 printf("fb_var.activate=%d\r\n",fb_var.activate);
84 printf("fb_var.height=%d\r\n",fb_var.height);
85 printf("fb_var.width=%d\r\n",fb_var.width);
86 printf("fb_var.accel_flags=%d\r\n",fb_var.accel_flags);
87 printf("fb_var.pixclock=%d\r\n",fb_var.pixclock);
88 printf("fb_var.left_margin=%d\r\n",fb_var.left_margin);
89 printf("fb_var.right_margin=%d\r\n",fb_var.right_margin);
90 printf("fb_var.upper_margin=%d\r\n",fb_var.upper_margin);
91 printf("fb_var.lower_margin=%d\r\n",fb_var.lower_margin);
92 printf("fb_var.hsync_len=%d\r\n",fb_var.hsync_len);
93 printf("fb_var.vsync_len=%d\r\n",fb_var.vsync_len);
94 printf("fb_var.sync=%d\r\n",fb_var.sync);
95 printf("fb_var.vmode=%d\r\n",fb_var.vmode);
96 printf("fb_var.rotate=%d\r\n",fb_var.rotate);
97 printf("fb_var.reserved[0]=%d\r\n",fb_var.reserved[0]);
98 printf("fb_var.reserved[1]=%d\r\n",fb_var.reserved[1]);
99 printf("fb_var.reserved[2]=%d\r\n",fb_var.reserved[2]);
100 printf("fb_var.reserved[3]=%d\r\n",fb_var.reserved[3]);
101 printf("fb_var.reserved[4]=%d\r\n",fb_var.reserved[4]);
102
103 return 0;
104 }
105
代碼看上去并不是很多,其目的主要是通過(guò)ioctl獲得framebuffer參數(shù),然后輸出,輸出結(jié)果為:
Success Opening FrameBuffer Device:/dev/fb0
fb_fix.id="VESA VGA"
fb_fix.smem_start=0xf0000000
fb_fix.mem_len=1920000
fb_fix.type=0
fb_fix.type_aux=0
fb_fix.visual=2
fb_fix.xpanstep=0
fb_fix.ypanstep=0
fb_fix.ywrapstep=0
fb_fix.line_length=1600
fb_fix.mmio_start=0
fb_fix.mmio_len=0
fb_fix.accel=0
fb_fix.reserved[0]=0
fb_fix.reserved[1]=0
fb_fix.reserved[2]=0
fb_var.xres=800
fb_var.yres=600
fb_var.xres_virtual=800
fb_var.yres_virtual=600
fb_var.xoffset=0
fb_var.yoffset=0
fb_var.bits_per_pixel=16
fb_var.grayscale=0
fb_var.red=0xb
fb_var.green=0x5
fb_var.blue=0
fb_var.transp=0
fb_var.nonstd=0
fb_var.activate=0
fb_var.height=-1
fb_var.width=-1
fb_var.accel_flags=0
fb_var.pixclock=20833
fb_var.left_margin=96
fb_var.right_margin=32
fb_var.upper_margin=16
fb_var.lower_margin=4
fb_var.hsync_len=96
fb_var.vsync_len=4
fb_var.sync=0
fb_var.vmode=0
fb_var.rotate=0
fb_var.reserved[0]=0
fb_var.reserved[1]=0
fb_var.reserved[2]=0
fb_var.reserved[3]=0
fb_var.reserved[4]=0
雖然輸出了很多的參數(shù),讀者可能會(huì)覺(jué)得這些參數(shù)看上去很眼花繚亂,不要緊,挑出一些關(guān)鍵的參數(shù)來(lái)使用即可,從輸出信息中可以看到fb_var.xres=800,fb_var.yres=600,說(shuō)明這個(gè)framebuffer的x最大值可以為800,y最大值可以為600。
當(dāng)?shù)玫剿行枰玫降闹狄院?,可以開(kāi)辟一段內(nèi)存:
/**************************************************
* example3.c
* Author: T-bagwell
*
* Compile:gcc -Wall example3.c -o example3
*************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <errno.h>
#include <sys/mman.h>
char *fb_addr;
unsigned fb_size;
int main(int argc, char *argv[])
{
int screen_fbd=0;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char *env=NULL;
if(!(env = getenv("FRAMEBUFFER")))
{
env = "/dev/fb0";
}
screen_fbd = open(env, O_RDWR);
if(screen_fbd < 0)
{
printf("Error Opening FrameBuffer Device:%s\r\n", env);
return 0;
}
else
{
printf("Success Opening FrameBuffer Device:%s\r\n",env);
}
if(ioctl(screen_fbd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
{
printf("Error Reading Screen Info FSCREENINFO.\n");
close(screen_fbd);
return 0;
}
if(ioctl(screen_fbd, FBIOGET_VSCREENINFO, &fb_var) == -1)
{
printf("Error Reading Screen Info VSCREENINFO.\n");
close(screen_fbd);
return 0;
}
fb_size = fb_var.yres * fb_fix.line_length;
fb_addr = (char *)mmap(NULL, fb_size, PROT_READ|PROT_WRITE,MAP_SHARED, screen_fbd, 0);
if (!fb_addr)
exit(1);
return 0;
}
首先得到整個(gè)framebuffer的大小fb_size = fb_var.yres * fb_fix.line_length;然后映射framebuffer的內(nèi)存,這樣,當(dāng)向指定的內(nèi)存處寫(xiě)入數(shù)據(jù)的時(shí)候,framebuffer中就會(huì)寫(xiě)入對(duì)應(yīng)的數(shù)據(jù),也就會(huì)有對(duì)應(yīng)的數(shù)據(jù)表示的圖象顯示在屏幕中。
[ 本帖最后由 T-bagwell 于 2009-3-30 20:27 編輯 ]
T-bagwell 回復(fù)于:2009-02-24 15:56:10
以向屏幕中顯示一個(gè)純白色的頁(yè)面為例,當(dāng)RGB值為255、255、255時(shí),顏色將為白色,代碼如下:
/**************************************************
* example4.c
* Author: T-bagwell
*
* Compile:gcc -Wall example4.c -o example4
*************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
int print_screen(char *buf,int width,int height);
char *fb_addr;
unsigned fb_size;
int main(int argc, char *argv[])
{
int screen_fbd=0;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char *env=NULL;
short *color_white;
if(!(env = getenv("FRAMEBUFFER")))
{
env = "/dev/fb0";
}
screen_fbd = open(env, O_RDWR);
if(screen_fbd < 0)
{
printf("liuqi Error Opening FrameBuffer Device:%s\r\n", env);
return 0;
}
else
{
printf("Success Opening FrameBuffer Device:%s\r\n",env);
}
if(ioctl(screen_fbd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
{
printf("Error Reading Screen Info FSCREENINFO.\n");
close(screen_fbd);
return 0;
}
if(ioctl(screen_fbd, FBIOGET_VSCREENINFO, &fb_var) == -1)
{
printf("Error Reading Screen Info VSCREENINFO.\n");
close(screen_fbd);
return 0;
}
fb_size = fb_var.yres * fb_fix.line_length;
fb_addr = (char *)mmap(NULL, fb_size, PROT_READ|PROT_WRITE,MAP_SHARED, screen_fbd, 0);
color_white=(char*)malloc(fb_var.yres * fb_fix.line_length);
memset(color_white,0xFF,fb_var.yres * fb_fix.line_length);
print_screen(color_white,fb_var.xres,fb_var.yres);
if (!fb_addr)
exit(1);
free(color_white);
return 0;
}
/*********************************************************
* function: print_screen
*args
* buf: the address of the buffer
* width: the width of the framebuffer
* height: the height of the framebuffer
********************************************************/
int print_screen(char *buf,int width,int height)
{
short *t_data = (short *)buf;
short *t_fb_addr = (short *)fb_addr;
int bytew= width<<1;
while(--height >= 0)
{
memcpy(t_fb_addr,t_data,bytew);
t_fb_addr += width;
t_data += width;
}
}
這部分代碼實(shí)現(xiàn)的是在屏幕中畫(huà)出一個(gè)白色的界面,其中,最關(guān)鍵的部分是在print_screen函數(shù)中,從main到print_screen中需要將一個(gè)buffer,寬度和高度傳給print_screen,當(dāng)print_screen得到相關(guān)的參數(shù)后,將會(huì)在framebuffer中畫(huà)對(duì)應(yīng)的顏色,也就是memcpy(t_fb_addr,t_data,bytew);這句話是畫(huà)一行的顏色,當(dāng)然,這個(gè)前提是從main中傳進(jìn)來(lái)的buffer也是16位色的值。當(dāng)畫(huà)完一行以后,將buffer指針下移一行,直到畫(huà)完framebuffer最后一行為止。畫(huà)出的圖象會(huì)顯示在屏幕中,如圖:[attach]229399[/attach]
接下來(lái)可以增加一些功能,例如畫(huà)線功能:
1 /**************************************************
2 * example5.c
3 * Author: T-bagwell
4 *
5 * Compile:gcc -Wall example5.c -o example5
6 *************************************************/
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <linux/fb.h>
13 #include <errno.h>
14 #include <sys/mman.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/ioctl.h>
18
19 int print_screen(short *buf,int width,int height);
20 void draw_hline(short *buffer,int x,int y,int maxy,int maxx);
21 char *fb_addr;
22 unsigned fb_size;
23
24 int main(int argc, char *argv[])
25 {
26 int screen_fbd=0;
27 struct fb_fix_screeninfo fb_fix;
28 struct fb_var_screeninfo fb_var;
29 char *env=NULL;
30 short *color_white;
31
32 if(!(env = getenv("FRAMEBUFFER")))
33 {
34 env = "/dev/fb0";
35 }
36
37 screen_fbd = open(env, O_RDWR);
38
39 if(screen_fbd < 0)
40 {
41 return 0;
42 }
43
44 if(ioctl(screen_fbd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
45 {
46 close(screen_fbd);
47 return 0;
48 }
49
50 if(ioctl(screen_fbd, FBIOGET_VSCREENINFO, &fb_var) == -1)
51 {
52 close(screen_fbd);
53 return 0;
54 }
55
56 fb_size = fb_var.yres * fb_fix.line_length;
57 fb_addr = (char *)mmap(NULL, fb_size, PROT_READ|PROT_WRITE,MAP_SHARED, screen_fbd, 0);
58 color_white=(char *)malloc(fb_var.yres * fb_fix.line_length);
59 draw_hline(color_white,0,30,fb_var.yres,fb_var.xres);
60 print_screen(color_white,fb_var.xres,fb_var.yres);
61 if (!fb_addr)
62 exit(1);
63 free(color_white);
64 return 0;
65 }
66
67 /*********************************************************
68 * function: print_screen
69 *args
70 * buf: the address of the buffer
71 * width: the width of the framebuffer
72 * height: the height of the framebuffer
73 ********************************************************/
74 int print_screen(short *buf,int width,int height)
75 {
76 short *t_data = (short *)buf;
77 short *t_fb_addr = (short *)fb_addr;
78 int bytew= width<<1;
79 while(--height >= 0)
80 {
81 memcpy(t_fb_addr,t_data,bytew);
82 t_fb_addr += width;
83 t_data += width;
84 }
85 return 0;
86 }
87
88 /*********************************************************
89 * function: draw_hline
90 *args
91 * line_buffer: the address of the buffer
92 * x: the x of the line start point on the framebuffer
93 * y: the y of the line start point on the framebuffer
94 * maxy: the height of the framebuffer
95 * maxx: the width of the framebuffer
96 ********************************************************/
97 void draw_hline(short *line_buffer,int x,int y,int maxy,int maxx)
98 {
99 int i=0,j=0;
100
101 for(j=0;j<maxy;j++)
102 {
103 if(j==y)
104 {
105 for(i=0;i<maxx;i++)
106 {
107 *line_buffer++=0xf800;
108 }
109 }
110 else
111 {
112 for(i=0;i<maxx;i++)
113 {
114 *line_buffer++=0xffff;
115 }
116 }
117 }
118 return ;
119 }
上述代碼實(shí)現(xiàn)了在屏幕中坐標(biāo)為x坐標(biāo)為0,y坐標(biāo)為30處畫(huà)一條紅色的橫線,當(dāng)然,顏色值可以作為參數(shù)進(jìn)行傳遞,只要對(duì)上面的函數(shù)進(jìn)行少量的修改即可。手累了,先寫(xiě)這么點(diǎn)吧。轉(zhuǎn)帖請(qǐng)注明
參考部分: baidu貼吧(RGB部分的一小部分)
frambuffer部分在Linuxkernel的Documents部分有詳細(xì)講解
[ 本帖最后由 T-bagwell 于 2009-3-30 20:22 編輯 ]