0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux小项目-数码相册设计

DS小龙哥-嵌入式技术 来源:DS小龙哥-嵌入式技术 作者:DS小龙哥-嵌入式技 2022-08-14 09:15 次阅读

1. 前言

这是基于Linux系统开发板设计一个小项目-数码相册,在LCD屏上可以显示完成常见的图片显示,翻页、旋转、缩放等功能。

image-20220122141248516

开发板采用友善之臂的Tiny4412开发板,CPU三星的4412,最高主频1.5GHZ。板子配有8G的EMMC,2G的DDR,运行Linux3.5内核,文件系统采用busybox制作的最小根文件系统,不带图形桌面框架,系统是最小最精简的系统。

要完成整个项目相册的功能,需要的东西还是比较多的,首先要编译安装各种图片库: libjpg,giflib,libpng等等,图片需要缩放,需要支持缩放算法;LCD界面上的文字,时间采用矢量字体显示的,还需要交叉编译安装freetype库。然后硬件层,需要编写LCD屏驱动(帧缓冲框架),触摸屏驱动(输入子系统),三轴加速度计驱动(mma7660飞思卡尔的芯片)。

整个项目的代码布局如下:

image-20220122134342597

如果把整个项目代码写完一遍,基本上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 
#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;//可变参数
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 \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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
​
#include 
#include 
​
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; //颜色赋值
}
​
​
//显示JPEG  jpeglib
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 int color;
    
  /* 打开图像文件*/
  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;>

2.3 gif图片显示

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;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. 打开图片文件*/
	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;iSWidth;i++)
	{
		Buffer[0][i]=fp->SBackGroundColor;
	}
	
	/*分配其他行,并将它们的颜色也设置为背景 */
	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);
				//帧间隔时间
				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;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("设备文件打开失败");
		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;
}
复制代码图片文件>+height;iw+=interlacedjumps[ih])>;h++)>

2.4 矢量字体调用显示

#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;//可变参数
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_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;



/*
函数功能: 封装画点函数
函数参数: 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;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);
			}
		}
	}
}

/*
函数功能: 初始化FreeType配置
*/
int InitConfig_FreeType(char *font_file)
{
	FT_Error      error;
	/*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_Error      error;
	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;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坐标位置
			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 \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"北京万邦易嵌科技有限公司");
	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驱动开发");
	/*7. 释放FreeType配置*/
	FreeType_Config();
	
	close(lcd_fd);
	return 0;
})bbox_height_max=freetypeconfig.bbox.ymax;>(text);i++)>;i++,p++)>

审核编辑:汤梓红

;>
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • lcd
    lcd
    +关注

    关注

    34

    文章

    4274

    浏览量

    164018
  • Linux
    +关注

    关注

    87

    文章

    10986

    浏览量

    206712
  • 开发板
    +关注

    关注

    25

    文章

    4417

    浏览量

    93916
收藏 人收藏

    评论

    相关推荐

    Linux驱动开发_数码相册项目、360WIFI驱动移植介绍

    这篇文章介绍两个知识点: 数码相册要求介绍、贴出案例代码、介绍360随身WIFI的驱动移植注意事项。
    的头像 发表于 09-17 15:51 1139次阅读
    <b class='flag-5'>Linux</b>驱动开发_<b class='flag-5'>数码相册</b><b class='flag-5'>项目</b>、360WIFI驱动移植介绍

    基于STM32设计的数码相册

    项目是基于STM32设计的数码相册,能够通过LCD显示屏解码显示主流的图片,支持bmp、jpg、gif等格式。用户可以通过按键或者触摸屏来切换图片,同时还可以旋转显示,并能够自适应居中显示,小尺寸图片居中显示,大尺寸图片自动缩小显示(超出屏幕范围)。图片从SD卡中获取。
    的头像 发表于 06-24 21:14 1.1w次阅读
    基于STM32设计的<b class='flag-5'>数码相册</b>

    单片机控制的DIY数码相册显示

    本帖最后由 eehome 于 2013-1-5 09:52 编辑 单片机控制的DIY数码相册显示
    发表于 08-15 23:05

    单片机小项目

    本帖最后由 eehome 于 2013-1-5 09:47 编辑 单片机小项目
    发表于 08-26 11:59

    求做小项目

    求助:初学单片机,想做个小项目,哪位同仁可以介绍介绍有什么好项目学习一下的。{:soso_e132:}
    发表于 09-27 00:32

    【Aworks申请】基于ARM9的电子相册

    申请理由:本人是一名嵌入式开发从业者,对嵌入式开发有着浓厚的兴趣,本套开发板具有极其丰富的学习资源,非常希望能够获得此次机会,对ARM9嵌入式系统开发有很大的帮助。项目描述:通过开发板的学习之后,制作一个简单的可以控制的电子数码相册,简单,美观。为今后的工作学习打下良好的
    发表于 07-15 08:58

    适合新手做的小项目

    接触Labview一个月,有没有适合新手做的小项目,求介绍下
    发表于 08-09 14:14

    单片机小项目开源分享

    转眼间已经工作一年,目前从事linux/android驱动工作,将大学期间单片机的小项目开源出来,供大家交流学习,比较简单。源码在git clone http://www.github.com
    发表于 09-17 11:33

    【YOXIOS X3开发板(基于Linux的GUI)试用连载】基于linux开发小项目

    项目名称:基于linux开发小项目试用计划:申请理由:我公司主要的产品是使用linux系统来开发各种产品。而我只会使用普通的单片机开发,一直想学习l
    发表于 07-27 15:05

    单片机的一些小项目资料

    单片机的一些小项目,单片机入门必备,适合初学者
    发表于 11-18 17:24 11次下载

    Linux应用小项目的解码库移植源代码免费下载

    本文档的主要内容详细介绍的是Linux应用小项目源码 解码库移植、调用的项目,源码中有详细注释,用交叉工具链直接可编译。
    发表于 10-24 08:00 0次下载

    STM32学习——入门小项目

    STM32学习——入门小项目
    发表于 12-07 17:21 70次下载
    STM32学习——入门<b class='flag-5'>小项目</b>

    Arduino Bootcamp师生小项目

    电子发烧友网站提供《Arduino Bootcamp师生小项目.zip》资料免费下载
    发表于 07-28 11:22 0次下载
    Arduino Bootcamp师生<b class='flag-5'>小项目</b>

    FPGA增强了数码相册功能

    随着我们不断以像素为单位捕获生活快照,我们正在积累一系列软件工具和设备来查看,编辑,存储,个性化和共享我们的数码照片。一个能够可靠地提供所有这些功能的单一、易于使用的系统将简化和增强照片制作过程。
    的头像 发表于 10-25 11:25 558次阅读
    FPGA增强了<b class='flag-5'>数码相册</b>功能

    通过ESP32制作数码相册

    电子发烧友网站提供《通过ESP32制作数码相册.zip》资料免费下载
    发表于 06-16 11:30 2次下载
    通过ESP32制作<b class='flag-5'>数码相册</b>