wordpress 把賬號(hào)名改成昵稱公司seo排名優(yōu)化
之前獲取LCD屏幕參數(shù)信息時(shí)了解到,LCD屏是 FrameBuffer 設(shè)備,操作 FrameBuffer 設(shè)備 其實(shí)就是在讀寫 /dev/fb0 文件。除此之外,LCD屏上包含多個(gè)像素點(diǎn),繪制點(diǎn)、線、矩形框本質(zhì)是在修改這些像素點(diǎn)的顏色。
目錄
1、定義 lcd_color 結(jié)構(gòu)體
2、獲取LCD設(shè)備參數(shù)信息
3、mmap 建立顯存映射
(1) 為什么要建立顯存映射?
(2) 代碼實(shí)現(xiàn)??
3、定義繪制函數(shù)
4、完整代碼
1、定義 lcd_color 結(jié)構(gòu)體
為了后續(xù)方便傳遞顏色,這里定義一個(gè) lcd_color 結(jié)構(gòu)體,結(jié)構(gòu)體聲明如下。?
struct lcd_color
{u_int8_t red;u_int8_t green;u_int8_t blue;
};
我們要如何將顏色傳遞給LCD屏呢?根據(jù)我們之前獲取到的屏幕信息,LCD屏顏色格式是RGB565。我們改變像素點(diǎn)顏色,實(shí)際上就是傳遞一個(gè)值。
這個(gè)值低5位表示藍(lán)色,中間6位表示綠色,高5位表示紅色,因此,我們拿到R、G、B對(duì)應(yīng)的數(shù)值后需要將他們按下面的方式拼接。
#define RGB565(color) (color->blue & 0x05) | \((color->green & 0x06) << 5) | \((color->red & 0x05) << 11)
2、獲取LCD設(shè)備參數(shù)信息
這里就不再贅述,請(qǐng)參考:獲取LCD屏幕參數(shù)信息
struct fb_fix_screeninfo fb_fix; // 固定參數(shù)信息
struct fb_var_screeninfo fb_var; // 可變參數(shù)信息int fd = open("/dev/fb0", O_RDWR);
if (fd < 0)
{perror("open fb failed");exit(-1);
}ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix); // 獲取固定參數(shù)信息
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var); // 獲取可變參數(shù)信息
3、mmap 建立顯存映射
(1) 為什么要建立顯存映射?
建立顯存映射的目的是提升IO效率。實(shí)際上使用read/write操作顯存也是可以的,然而數(shù)據(jù)量較大的時(shí)候,普通IO的方式效率較低。一般顯示的圖像是動(dòng)態(tài)變化的,圖像數(shù)據(jù)需要不斷被更新,這種情況下的數(shù)據(jù)量較大,建議采用存儲(chǔ)映射IO方式。
mmap 函數(shù)的詳細(xì)使用可以參考:mmap函數(shù)詳解
(2) 代碼實(shí)現(xiàn)??
值得一提的是,雖然最開(kāi)始畫的LCD示意圖是一個(gè)矩形,但是在內(nèi)存中還是線性存儲(chǔ)的,顯存的起始地址為?screen_base ,類型必須為 u_int16_t*? 或者為 unsigned short*,因?yàn)橹羔橆愋蜎Q定了移動(dòng)一次的步長(zhǎng),所以每次?screen_base + 1 的時(shí)候,實(shí)際上移動(dòng)了16bit。(如果是 int,即32bit,screen_base + 1 時(shí)將會(huì)移動(dòng) 32 bit)
u_int16_t *screen_base = NULL; // 映射基地址(全局變量)int main(int args, char **argv)
{struct fb_fix_screeninfo fb_fix; // 固定參數(shù)信息struct fb_var_screeninfo fb_var; // 可變參數(shù)信息// ... ... 獲取可變參數(shù)信息size_t len = fb_fix.line_length * fb_var.yres;screen_base = (u_int16_t *)mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);if ((void*)screen_base == MAP_FAILED){perror("mmap failed");exit(-2);}
}
3、定義繪制函數(shù)
繪制點(diǎn)
繪制點(diǎn)的關(guān)鍵在于確定像素點(diǎn)的位置,然后賦予顏色。
/********************************************************************* 函數(shù)名稱: lcd_draw_point* 功能描述: 在LCD屏上繪制一個(gè)點(diǎn)* 輸入?yún)?shù): x, y, color* 返 回 值: 無(wú)********************************************************************/
void lcd_draw_point(uint x, uint y, struct lcd_color* color)
{screen_base[y*width + x] = RGB565(color); // 這里的 width 是全局變量,對(duì)應(yīng)LCD屏的每行的像素點(diǎn)個(gè)數(shù)
}
繪制線
/********************************************************************* 函數(shù)名稱: lcd_draw_line* 功能描述: 在LCD屏上繪制一根線* 輸入?yún)?shù): 其實(shí)就是繪制一個(gè)實(shí)心的矩形start_x: 起始橫坐標(biāo) start_y: 起始縱坐標(biāo)line_width: 線的寬度 line_height: 線的高度color: 線的顏色* 返 回 值: 無(wú)********************************************************************/
void lcd_draw_line(uint start_x, uint start_y, uint line_width, uint line_height, struct lcd_color* color)
{for (size_t i = start_y; i < start_y + line_height; i++){for (size_t j = start_x; j < start_x + line_width; j++){lcd_draw_point(j, i, color);}}
}
繪制矩形框
/********************************************************************* 函數(shù)名稱: lcd_draw_rect* 功能描述: 在LCD屏上繪制一個(gè)矩形框* 輸入?yún)?shù): 其實(shí)就是繪制一個(gè)實(shí)心的矩形start_x: 起始橫坐標(biāo) start_y: 起始縱坐標(biāo)rect_width: 矩形框的寬度 rect_height: 矩形框的高度line_width:線的粗細(xì)程度color: 線的顏色* 返 回 值: 無(wú)********************************************************************/
void lcd_draw_rect(uint start_x, uint start_y, uint rect_width, uint rect_height, uint line_width, struct lcd_color* color)
{lcd_draw_line(start_x, start_y, rect_width, line_width, color); // 上lcd_draw_line(start_x, start_y + rect_height - line_width - 1, rect_width, line_width, color); // 下lcd_draw_line(start_x, start_y + line_width, line_width, rect_height - line_width, color); // 左lcd_draw_line(start_x + rect_width - line_width - 1, start_y + line_width, line_width, rect_height - line_width, color); // 右
}
4、完整代碼
由于只分配了 5 bit來(lái)表示紅色,所以顯示出來(lái)的紅色可能偏暗。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>u_int16_t width = 0;
u_int16_t height = 0;u_int16_t *screen_base = NULL; // 映射基地址typedef unsigned int uint;
struct lcd_color
{u_int8_t red;u_int8_t green;u_int8_t blue;
};
#define RGB565(color) (color->blue & 0x05) | \((color->green & 0x06) << 5) | \((color->red & 0x05) << 11)/********************************************************************* 函數(shù)名稱: lcd_draw_point* 功能描述: 在LCD屏上繪制一個(gè)點(diǎn)* 輸入?yún)?shù): x, y, color* 返 回 值: 無(wú)********************************************************************/
void lcd_draw_point(uint x, uint y, struct lcd_color* color)
{screen_base[y*width + x] = RGB565(color);
}/********************************************************************* 函數(shù)名稱: lcd_draw_line* 功能描述: 在LCD屏上繪制一根線* 輸入?yún)?shù): start_x, start_y, line_width, line_height, color* 返 回 值: 無(wú)********************************************************************/
void lcd_draw_line(uint start_x, uint start_y, uint line_width, uint line_height, struct lcd_color* color)
{for (size_t i = start_y; i < start_y + line_height; i++){for (size_t j = start_x; j < start_x + line_width; j++){lcd_draw_point(j, i, color);}}
}/********************************************************************* 函數(shù)名稱: lcd_draw_rect* 功能描述: 在LCD屏上繪制一個(gè)矩形框* 輸入?yún)?shù): start_x, start_y, rect_width, rect_height, line_width, color* 返 回 值: 無(wú)********************************************************************/
void lcd_draw_rect(uint start_x, uint start_y, uint rect_width, uint rect_height, uint line_width, struct lcd_color* color)
{lcd_draw_line(start_x, start_y, rect_width, line_width, color); // 上lcd_draw_line(start_x, start_y + rect_height - line_width - 1, rect_width, line_width, color); // 下lcd_draw_line(start_x, start_y + line_width, line_width, rect_height - line_width, color); // 左lcd_draw_line(start_x + rect_width - line_width - 1, start_y + line_width, line_width, rect_height - line_width, color); // 右
}int main(int args, char **argv)
{struct fb_fix_screeninfo fb_fix; // 固定參數(shù)信息struct fb_var_screeninfo fb_var; // 可變參數(shù)信息int fd = open("/dev/fb0", O_RDWR);if (fd < 0){perror("open fb failed");exit(-1);}ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);width = fb_var.xres;height = fb_var.yres;size_t len = fb_fix.line_length * fb_var.yres;screen_base = (u_int16_t *)mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);if ((void*)screen_base == MAP_FAILED){perror("mmap failed");exit(-2);}// 將整個(gè)屏幕填充成紅色for (size_t i = 0; i < height; i++){for (size_t j = 0; j < width; j++){struct lcd_color color = {31, 0, 0};lcd_draw_point(j, i, &color);}}// 繪制一根長(zhǎng)為width,寬為 height/2 的線struct lcd_color line_color = {0, 31, 0};lcd_draw_line(0, 0, width, height/2, &line_color);// 繪制一個(gè)長(zhǎng)為width,寬為height,線粗為10的矩形框struct lcd_color rect_color = {31, 31, 0};lcd_draw_rect(0, 0, width, height, 10, &rect_color);return 0;
}