#yyds干货盘点# Linux小项目-数码相册设计

曾无好事来相访,赖尔高文一起予。这篇文章主要讲述#yyds干货盘点# Linux小项目-数码相册设计相关的知识,希望能为你提供帮助。
1. 前言这是基于Linux系统开发板设计一个小项目-数码相册,在LCD屏上可以显示完成常见的图片显示,翻页、旋转、缩放等功能。
【#yyds干货盘点# Linux小项目-数码相册设计】

#yyds干货盘点# Linux小项目-数码相册设计

文章图片

开发板采用友善之臂的Tiny4412开发板,CPU是三星的4412,最高主频1.5GHZ。板子配有8G的EMMC,2G的DDR,运行Linux3.5内核,文件系统采用busybox制作的最小根文件系统,不带图形桌面框架,系统是最小最精简的系统。
要完成整个项目相册的功能,需要的东西还是比较多的,首先要编译安装各种图片库: libjpg,giflib,libpng等等,图片需要缩放,需要支持缩放算法;LCD界面上的文字,时间采用矢量字体显示的,还需要交叉编译安装freetype库。然后硬件层,需要编写LCD屏驱动(帧缓冲框架),触摸屏驱动(输入子系统),三轴加速度计驱动(mma7660飞思卡尔的芯片)。
整个项目的代码布局如下:
#yyds干货盘点# Linux小项目-数码相册设计

文章图片

如果把整个项目代码写完一遍,基本上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;


    推荐阅读