1. 前言
這是基于Linux系統(tǒng)開(kāi)發(fā)板設(shè)計(jì)一個(gè)小項(xiàng)目-數(shù)碼相冊(cè),在LCD屏上可以顯示完成常見(jiàn)的圖片顯示,翻頁(yè)、旋轉(zhuǎn)、縮放等功能。
開(kāi)發(fā)板采用友善之臂的Tiny4412開(kāi)發(fā)板,CPU是三星的4412,最高主頻1.5GHZ。板子配有8G的EMMC,2G的DDR,運(yùn)行Linux3.5內(nèi)核,文件系統(tǒng)采用busybox制作的最小根文件系統(tǒng),不帶圖形桌面框架,系統(tǒng)是最小最精簡(jiǎn)的系統(tǒng)。
要完成整個(gè)項(xiàng)目相冊(cè)的功能,需要的東西還是比較多的,首先要編譯安裝各種圖片庫(kù): libjpg,giflib,libpng等等,圖片需要縮放,需要支持縮放算法;LCD界面上的文字,時(shí)間采用矢量字體顯示的,還需要交叉編譯安裝freetype庫(kù)。然后硬件層,需要編寫(xiě)LCD屏驅(qū)動(dòng)(幀緩沖框架),觸摸屏驅(qū)動(dòng)(輸入子系統(tǒng)),三軸加速度計(jì)驅(qū)動(dòng)(mma7660飛思卡爾的芯片)。
整個(gè)項(xiàng)目的代碼布局如下:
如果把整個(gè)項(xiàng)目代碼寫(xiě)完一遍,基本上Linux驅(qū)動(dòng)、應(yīng)用層編程都能夠熟悉一遍。
涉及的技術(shù)點(diǎn)總結(jié):
(1)png、jpg、gif等各種開(kāi)源圖片庫(kù)的編譯安裝,完成對(duì)應(yīng)圖片解碼,顯示。整個(gè)過(guò)程里還需要懂得png、jpg、GIF圖片的構(gòu)造原理,如何讀取數(shù)據(jù),如何提取rgb數(shù)據(jù),最終在LCD屏上完成顯示。
(2)LCD驅(qū)動(dòng)編寫(xiě),首先得了解Linux幀緩沖框架原理,明白LCD屏的時(shí)序,才能編寫(xiě)驅(qū)動(dòng)。應(yīng)用層需要明白如何針對(duì)幀緩沖框架完成應(yīng)用編程,實(shí)現(xiàn)畫(huà)點(diǎn)、畫(huà)線、文字等基本顯示。
(3)觸摸屏驅(qū)編寫(xiě),觸摸屏驅(qū)動(dòng)芯片是FT5X06,這個(gè)IIC接口的芯片,編寫(xiě)觸摸屏驅(qū)動(dòng)需要熟悉IIC子系統(tǒng)、輸入子系統(tǒng)、內(nèi)核中斷、工作隊(duì)列等框架,因?yàn)橛|摸屏芯片支持筆中斷,需要注冊(cè)中斷,在中斷服務(wù)函數(shù)里調(diào)用工作隊(duì)列實(shí)時(shí)讀取數(shù)據(jù)。 應(yīng)用層還需要適配tslib庫(kù)接口,讓tslib去讀取輸入子系統(tǒng)上傳的坐標(biāo),還能完成校準(zhǔn),測(cè)試等功能,最終在自己工程內(nèi)再封裝函數(shù)去讀取tslib接口返回的坐標(biāo)數(shù)據(jù),完成觸屏屏邏輯處理。
(4)三軸加速度mma7660驅(qū)動(dòng)編寫(xiě),通過(guò)三軸加速度測(cè)量開(kāi)發(fā)板的姿態(tài),完成數(shù)碼相冊(cè)里圖片的自動(dòng)上下左右翻轉(zhuǎn),手機(jī)相冊(cè)都有這個(gè)功能,橫豎屏切換。
(5)按鍵驅(qū)動(dòng)編寫(xiě),數(shù)碼相冊(cè)支持按鍵翻頁(yè)、觸摸屏滑動(dòng)翻頁(yè)、自動(dòng)圖片播放(幻燈片)等功能,所以還需要編寫(xiě)按鍵驅(qū)動(dòng),按鍵驅(qū)動(dòng)采用雜項(xiàng)字符設(shè)備編寫(xiě),通過(guò)ioctl接口上傳按鍵值。
(6)矢量字體庫(kù)編譯安裝,界面上需要顯示各種文字提示、時(shí)間等信息。用到矢量字體ttc,ttf等。
圖片的翻頁(yè)采用雙向鏈表完成,支持左右翻頁(yè),更新鏈表時(shí),將指定目錄下所有圖片加到雙向鏈表里,通過(guò)按鍵、觸摸屏、自動(dòng)播放時(shí),從鏈表里獲取圖片地址完成顯示。
2. 涉及到源代碼
2.1 png圖片顯示
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LCD_DEVICE "/dev/fb0"
int lcd_fd;
struct fb_var_screeninfo vinfo;//可變參數(shù)
struct fb_fix_screeninfo finfo; //固定參數(shù)
unsigned char *lcd_mem=NULL; //LCD首地址
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
int image_height;
int image_width;
unsigned char *image_buffer[4];
int video_fd;
void LCD_DrawPoint(u32 x,u32 y,u32 c);
u32 LCD_ReadPoint(u32 x,u32 y);
/*顯示PNG文件*/
int display_png(u32 x,u32 y,char* filename)
{
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type, number_passes;
u32 i,j;
u32 x0;
u32 rgb24,b_rgb24;
u8 r,g,b,a;
u8 b_r,b_g,b_b;
u8 R,G,B;
if((fp = fopen(filename,"rb")) == NULL)
{
printf("%s 文件打開(kāi)失敗.\n",filename);
return -1;
}
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL);
/*需要分配/初始化內(nèi)存以獲取圖像信息*/
info_ptr = png_create_info_struct(png_ptr);
/*設(shè)置PNG圖片的文件指針*/
png_init_io(png_ptr,fp);
png_read_info(png_ptr,info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL);
printf("圖片寬度:[%4d]\n",width);
printf("圖片高度:[%4d]\n",height);
printf("顏色位數(shù):[%4d]\n",bit_depth); //ARGB
/*讀取圖像的最簡(jiǎn)單方法:*/
png_bytep row_pointers[height];
/*清除指針數(shù)組*/
for(i = 0; i < height; i++)
{
row_pointers[i] = NULL;
row_pointers[i] = malloc(width * 4); /* RGBA */
memset(row_pointers[i], 0, width * 4);
}
/*讀取整個(gè)PNG圖像*/
png_read_image(png_ptr,row_pointers);
for(i = 0; i < height; i++)
{
x0=x;
for(j = 0; j < width * 4; j += 4)
{
/*得到圖片顏色*/
r=row_pointers[i][j + 0];
g=row_pointers[i][j + 1];
b=row_pointers[i][j + 2];
a=row_pointers[i][j + 3];
/*讀取當(dāng)前屏幕點(diǎn)的背景顏色*/
b_rgb24=LCD_ReadPoint(x0,y);
b_r=b_rgb24>>16&0xFF;
b_g=b_rgb24>>8&0xFF;
b_b=b_rgb24>>0&0xFF;
/*合成屏幕背景顏色*/
R = (unsigned char)(r * (a / 255.0) + (b_r * (255 - a)) / 255.0);
G = (unsigned char)(g * (a / 255.0) + (b_g * (255 - a)) / 255.0);
B = (unsigned char)(b * (a / 255.0) + (b_b * (255 - a)) / 255.0);
/*顯示數(shù)據(jù)*/
rgb24=R<<16|G<<8|B;
LCD_DrawPoint(x0,y,rgb24);
/*坐標(biāo)自增*/
x0++;
}
y++;
}
/* 讀取文件的其余部分,并在info_ptr中獲取其他塊-必需*/
png_read_end(png_ptr, info_ptr);
/*讀取后清理,并釋放已分配的所有內(nèi)存-必需*/
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
/* 統(tǒng)一釋放內(nèi)存 */
for(i = 0; i < height; i++)
{
free(row_pointers[i]);
}
/*關(guān)閉文件*/
fclose(fp);
return 0;
}
/*
函數(shù)功能: 封裝畫(huà)點(diǎn)函數(shù)
函數(shù)參數(shù): u32 x,u32 y,u16 c
*/
void LCD_DrawPoint(u32 x,u32 y,u32 c)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
*lcd_p=c;
}
/*
函數(shù)功能: 封裝讀點(diǎn)函數(shù)
函數(shù)參數(shù): u32 x,u32 y,u16 c
*/
u32 LCD_ReadPoint(u32 x,u32 y)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
return *lcd_p;
}
int main(int argc,char **argv)
{
int err;
if(argc!=2)
{
printf("./app \n");
return 0;
}
/*1. 打開(kāi)設(shè)備文件*/
lcd_fd=open(LCD_DEVICE,O_RDWR);
if(lcd_fd<0)
{
printf("%s 設(shè)備文件打開(kāi)失敗.\n",LCD_DEVICE);
return 0;
}
/*2. 獲取可變參數(shù)*/
ioctl(lcd_fd,FBIOGET_VSCREENINFO,&vinfo);
printf("x=%d,y=%d,pixel=%d\n",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
/*3. 獲取固定參數(shù)*/
ioctl(lcd_fd,FBIOGET_FSCREENINFO,&finfo);
printf("smem_len=%d\n",finfo.smem_len);
printf("line_length=%d\n",finfo.line_length);
/*4. 映射LCD地址*/
lcd_mem=mmap(NULL,finfo.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
if(lcd_mem==NULL)
{
printf("映射LCD地址失敗.\n");
return -1;
}
//memset(lcd_mem,0xFFFFFF,finfo.smem_len);
/*5. 顯示PN圖片*/
display_png(0,0,argv[1]);
close(lcd_fd);
return 0;
}
復(fù)制代碼
2.2 jpg圖片顯示
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
?
#include
#include
?
struct fb_var_screeninfo var; //可變參數(shù)
struct fb_fix_screeninfo fix; //固定參數(shù)
unsigned char *fb_mem=NULL; //LCD屏的首地址
?
/*
函數(shù)功能: 畫(huà)點(diǎn)
*/
void Show_Pixel(int x,int y,int color)
{
unsigned int *lcd=(unsigned int *)(fb_mem+y*var.xres*var.bits_per_pixel/8+x*var.bits_per_pixel/8);
*lcd=color; //顏色賦值
}
?
?
//顯示JPEG jpeglib
int LCD_ShowJPEG(int x,int y,unsigned char *file)
{
struct jpeg_decompress_struct cinfo; //存放圖像的數(shù)據(jù)
struct jpeg_error_mgr jerr; //存放錯(cuò)誤信息
FILE *infile;
unsigned int *dst=(unsigned int *)fb_mem;
unsigned char *buffer;
unsigned int i;
unsigned int color;
/* 打開(kāi)圖像文件*/
if ((infile = fopen(file, "rb")) == NULL)
{
perror("jpeg文件打開(kāi)失敗!\n");
return -1;
}
?
/*init jpeg壓縮對(duì)象錯(cuò)誤處理程序*/
cinfo.err = jpeg_std_error(&jerr); //初始化標(biāo)準(zhǔn)錯(cuò)誤,用來(lái)存放錯(cuò)誤信息
jpeg_create_decompress(&cinfo); //創(chuàng)建解壓縮結(jié)構(gòu)信息
/*將jpeg壓縮對(duì)象綁定到infile*/
jpeg_stdio_src(&cinfo, infile);
?
/*讀jpeg頭*/
jpeg_read_header(&cinfo, TRUE);
/*開(kāi)始解壓*/
jpeg_start_decompress(&cinfo);
printf("JPEG圖片高度: %d\n",cinfo.output_height);
printf("JPEG圖片寬度: %d\n",cinfo.output_width);
printf("JPEG圖片顏色位數(shù)(字節(jié)單位): %d\n",cinfo.output_components);
/*為一條掃描線上的像素點(diǎn)分配存儲(chǔ)空間,一行一行的解碼*/
buffer = (unsigned char *)malloc(cinfo.output_width *cinfo.output_components);
//將圖片內(nèi)容顯示到framebuffer上,cinfo.output_scanline表示當(dāng)前行的位置,讀取數(shù)據(jù)是會(huì)自動(dòng)增加
while(cinfo.output_scanline < cinfo.output_height)
? ? {
? ? ? ? ? //讀取一行的數(shù)據(jù) ? ?
? ? ? ? ?jpeg_read_scanlines(&cinfo,&buffer,1);
? for(i = 0; i;>
2.3 gif圖片顯示
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct fb_var_screeninfo var; //可變參數(shù)
struct fb_fix_screeninfo fix; //固定參數(shù)
unsigned char *fb_mem=NULL; //LCD屏的首地址
/*
函數(shù)功能: 畫(huà)點(diǎn)
*/
void LCD_WritePoint(int x,int y,int color)
{
unsigned int *lcd=(unsigned int *)(fb_mem+y*var.xres*var.bits_per_pixel/8+x*var.bits_per_pixel/8);
*lcd=color; //顏色賦值
}
//幀緩沖顯示
void FrameBufferDraw(int x,int y,int image_w,int image_h,unsigned char *rgbBuf)
{
int w,h;
unsigned char r,g,b;
unsigned int c;
/*將圖像數(shù)據(jù)顯示在LCD屏幕上*/
unsigned char *rgb_p=rgbBuf;
for(h=0;hColors[GifRow[idxW]];
*rgbBuf++ = ColorMapEntry->Blue;
*rgbBuf++ = ColorMapEntry->Green;
*rgbBuf++ = ColorMapEntry->Red;
}
}
}
//顯示GIF圖像
int LCD_DisplayGIF(int x,int y,unsigned char *file)
{
int error=0;
int size;
int i;
GifRowType *Buffer;
GifFileType *fp;
/*1. 打開(kāi)圖片文件*/
fp=DGifOpenFileName(file,&error);
if(fp==NULL)return -1;
printf("GIF圖片尺寸:%dx%d\n",fp->SWidth,fp->SHeight);
/*2. 內(nèi)存空間申請(qǐng)、初始化*/
Buffer=(GifRowType*)malloc(fp->SHeight*sizeof(GifRowType));
/*一行字節(jié)大小*/
size = fp->SWidth*sizeof(GifPixelType);
Buffer[0]=(GifRowType)malloc(size);
/*將其顏色設(shè)置為BackGround*/
for(i=0;iSWidth;i++)
{
Buffer[0][i]=fp->SBackGroundColor;
}
/*分配其他行,并將它們的顏色也設(shè)置為背景 */
for(i=1;iSHeight;i++)
{
Buffer[i]=(GifRowType)malloc(size);
memcpy(Buffer[i],Buffer[0],size);
}
/*3. 顯示圖片*/
ColorMapObject *colorMap=NULL;
GifByteType *extension=NULL;
GifRecordType gRecordType=UNDEFINED_RECORD_TYPE;
int InterlacedOffset[]={0,4,2,1}; // The way Interlaced image should
int InterlacedJumps[]={8,8,4,2}; // be read - offsets and jumps...
unsigned char rgbBuf[800 * 480]={0};
int extCode = 0;
int row = 0;
int col = 0;
int width = 0;
int height = 0;
int iW = 0;
int iH = 0;
do
{
if(DGifGetRecordType(fp,&gRecordType)==GIF_ERROR)break;
switch(gRecordType)
{
case IMAGE_DESC_RECORD_TYPE:
if(DGifGetImageDesc(fp)==GIF_ERROR)break;
row=fp->Image.Top;
col=fp->Image.Left;
width=fp->Image.Width;
height=fp->Image.Height;
if(fp->Image.Interlace)
{
for(iH=0;iH<4;iH++)
{
for(iW=row+InterlacedOffset[iH];iWImage.ColorMap?fp->Image.ColorMap:fp->SColorMap);
if(colorMap==NULL)
{
break;
}
GifBufferToRgb888(colorMap,rgbBuf,Buffer,fp->SWidth,fp->SHeight);
//將圖像顯示在LCD屏上
FrameBufferDraw(x,y,fp->SWidth,fp->SHeight,rgbBuf);
//幀間隔時(shí)間
usleep(1000*50);
break;
case EXTENSION_RECORD_TYPE:
/* 跳過(guò)文件中的所有擴(kuò)展塊*/
if(DGifGetExtension(fp,&extCode,&extension)==GIF_ERROR)break;
while(extension!=NULL)
{
if(DGifGetExtensionNext(fp, &extension) == GIF_ERROR)break;
}
break;
case TERMINATE_RECORD_TYPE:
break;
default:
break;
}
}while(gRecordType!=TERMINATE_RECORD_TYPE);
/*4. 釋放空間*/
for(i =0;iSHeight;i++)
{
free(Buffer[i]);
}
free(Buffer);
DGifCloseFile(fp,&error);
return 0;
}
int main(int argc,char **argv)
{
if(argc!=2)
{
printf("./app \n");
return 0;
}
int fd=open("/dev/fb0",O_RDWR);
if(fd<0)
{
perror("設(shè)備文件打開(kāi)失敗");
return 0;
}
/*1. 獲取LCD屏的可變形參*/
ioctl(fd,FBIOGET_VSCREENINFO,&var);
printf("分辨率:%d*%d\n",var.xres,var.yres);
printf("像素點(diǎn)位數(shù):%d\n",var.bits_per_pixel);
/*2. 獲取LCD屏的固定形參*/
ioctl(fd,FBIOGET_FSCREENINFO,&fix);
printf("映射的長(zhǎng)度:%d\n",fix.smem_len);
printf("一行的字節(jié)數(shù):%d\n",fix.line_length);
/*3. 映射LCD緩沖區(qū)地址到進(jìn)程空間*/
fb_mem=mmap(NULL,fix.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(fb_mem==NULL)
{
perror("空間映射失敗!\n");
return 0;
}
/*4. 控制顯示屏*/
memset(fb_mem,0xFFFFFF,fix.smem_len); //將屏幕清屏為白色
while(1)
{
printf("GIF圖片顯示狀態(tài):%d\n",LCD_DisplayGIF(100,100,argv[1]));
}
munmap(fb_mem,fix.smem_len);
close(fd);
return 0;
}
復(fù)制代碼圖片文件>+height;iw+=interlacedjumps[ih])>;h++)>
2.4 矢量字體調(diào)用顯示
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include FT_FREETYPE_H
#include FT_STROKER_H
#define LCD_DEVICE "/dev/fb0"
int lcd_fd;
struct fb_var_screeninfo vinfo;//可變參數(shù)
struct fb_fix_screeninfo finfo; //固定參數(shù)
unsigned char *lcd_mem=NULL; //LCD首地址
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
/*定義一個(gè)結(jié)構(gòu)體存放矢量字體的配置*/
struct FREE_TYPE_CONFIG
{
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_Vector pen; /* untransformed origin */
FT_Error error;
FT_BBox bbox;
FT_Glyph glyph;
};
struct FREE_TYPE_CONFIG FreeTypeConfig;
/*
函數(shù)功能: 封裝畫(huà)點(diǎn)函數(shù)
函數(shù)參數(shù): u32 x,u32 y,u16 c
*/
void LCD_DrawPoint(u32 x,u32 y,u32 c)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
*lcd_p=c;
}
/*
函數(shù)功能: 封裝讀點(diǎn)函數(shù)
函數(shù)參數(shù): u32 x,u32 y,u16 c
*/
u32 LCD_ReadPoint(u32 x,u32 y)
{
u32 *lcd_p=(u32*)(lcd_mem+vinfo.xres*vinfo.bits_per_pixel/8*y+x*vinfo.bits_per_pixel/8);
return *lcd_p;
}
/* LCD顯示矢量字體的位圖信息
* bitmap : 要顯示的字體的矢量位圖
* x : 顯示的x坐標(biāo)
* y : 顯示的y坐標(biāo)
*/
void LCD_DrawBitmap(FT_Bitmap* bitmap,FT_Int x,FT_Int y)
{
FT_Int i,j,p,q;
FT_Int x_max=x+bitmap->width;
FT_Int y_max=y+bitmap->rows;
/* 將位圖信息循環(huán)打印到屏幕上 */
for(i=x,p=0;ix_max)||(j>y_max)||(i<0)||(j<0))continue;
if(bitmap->buffer[q*bitmap->width+p]!=0)
{
LCD_DrawPoint(i, j,0xFF0033);
}
else
{
LCD_DrawPoint(i, j,0xFFFFFF);
}
}
}
}
/*
函數(shù)功能: 初始化FreeType配置
*/
int InitConfig_FreeType(char *font_file)
{
FT_Error error;
/*1. 初始化freetype庫(kù)*/
error=FT_Init_FreeType(&FreeTypeConfig.library);
if(error)
{
printf("freetype字體庫(kù)初始化失敗.\n");
return -1;
}
/*2. 打開(kāi)加載的字體文件*/
error=FT_New_Face(FreeTypeConfig.library,font_file,0,&FreeTypeConfig.face);
if(error)
{
printf("矢量字體文件加載失敗.\n");
return -2;
}
return 0;
}
/*
函數(shù)功能: 釋放FreeType配置
*/
void FreeType_Config(void)
{
FT_Done_Face(FreeTypeConfig.face);
FT_Done_FreeType(FreeTypeConfig.library);
}
/*
函數(shù)功能: 在LCD屏顯示一串文本數(shù)據(jù)
函數(shù)參數(shù):
u32 x 坐標(biāo)位置
u32 y 坐標(biāo)位置
u32 size 字體大小
wchar_t *text 顯示的文本數(shù)據(jù)
*/
int LCD_DrawText(u32 x,u32 y,u32 size,wchar_t *text)
{
FT_Error error;
int i = 0;
int bbox_height_min = 10000;
int bbox_height_max = 0;
/*3. 設(shè)置字符的像素的大小為size*size*/
error=FT_Set_Pixel_Sizes(FreeTypeConfig.face,size,0);
if(error)
{
printf("字符的像素大小設(shè)置失敗.\n");
return -1;
}
/*4. 設(shè)置字體文件的輪廓的插槽*/
FreeTypeConfig.slot=FreeTypeConfig.face->glyph;
/* 設(shè)置坐標(biāo)為原點(diǎn)坐標(biāo)
* 將LCD坐標(biāo)轉(zhuǎn)換成笛卡爾坐標(biāo)
* 單位是 1/64 Point
*/
FreeTypeConfig.pen.x=x*64;
FreeTypeConfig.pen.y=(vinfo.yres-size-y)*64;
/*5. 循環(huán)的將文字顯示出來(lái)*/
for(i=0;iFreeTypeConfig.bbox.yMin)bbox_height_min=FreeTypeConfig.bbox.yMin;
if(bbox_height_maxbitmap,
FreeTypeConfig.slot->bitmap_left,
vinfo.yres-FreeTypeConfig.slot->bitmap_top);
if(FreeTypeConfig.slot->bitmap_left+size*2>vinfo.xres)
{
FreeTypeConfig.pen.x=0; //更新X坐標(biāo)位置
FreeTypeConfig.pen.y=(vinfo.yres-size-y-size)*64; //更新Y坐標(biāo)位置
}
else
{
/* 更新原點(diǎn)坐標(biāo)位置 */
FreeTypeConfig.pen.x+=FreeTypeConfig.slot->advance.x;
FreeTypeConfig.pen.y+=FreeTypeConfig.slot->advance.y;
}
}
return 0;
}
int main(int argc,char **argv)
{
if(argc!=2)
{
printf("./app \n");
return 0;
}
/*1. 打開(kāi)設(shè)備文件*/
lcd_fd=open(LCD_DEVICE,O_RDWR);
if(lcd_fd<0)
{
printf("%s open error.\n",LCD_DEVICE);
return 0;
}
/*2. 獲取可變參數(shù)*/
ioctl(lcd_fd,FBIOGET_VSCREENINFO,&vinfo);
printf("x=%d,y=%d,pixel=%d\n",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
/*3. 獲取固定參數(shù)*/
ioctl(lcd_fd,FBIOGET_FSCREENINFO,&finfo);
printf("smem_len=%d\n",finfo.smem_len);
printf("line_length=%d\n",finfo.line_length);
/*4. 映射LCD地址*/
lcd_mem=mmap(NULL,finfo.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
if(lcd_mem==NULL)
{
printf("映射LCD地址失敗.\n");
return -1;
}
memset(lcd_mem,0xFFFFFF,finfo.smem_len);
/*5. 初始化配置FreeType*/
InitConfig_FreeType(argv[1]);
/*6. 在指定位置顯示文本*/
/*
wcslen() 函數(shù)用于計(jì)算寬字符的個(gè)數(shù),支持區(qū)分中文和英文字符,文本需要在UTF-8編碼下。
定義寬字符串示例:
wchar_t *wp=L"1234567890中國(guó)"; //12
printf("wcslen p:%d\n",wcslen(wp)); 返回值是12
*/
LCD_DrawText(50,56*0,56,L"北京萬(wàn)邦易嵌科技有限公司");
LCD_DrawText(150,56*1,56,L"www.wanbangee.com");
LCD_DrawText(200,56*3,48,L"FreeType矢量字體");
LCD_DrawText(150,56*5,80,L"Linux驅(qū)動(dòng)開(kāi)發(fā)");
/*7. 釋放FreeType配置*/
FreeType_Config();
close(lcd_fd);
return 0;
})bbox_height_max=freetypeconfig.bbox.ymax;>(text);i++)>;i++,p++)>
審核編輯:湯梓紅
;>-
lcd
+關(guān)注
關(guān)注
34文章
4411瀏覽量
167101 -
Linux
+關(guān)注
關(guān)注
87文章
11229瀏覽量
208931 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
4945瀏覽量
97200
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論