在开发板上显示字母,汉字,方框,宋体等。 我这里大部分都是参考韦东山老师讲的。
这里只是为了测试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; }