wordpress 把賬號名改成昵稱公司seo排名優(yōu)化
之前獲取LCD屏幕參數(shù)信息時了解到,LCD屏是 FrameBuffer 設備,操作 FrameBuffer 設備 其實就是在讀寫 /dev/fb0 文件。除此之外,LCD屏上包含多個像素點,繪制點、線、矩形框本質(zhì)是在修改這些像素點的顏色。
目錄
1、定義 lcd_color 結(jié)構(gòu)體
2、獲取LCD設備參數(shù)信息
3、mmap 建立顯存映射
(1) 為什么要建立顯存映射?
(2) 代碼實現(xiàn)??
3、定義繪制函數(shù)
4、完整代碼
1、定義 lcd_color 結(jié)構(gòu)體
為了后續(xù)方便傳遞顏色,這里定義一個 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。我們改變像素點顏色,實際上就是傳遞一個值。
這個值低5位表示藍色,中間6位表示綠色,高5位表示紅色,因此,我們拿到R、G、B對應的數(shù)值后需要將他們按下面的方式拼接。
#define RGB565(color) (color->blue & 0x05) | \((color->green & 0x06) << 5) | \((color->red & 0x05) << 11)
2、獲取LCD設備參數(shù)信息
這里就不再贅述,請參考:獲取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效率。實際上使用read/write操作顯存也是可以的,然而數(shù)據(jù)量較大的時候,普通IO的方式效率較低。一般顯示的圖像是動態(tài)變化的,圖像數(shù)據(jù)需要不斷被更新,這種情況下的數(shù)據(jù)量較大,建議采用存儲映射IO方式。
mmap 函數(shù)的詳細使用可以參考:mmap函數(shù)詳解
(2) 代碼實現(xiàn)??
值得一提的是,雖然最開始畫的LCD示意圖是一個矩形,但是在內(nèi)存中還是線性存儲的,顯存的起始地址為?screen_base ,類型必須為 u_int16_t*? 或者為 unsigned short*,因為指針類型決定了移動一次的步長,所以每次?screen_base + 1 的時候,實際上移動了16bit。(如果是 int,即32bit,screen_base + 1 時將會移動 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ù)
繪制點
繪制點的關(guān)鍵在于確定像素點的位置,然后賦予顏色。
/********************************************************************* 函數(shù)名稱: lcd_draw_point* 功能描述: 在LCD屏上繪制一個點* 輸入?yún)?shù): x, y, color* 返 回 值: 無********************************************************************/
void lcd_draw_point(uint x, uint y, struct lcd_color* color)
{screen_base[y*width + x] = RGB565(color); // 這里的 width 是全局變量,對應LCD屏的每行的像素點個數(shù)
}
繪制線
/********************************************************************* 函數(shù)名稱: lcd_draw_line* 功能描述: 在LCD屏上繪制一根線* 輸入?yún)?shù): 其實就是繪制一個實心的矩形start_x: 起始橫坐標 start_y: 起始縱坐標line_width: 線的寬度 line_height: 線的高度color: 線的顏色* 返 回 值: 無********************************************************************/
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屏上繪制一個矩形框* 輸入?yún)?shù): 其實就是繪制一個實心的矩形start_x: 起始橫坐標 start_y: 起始縱坐標rect_width: 矩形框的寬度 rect_height: 矩形框的高度line_width:線的粗細程度color: 線的顏色* 返 回 值: 無********************************************************************/
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來表示紅色,所以顯示出來的紅色可能偏暗。
#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屏上繪制一個點* 輸入?yún)?shù): x, y, color* 返 回 值: 無********************************************************************/
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* 返 回 值: 無********************************************************************/
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屏上繪制一個矩形框* 輸入?yún)?shù): start_x, start_y, rect_width, rect_height, line_width, color* 返 回 值: 無********************************************************************/
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);}// 將整個屏幕填充成紅色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);}}// 繪制一根長為width,寬為 height/2 的線struct lcd_color line_color = {0, 31, 0};lcd_draw_line(0, 0, width, height/2, &line_color);// 繪制一個長為width,寬為height,線粗為10的矩形框struct lcd_color rect_color = {31, 31, 0};lcd_draw_rect(0, 0, width, height, 10, &rect_color);return 0;
}