曾无好事来相访,赖尔高文一起予。这篇文章主要讲述#yyds干货盘点# Linux小项目-数码相册设计相关的知识,希望能为你提供帮助。
1. 前言这是基于Linux系统开发板设计一个小项目-数码相册,在LCD屏上可以显示完成常见的图片显示,翻页、旋转、缩放等功能。
【#yyds干货盘点# Linux小项目-数码相册设计】
文章图片
开发板采用友善之臂的Tiny4412开发板,CPU是三星的4412,最高主频1.5GHZ。板子配有8G的EMMC,2G的DDR,运行Linux3.5内核,文件系统采用busybox制作的最小根文件系统,不带图形桌面框架,系统是最小最精简的系统。
要完成整个项目相册的功能,需要的东西还是比较多的,首先要编译安装各种图片库: libjpg,giflib,libpng等等,图片需要缩放,需要支持缩放算法;LCD界面上的文字,时间采用矢量字体显示的,还需要交叉编译安装freetype库。然后硬件层,需要编写LCD屏驱动(帧缓冲框架),触摸屏驱动(输入子系统),三轴加速度计驱动(mma7660飞思卡尔的芯片)。
整个项目的代码布局如下:
文章图片
如果把整个项目代码写完一遍,基本上Linux驱动、应用层编程都能够熟悉一遍。
涉及的技术点总结:
(1)png、jpg、gif等各种开源图片库的编译安装,完成对应图片解码,显示。整个过程里还需要懂得png、jpg、GIF图片的构造原理,如何读取数据,如何提取rgb数据,最终在LCD屏上完成显示。
(2)LCD驱动编写,首先得了解Linux帧缓冲框架原理,明白LCD屏的时序,才能编写驱动。应用层需要明白如何针对帧缓冲框架完成应用编程,实现画点、画线、文字等基本显示。
(3)触摸屏驱编写,触摸屏驱动芯片是FT5X06,这个IIC接口的芯片,编写触摸屏驱动需要熟悉IIC子系统、输入子系统、内核中断、工作队列等框架,因为触摸屏芯片支持笔中断,需要注册中断,在中断服务函数里调用工作队列实时读取数据。 应用层还需要适配tslib库接口,让tslib去读取输入子系统上传的坐标,还能完成校准,测试等功能,最终在自己工程内再封装函数去读取tslib接口返回的坐标数据,完成触屏屏逻辑处理。
(4)三轴加速度mma7660驱动编写,通过三轴加速度测量开发板的姿态,完成数码相册里图片的自动上下左右翻转,手机相册都有这个功能,横竖屏切换。
(5)按键驱动编写,数码相册支持按键翻页、触摸屏滑动翻页、自动图片播放(幻灯片)等功能,所以还需要编写按键驱动,按键驱动采用杂项字符设备编写,通过ioctl接口上传按键值。
(6)矢量字体库编译安装,界面上需要显示各种文字提示、时间等信息。用到矢量字体ttc,ttf等。
图片的翻页采用双向链表完成,支持左右翻页,更新链表时,将指定目录下所有图片加到双向链表里,通过按键、触摸屏、自动播放时,从链表里获取图片地址完成显示。
2. 涉及到源代码 2.1 png图片显示
#include <
stdio.h>
#include <
sys/types.h>
#include <
sys/stat.h>
#include <
fcntl.h>
#include <
sys/ioctl.h>
#include <
termios.h>
#include <
unistd.h>
#include <
string.h>
#include <
linux/fb.h>
#include <
sys/mman.h>
#include <
sys/stat.h>
#include <
stdlib.h>
#include <
linux/videodev2.h>
#include <
poll.h>
#include <
png.h>
#include <
pngconf.h>
#define LCD_DEVICE "/dev/fb0"int lcd_fd;
struct fb_var_screeninfo vinfo;
//可变参数
struct fb_fix_screeninfo finfo;
//固定参数
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 文件打开失败.\\n",filename);
return -1;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL);
/*需要分配/初始化内存以获取图像信息*/
info_ptr = png_create_info_struct(png_ptr);
/*设置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("颜色位数:[%4d]\\n",bit_depth);
//ARGB/*读取图像的最简单方法:*/
png_bytep row_pointers[height];
/*清除指针数组*/
for(i = 0;
i <
height;
i++)row_pointers[i] = NULL;
row_pointers[i] = malloc(width * 4);
/* RGBA */
memset(row_pointers[i], 0, width * 4);
/*读取整个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];
/*读取当前屏幕点的背景颜色*/
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);
/*显示数据*/
rgb24=R<
<
16|G<
<
8|B;
LCD_DrawPoint(x0,y,rgb24);
/*坐标自增*/
x0++;
y++;
/* 读取文件的其余部分,并在info_ptr中获取其他块-必需*/
png_read_end(png_ptr, info_ptr);
/*读取后清理,并释放已分配的所有内存-必需*/
png_destroy_read_struct(&
png_ptr, &
info_ptr, NULL);
/* 统一释放内存 */
for(i = 0;
i <
height;
i++)free(row_pointers[i]);
/*关闭文件*/
fclose(fp);
return 0;
/*
函数功能: 封装画点函数
函数参数: 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;
/*
函数功能: 封装读点函数
函数参数: 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 <
xxx.png>
\\n");
return 0;
/*1. 打开设备文件*/
lcd_fd=open(LCD_DEVICE,O_RDWR);
if(lcd_fd<
0)printf("%s 设备文件打开失败.\\n",LCD_DEVICE);
return 0;
/*2. 获取可变参数*/
ioctl(lcd_fd,FBIOGET_VSCREENINFO,&
vinfo);
printf("x=%d,y=%d,pixel=%d\\n",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
/*3. 获取固定参数*/
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;
2.2 jpg图片显示
#include <
stdio.h>
#include <
sys/types.h>
#include <
sys/stat.h>
#include <
fcntl.h>
#include <
sys/ioctl.h>
#include <
linux/fb.h>
#include <
sys/ioctl.h>
#include <
sys/mman.h>
#include <
string.h>
#include <
sys/types.h>
#include <
sys/stat.h>
#include <
unistd.h>
#include <
stdlib.h>
#include <
jpeglib.h>
#include <
jerror.h>
struct fb_var_screeninfo var;
//可变参数
struct fb_fix_screeninfo fix;
//固定参数
unsigned char *fb_mem=NULL;
//LCD屏的首地址/*
函数功能: 画点
*/
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;
//颜色赋值//显示JPEGjpeglib
int LCD_ShowJPEG(int x,int y,unsigned char *file)struct jpeg_decompress_struct cinfo;
//存放图像的数据
struct jpeg_error_mgr jerr;
//存放错误信息
FILE*infile;
unsigned int *dst=(unsigned int *)fb_mem;
unsigned char*buffer;
unsigned int i;
unsigned intcolor;
/* 打开图像文件*/
if ((infile = fopen(file, "rb")) == NULL) perror("jpeg文件打开失败!\\n");
return -1;
/*init jpeg压缩对象错误处理程序*/
cinfo.err = jpeg_std_error(&
jerr);
//初始化标准错误,用来存放错误信息
jpeg_create_decompress(&
cinfo);
//创建解压缩结构信息/*将jpeg压缩对象绑定到infile*/
jpeg_stdio_src(&
cinfo, infile);
/*读jpeg头*/
jpeg_read_header(&
cinfo, TRUE);
/*开始解压*/
jpeg_start_decompress(&
cinfo);
printf("JPEG图片高度: %d\\n",cinfo.output_height);
printf("JPEG图片宽度: %d\\n",cinfo.output_width);
printf("JPEG图片颜色位数(字节单位): %d\\n",cinfo.output_components);
/*为一条扫描线上的像素点分配存储空间,一行一行的解码*/
buffer = (unsigned char *)malloc(cinfo.output_width *cinfo.output_components);
//将图片内容显示到framebuffer上,cinfo.output_scanline表示当前行的位置,读取数据是会自动增加
while(cinfo.output_scanline <
cinfo.output_height) //读取一行的数据
jpeg_read_scanlines(&
cinfo,&
buffer,1);
for(i = 0;
i<
cinfo.output_width;
i++) //取出一个像素点(从左到右)
color = buffer[i * 3 + 0] <
<
16|
buffer[i * 3 + 1] <
<
8|
buffer[i * 3 + 2] <
<
0;
//画点
Show_Pixel(x+i,y,color);
y++;
// 继续下一行/*完成解压,摧毁解压对象*/
jpeg_finish_decompress(&
cinfo);
//结束解压
jpeg_destroy_decompress(&
cinfo);
//释放结构体占用的空间/*释放内存缓冲区*/
free(buffer);
/*关闭文件*/
fclose(infile);
return 0;
int main(int argc,char **argv)if(argc!=2)printf("./app <
JPEG图片文件>
\\n");
return 0;
int fd=open("/dev/fb0",O_RDWR);
if(fd<
0)perror("设备文件打开失败");
return 0;
/*1. 获取LCD屏的可变形参*/
ioctl(fd,FBIOGET_VSCREENINFO,&
var);
printf("分辨率:%d*%d\\n",var.xres,var.yres);
printf("像素点位数:%d\\n",var.bits_per_pixel);
/*2. 获取LCD屏的固定形参*/
ioctl(fd,FBIOGET_FSCREENINFO,&
fix);
printf("映射的长度:%d\\n",fix.smem_len);
printf("一行的字节数:%d\\n",fix.line_length);
/*3. 映射LCD缓冲区地址到进程空间*/
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);
//将屏幕清屏为白色LCD_ShowJPEG(0,0,argv[1]);
munmap(fb_mem,fix.smem_len);
close(fd);
return 0;
2.3 gif图片显示
#include <
stdio.h>
#include <
sys/types.h>
#include <
sys/stat.h>
#include <
fcntl.h>
#include <
sys/ioctl.h>
#include <
linux/fb.h>
#include <
sys/ioctl.h>
#include <
sys/mman.h>
#include <
string.h>
#include <
sys/types.h>
#include <
sys/stat.h>
#include <
unistd.h>
#include <
stdlib.h>
#include <
gif_lib.h>
struct fb_var_screeninfo var;
//可变参数
struct fb_fix_screeninfo fix;
//固定参数
unsigned char *fb_mem=NULL;
//LCD屏的首地址/*
函数功能: 画点
*/
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;
/*将图像数据显示在LCD屏幕上*/
unsigned char *rgb_p=rgbBuf;
for(h=0;
h<
image_h;
h++)for(w=0;
w<
image_w;
w++)b=*rgb_p++;
g=*rgb_p++;
r=*rgb_p++;
c=r<
<
16|g<
<
8|b<
<
0;
LCD_WritePoint(w+x,h+y,c);
/*绘制像素点到LCD屏*///颜色转换
void GifBufferToRgb888(ColorMapObject *ColorMap, unsigned char *inRgb,GifRowType *Buffer, int w, int h)GifColorType *ColorMapEntry = NULL;
GifRowType GifRow = NULL;
unsigned char *rgbBuf = inRgb;
int idxH = 0;
int idxW = 0;
for (idxH = 0;
idxH <
h;
idxH++)GifRow = Buffer[idxH];
rgbBuf = inRgb + idxH * w * 3;
for(idxW = 0;
idxW <
w;
idxW++)ColorMapEntry = &
ColorMap->
Colors[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. 打开图片文件*/
fp=DGifOpenFileName(file,&
error);
if(fp==NULL)return -1;
printf("GIF图片尺寸:%dx%d\\n",fp->
SWidth,fp->
SHeight);
/*2. 内存空间申请、初始化*/
Buffer=(GifRowType*)malloc(fp->
SHeight*sizeof(GifRowType));
/*一行字节大小*/
size = fp->
SWidth*sizeof(GifPixelType);
Buffer[0]=(GifRowType)malloc(size);
/*将其颜色设置为BackGround*/
for(i=0;
i<
fp->
SWidth;
i++)Buffer[0][i]=fp->
SBackGroundColor;
/*分配其他行,并将它们的颜色也设置为背景 */
for(i=1;
i<
fp->
SHeight;
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;
doif(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];
iW<
row+height;
iW+=InterlacedJumps[iH])DGifGetLine(fp,&
Buffer[iW][col],width);
elsefor(iH=0;
iH<
height;
iH++)DGifGetLine(fp,&
Buffer[row++][col],width);
colorMap=(fp->
Image.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);
//帧间隔时间
usleep(1000*50);
break;
case EXTENSION_RECORD_TYPE:
/* 跳过文件中的所有扩展块*/
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;
i<
fp->
SHeight;
i++)free(Buffer[i]);
free(Buffer);
DGifCloseFile(fp,&
error);
return 0;
int main(int argc,char **argv)if(argc!=2)printf("./app <
GIF图片文件>
\\n");
return 0;
int fd=open("/dev/fb0",O_RDWR);
if(fd<
0)perror("设备文件打开失败");
return 0;
/*1. 获取LCD屏的可变形参*/
ioctl(fd,FBIOGET_VSCREENINFO,&
var);
printf("分辨率:%d*%d\\n",var.xres,var.yres);
printf("像素点位数:%d\\n",var.bits_per_pixel);
/*2. 获取LCD屏的固定形参*/
ioctl(fd,FBIOGET_FSCREENINFO,&
fix);
printf("映射的长度:%d\\n",fix.smem_len);
printf("一行的字节数:%d\\n",fix.line_length);
/*3. 映射LCD缓冲区地址到进程空间*/
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图片显示状态:%d\\n",LCD_DisplayGIF(100,100,argv[1]));
munmap(fb_mem,fix.smem_len);
close(fd);
return 0;
2.4 矢量字体调用显示
#include <
stdio.h>
#include <
sys/types.h>
#include <
sys/stat.h>
#include <
fcntl.h>
#include <
sys/ioctl.h>
#include <
termios.h>
#include <
unistd.h>
#include <
string.h>
#include <
linux/fb.h>
#include <
sys/mman.h>
#include <
math.h>
#include <
wchar.h>
#include <
ft2build.h>
#include FT_FREETYPE_H
#include FT_STROKER_H#define LCD_DEVICE "/dev/fb0"
int lcd_fd;
struct fb_var_screeninfo vinfo;
//可变参数
struct fb_fix_screeninfo finfo;
//固定参数
unsigned char *lcd_mem=NULL;
//LCD首地址
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
/*定义一个结构体存放矢量字体的配置*/
struct FREE_TYPE_CONFIGFT_Librarylibrary;
FT_Faceface;
FT_GlyphSlotslot;
FT_Vectorpen;
/* untransformed origin*/
FT_Errorerror;
FT_BBoxbbox;
FT_Glyphglyph;
;
struct FREE_TYPE_CONFIG FreeTypeConfig;
/*
函数功能: 封装画点函数
函数参数: 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;
/*
函数功能: 封装读点函数
函数参数: 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坐标
*y : 显示的y坐标
*/
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;
/* 将位图信息循环打印到屏幕上 */
for(i=x,p=0;
i<
x_max;
i++,p++)for(j=y,q=0;
j<
y_max;
j++,q++)if((i>
x_max)||(j>
y_max)||(i<
0)||(j<
0))continue;
if(bitmap->
buffer[q*bitmap->
width+p]!=0)LCD_DrawPoint(i, j,0xFF0033);
elseLCD_DrawPoint(i, j,0xFFFFFF);
/*
函数功能: 初始化FreeType配置
*/
int InitConfig_FreeType(char *font_file)FT_Errorerror;
/*1. 初始化freetype库*/
error=FT_Init_FreeType(&
FreeTypeConfig.library);
if(error)printf("freetype字体库初始化失败.\\n");
return -1;
/*2. 打开加载的字体文件*/
error=FT_New_Face(FreeTypeConfig.library,font_file,0,&
FreeTypeConfig.face);
if(error)printf("矢量字体文件加载失败.\\n");
return -2;
return 0;
/*
函数功能: 释放FreeType配置
*/
void FreeType_Config(void)FT_Done_Face(FreeTypeConfig.face);
FT_Done_FreeType(FreeTypeConfig.library);
/*
函数功能: 在LCD屏显示一串文本数据
函数参数:
u32 x坐标位置
u32 y坐标位置
u32 size 字体大小
wchar_t *text 显示的文本数据
*/
int LCD_DrawText(u32 x,u32 y,u32 size,wchar_t *text)FT_Errorerror;
int i = 0;
int bbox_height_min = 10000;
int bbox_height_max = 0;
/*3. 设置字符的像素的大小为size*size*/
error=FT_Set_Pixel_Sizes(FreeTypeConfig.face,size,0);
if(error)printf("字符的像素大小设置失败.\\n");
return -1;
/*4. 设置字体文件的轮廓的插槽*/
FreeTypeConfig.slot=FreeTypeConfig.face->
glyph;
/* 设置坐标为原点坐标
* 将LCD坐标转换成笛卡尔坐标
* 单位是 1/64 Point
*/
FreeTypeConfig.pen.x=x*64;
FreeTypeConfig.pen.y=(vinfo.yres-size-y)*64;
/*5. 循环的将文字显示出来*/
for(i=0;
i<
wcslen(text);
i++)FT_Set_Transform(FreeTypeConfig.face,0,&
FreeTypeConfig.pen);
//设置字体的起始坐标位置
/*装载字符编码,填充face的glyph slot成员*/
error=FT_Load_Char(FreeTypeConfig.face,text[i],FT_LOAD_RENDER);
if(error)printf("装载字符编码失败.\\n");
return -1;
/*通过glyph slot来获得glyph*/
FT_Get_Glyph(FreeTypeConfig.slot,&
FreeTypeConfig.glyph);
/*通过glyph来获得cbox*/
FT_Glyph_Get_CBox(FreeTypeConfig.glyph,FT_GLYPH_BBOX_TRUNCATE,&
FreeTypeConfig.bbox);
/*获得字体高度的最大值和最小值*/
if(bbox_height_min>
FreeTypeConfig.bbox.yMin)bbox_height_min=FreeTypeConfig.bbox.yMin;
if(bbox_height_max<
FreeTypeConfig.bbox.yMax)bbox_height_max=FreeTypeConfig.bbox.yMax;
/*画点,把笛卡尔坐标转换成LCD坐标*/
LCD_DrawBitmap(&
FreeTypeConfig.slot->
bitmap,
FreeTypeConfig.slot->
bitmap_left,
vinfo.yres-FreeTypeConfig.slot->
bitmap_top);
if(FreeTypeConfig.slot->
bitmap_left+size*2>
vinfo.xres)FreeTypeConfig.pen.x=0;
//更新X坐标位置
FreeTypeConfig.pen.y=(vinfo.yres-size-y-size)*64;
//更新Y坐标位置else/* 更新原点坐标位置 */
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 <
xxx.ttf 字体文件>
\\n");
return 0;
/*1. 打开设备文件*/
lcd_fd=open(LCD_DEVICE,O_RDWR);
if(lcd_fd<
0)printf("%s open error.\\n",LCD_DEVICE);
return 0;
/*2. 获取可变参数*/
ioctl(lcd_fd,FBIOGET_VSCREENINFO,&
vinfo);
printf("x=%d,y=%d,pixel=%d\\n",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
/*3. 获取固定参数*/
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() 函数用于计算宽字符的个数,支持区分中文和英文字符,文本需要在UTF-8编码下。
定义宽字符串示例:
wchar_t *wp=L"1234567890中国";
//12
printf("wcslen p:%d\\n",wcslen(wp));
返回值是12
*/
LCD_DrawText(50,56*0,56,L"Linux项目开发");
LCD_DrawText(150,56*1,56,L"数码相册开发");
LCD_DrawText(200,56*3,48,L"FreeType矢量字体");
LCD_DrawText(150,56*5,80,L"Linux驱动开发");
/*7. 释放FreeType配置*/
FreeType_Config();
close(lcd_fd);
return 0;
推荐阅读
- #yyds干货盘点#spring-cloud-kubernetes与k8s的configmap
- #过年不停更#HarmonyOS-JAVA之手把手教你绘制冰墩墩
- python测试webservice接口
- pycharm 快捷键
- python开启httpserver服务在自动化测试中的一个小运用
- wireshark配合jmeter测试webservice接口
- LoadRunner断言(正确结果有多种情况)
- Java NIO 网络编程《Netty In Action》 #yyds干货盘点#
- Linux环境aspose插件word转pdf中文乱码解决方案