在开发板上显示字母,汉字,方框,宋体等。 我这里大部分都是参考韦东山老师讲的。
这里只是为了测试lcd驱动并且从新总结下。
英文字母和汉字: 利用点阵画点。
画线和画框: 调用画线函数
宋体: 利用freetype 库
图片: 利用libjpeg 压缩jpeg 图片显示。
// lcd_test.c
// 显示 横线 竖线 框 字符 汉字 字体 图像等
#include <sys/mman.h>
#include <stdio.h>
#include "ascii 8_16.h"
#include <linux/fb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wchar.h>
#include <string.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "jpeglib.h"
#include <setjmp.h>
int fb_fd;
int hzk_fd;
struct stat hzk_stat;
unsigned char *hzk_mem;
unsigned char *fb_mem;
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
int x_res, y_res;
int line_length;
int screen_size;
int pixel_length;
// freetype relattived parameters
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_Matrix matrix; /* transformation matrix */
FT_Vector pen; /* untransformed origin */
FT_Error error;
wchar_t *wtext = L"中国neo";
unsigned int n ;
/* 显示 jpeg 图片相关参数*/
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE * infile; /* source file */
unsigned char *buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
};
void lcd_clear_display(unsigned int c)
{
memset(fb_mem , 0 , screen_size);
}
void show_put_pixel(int x ,int y , unsigned int color)
{
unsigned int *pen_32 = (unsigned int *)(fb_mem + y*line_length + x*pixel_length);
if(var.bits_per_pixel != 32)
{
printf(" sorry ! only support 32 bit\n");
return ;
}
*pen_32 = color ;
}
void lcd_put_line(int x1, int y1 , int x2, int y2 , unsigned int color)
{
int dx,dy,e;
dx=x2-x1;
dy=y2-y1;
if(dx>=0)
{
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 1/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
show_put_pixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 2/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
show_put_pixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)
if(dx>=dy) // 8/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
show_put_pixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 7/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
show_put_pixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
else //dx<0
{
dx=-dx; //dx=abs(dx)
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 4/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
show_put_pixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 3/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
show_put_pixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)
if(dx>=dy) // 5/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
show_put_pixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 6/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
show_put_pixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
}
void lcd_put_ascii(int x, int y , unsigned char c)
{
int i,j;
unsigned char byte;
// 获得点阵的起始坐标
unsigned char *dots = (unsigned char*)&fontdata_8x16[c*16] ;
printf("dots \n");
for(i=0 ; i<16; i++)
{
byte = dots[i];
for(j=7;j>=0;j--)
{
if(byte & (1<<j))
show_put_pixel(x+(7-j),y+i,0xffffff);
else
show_put_pixel(x+(7-j),y+i,0);
}
}
}
void lcd_put_gbk(int x, int y, unsigned char *str )
{
int i, j,k ;
unsigned char byte;
// 根据汉字库找到 汉字 起始地址
unsigned int area = str[0] - 0xA1; // hzk16 点阵字体文件是从0xA1 0xA1 开始的
unsigned int where = str[1] - 0xA1;
unsigned char *dots = (hzk_mem + (area*94 + where)*32);
for(i=0; i< 16 ;i++)
{
for(j=0 ; j<2 ;j++)
{
byte = dots[i*2+j*1]; // 逐个处理每个字节
for(k=7 ; k>=0; k--)
{
if(byte & (1<<k))
{
show_put_pixel(x+(7-k)+j*8,y+i,0xffffff);
}
else
{
show_put_pixel(x+(7-k)+j*8,y+i,0);
}
}
}
}
}
void
draw_bitmap( 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 < 0 || j < 0 ||
i >=x_res || j >= x_res )
continue;
if(bitmap->buffer[q * bitmap->width + p] )
show_put_pixel(x+p , y+q , 0xffffff);
else
show_put_pixel(x+p , y+q , 0);
// image[j][i] |= bitmap->buffer[q * bitmap->width + p];
}
}
}
int put_scanline_someplace(unsigned char* buffer , int starty , int startx , int endx )
{
int iX;
unsigned int color;
if(starty >= y_res)
return -1;
if(startx >= x_res)
return -1;
if(endx >= x_res)
endx = x_res ;
for(iX=startx ; iX<endx ; iX++)
{
color = (*buffer << 16) + (*(buffer+1) << 8) + (*(buffer+2)) ;
buffer += 3;
show_put_pixel(iX ,starty , color );
}
return 0;
}
int main(int argc , char **argv)
{
unsigned char str1[] = {0xd6 , 0xd0}; // 中
unsigned char str2[] = {0xb9 , 0xfa}; // 国
unsigned char str3[] = "中" ; // 中
unsigned char str4[] = "国"; // 国
int ret;
/* 打开 framebuffer */
fb_fd = open("dev/fb0" , O_RDWR);
if(fb_fd < 0)
{
printf("neo: cannot open the fb device\n");
return -1;
}
/*获得固定参数 和 变化参数 */
ret = ioctl(fb_fd , FBIOGET_VSCREENINFO , &var);
if(ret)
{
printf("neo: get FBIOGET_VSCREENINFO args error");
return -1 ;
}
ret = ioctl(fb_fd , FBIOGET_FSCREENINFO , &fix);
if(ret)
{
printf("neo: get FBIOGET_FSCREENINFO args error");
return -1 ;
}
line_length = fix.line_length;
screen_size = fix.smem_len;
pixel_length = var.bits_per_pixel / 8;
x_res = var.xres;
y_res = var.yres;
/* 映射 framebuffer 地址 */
fb_mem = (unsigned char*)mmap(NULL, screen_size,PROT_READ | PROT_WRITE,MAP_SHARED,fb_fd, 0);
/*清屏*/
lcd_clear_display(0);
/*显示 字符 'H'*/
lcd_put_ascii(100,100,'H');
/* 画线 */
lcd_put_line(0,0,799,479, 0xffffff);
/* 画框 */
lcd_put_line(30,30,700,30, 0xffffff);
lcd_put_line(30,30,30,300, 0xffffff);
lcd_put_line(700,30,700,300, 0xffffff);
lcd_put_line(30,300,700,300, 0xffffff);
/* 显示汉字 中国*/
hzk_fd = open("HZK16" , O_RDWR); // 打开汉字库
ret = fstat(hzk_fd, &hzk_stat); // 获得汉字库大小
if(ret)
{
printf("can't open the hanziku\n");
}
hzk_mem = (unsigned char*)mmap(NULL, hzk_stat.st_size,PROT_READ | PROT_WRITE,MAP_SHARED,hzk_fd, 0);
printf("打印出 中国的 GBk code \n");
printf("GBK code : %x , %x , %x ,%x \n" , str1[0] , str1[1] ,str2[0] , str2[1] );
printf("GBK code : %x , %x , %x ,%x \n" , str3[0] , str3[1] ,str4[0] , str4[1] );
lcd_put_gbk(250 ,200 , str1); // 此时中字采用 gbk码 保存的 所以为 d6 d0
lcd_put_gbk(500 ,200 , str2);
/*显示宋体中国*/
error = FT_Init_FreeType( &library ); /* initialize library */
error = FT_New_Face( library, "./simsun.ttc", 0, &face ); /* create face object */
slot = face->glyph;
error = FT_Set_Pixel_Sizes(face, 24, 0); /* set font size */
/* the pen position in 26.6 cartesian space coordinates; */
/* start at (300,200) relative to the upper left corner */
pen.x = 300 * 64;
pen.y = ( y_res - 200 ) * 64;
for ( n = 0; n < wcslen( wtext ); n++ )
{
/* set transformation */
FT_Set_Transform( face, 0, &pen );
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, wtext[n], FT_LOAD_RENDER );
if ( error )
continue; /* ignore errors */
/* now, draw to our target surface (convert position) */
draw_bitmap( &slot->bitmap,
slot->bitmap_left,
y_res - slot->bitmap_top );
/* increment pen position */
pen.x += slot->advance.x;
}
/*显示 图片*/
// Allocate and initialize a JPEG decompression object.
cinfo.err = jpeg_std_error(&jerr.pub);
jpeg_create_decompress(&cinfo);
// Specify the source of the compressed data (eg, a file).
if ((infile = fopen("1.jpg", "rb")) == NULL) {
printf("can not open the jpeg file \n");
return -1;
}
jpeg_stdio_src(&cinfo, infile);
// 3. Call jpeg_read_header() to obtain image info.
jpeg_read_header(&cinfo, 1);
// 4. Set parameters for decompression.
printf("enter scale M/N:\n");
scanf("%d/%d",&cinfo.scale_num, &cinfo.scale_denom);
printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom);
// 5. jpeg_start_decompress(...);
jpeg_start_decompress(&cinfo);
/* 输出的图象的信息 */
printf("output_width = %d\n", cinfo.output_width);
printf("output_height = %d\n", cinfo.output_height);
printf("output_components = %d\n", cinfo.output_components);
// 6. deal everyline data
row_stride = cinfo.output_width * cinfo.output_components;
buffer = malloc(row_stride);
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo, &buffer, 1);
put_scanline_someplace(&buffer[0], cinfo.output_scanline , 0 ,cinfo.output_width); // 显示
}
/* Step 7: Finish decompression */
jpeg_finish_decompress(&cinfo);
/* Step 8: Release JPEG decompression object */
jpeg_destroy_decompress(&cinfo);
fclose(infile);
free(buffer);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/781f310cfe72f8064ce10eeda0a5d47c.png)