[Linux]数码相框&电子书(一)

[Linux]数码相框&电子书(一)

个人博客https://aeneag.xyz/

艾恩凝

2021/7/14

Introduction

项目第一天,主要研究了LCD显示文字,基础不1313了,搞了整整一天,知识点到也就这样了,灵活运用就可以了,几年前搞stm32的时候,现在的屏幕显示字和32的差不多,轻车熟路。其他的没什么好说

Achievement

IMG20210714190919.jpg

上面是明白基础知识以后,打上的字

Code

  1int fd_fb;
  2struct fb_var_screeninfo var;	/* Current var */
  3struct fb_fix_screeninfo fix;	/* Current fix */
  4int screen_size;
  5unsigned char *fbmem;
  6unsigned int line_width;
  7unsigned int pixel_width;
  8
  9int fd_hzk16;
 10struct stat hzk_stat;
 11unsigned char *hzkmem;
 12
 13FT_Library	  library;
 14FT_Face 	  face;
 15FT_Error error;
 16FT_Vector	  pen;
 17FT_GlyphSlot  slot;
 18FT_Matrix	  matrix;				  /* transformation matrix */
 19
 20double		  aen_angle;
 21
 22/* color : 0x00RRGGBB */
 23void lcd_put_pixel(int x, int y, unsigned int color)
 24{
 25	unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;
 26	unsigned short *pen_16;
 27	unsigned int *pen_32;
 28
 29	unsigned int red, green, blue;
 30
 31	pen_16 = (unsigned short *)pen_8;
 32	pen_32 = (unsigned int *)pen_8;
 33
 34	switch (var.bits_per_pixel)
 35	{
 36		case 8:
 37		{
 38			*pen_8 = color;
 39			break;
 40		}
 41		case 16:
 42		{
 43			/* 565 */
 44			red   = (color >> 16) & 0xff;
 45			green = (color >> 8) & 0xff;
 46			blue  = (color >> 0) & 0xff;
 47			color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
 48			*pen_16 = color;
 49			break;
 50		}
 51		case 32:
 52		{
 53			*pen_32 = color;
 54			break;
 55		}
 56		default:
 57		{
 58			printf("can't surport %dbpp\n", var.bits_per_pixel);
 59			break;
 60		}
 61	}
 62}
 63
 64void lcd_put_ascii(int x, int y, unsigned char c)
 65{
 66	unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
 67	int i, b;
 68	unsigned char byte;
 69
 70	for (i = 0; i < 16; i++)
 71	{
 72		byte = dots[i];
 73		for (b = 7; b >= 0; b--)
 74		{
 75			if (byte & (1<<b))
 76			{
 77				/* show */
 78				lcd_put_pixel(x+7-b, y+i, 0xffffff); /* 白 */
 79			}
 80			else
 81			{
 82				/* hide */
 83				lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */
 84			}
 85		}
 86	}
 87}
 88
 89void lcd_put_chinese(int x, int y, unsigned char *str)
 90{
 91	unsigned int area  = str[0] - 0xA1;
 92	unsigned int where = str[1] - 0xA1;
 93	unsigned char *dots = hzkmem + (area * 94 + where)*32;
 94	unsigned char byte;
 95
 96	int i, j, b;
 97	for (i = 0; i < 16; i++)
 98		for (j = 0; j < 2; j++)
 99		{
100			byte = dots[i*2 + j];
101			for (b = 7; b >=0; b--)
102			{
103				if (byte & (1<<b))
104				{
105					/* show */
106					lcd_put_pixel(x+j*8+7-b, y+i, 0xffffff); /* 白 */
107				}
108				else
109				{
110					/* hide */
111					lcd_put_pixel(x+j*8+7-b, y+i, 0); /* 黑 */
112				}
113	
114			}
115		}
116
117}
118
119
120
121/* Replace this function with something useful. */
122
123void
124draw_bitmap( FT_Bitmap*  bitmap,
125             FT_Int      x,
126             FT_Int      y)
127{
128  FT_Int  i, j, p, q;
129  FT_Int  x_max = x + bitmap->width;
130  FT_Int  y_max = y + bitmap->rows;
131
132  for ( i = x, p = 0; i < x_max; i++, p++ )
133  {
134    for ( j = y, q = 0; j < y_max; j++, q++ )
135    {
136      if ( i < 0      || j < 0       ||
137           i >= var.xres || j >= var.yres )
138        continue;
139
140      //image[j][i] |= bitmap->buffer[q * bitmap->width + p];
141      lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]);
142    }
143  }
144}
145
146int show_word(__u32 x, __u32 y,char *angle,wchar_t *str){
147	/* 确定座标:
148	 * lcd_x = var.xres/2 + 8 + 16
149	 * lcd_y = var.yres/2 + 16
150	 * 笛卡尔座标系:
151	 * x = lcd_x = var.xres/2 + 8 + 16
152	 * y = var.yres - lcd_y = var.yres/2 - 16
153	 */
154	pen.x = x * 64;
155	pen.y = y * 64;
156
157
158	aen_angle= ( 1.0 * strtoul(angle,NULL,0)/ 360 ) * 3.14159 * 2;	  /* use 25 degrees 	*/
159	/* set up matrix */
160	matrix.xx = (FT_Fixed)( cos( aen_angle ) * 0x10000L );
161	matrix.xy = (FT_Fixed)(-sin( aen_angle ) * 0x10000L );
162	matrix.yx = (FT_Fixed)( sin( aen_angle ) * 0x10000L );
163	matrix.yy = (FT_Fixed)( cos( aen_angle ) * 0x10000L );
164
165    /* set transformation */
166    FT_Set_Transform( face,  &matrix, &pen);
167
168    /* load glyph image into the slot (erase previous one) */
169    error = FT_Load_Char( face, (FT_ULong)str, FT_LOAD_RENDER );
170		if (error)
171	{
172		printf("FT_Load_Char error\n");
173		return -1;
174	}
175
176    draw_bitmap( &slot->bitmap,
177                 slot->bitmap_left,
178                 var.yres - slot->bitmap_top);
179	return 0;
180
181}
182void show_sentence(__u32 x, __u32 y,int width,int size,char *angle,wchar_t *str){
183	__u32 xx=x;
184	int i = 0;
185	for(i = 0;i < size; i++){
186		show_word(xx, y,angle,(wchar_t *)str[i]);
187		xx = xx + width;
188	}
189	 
190}
191int main(int argc, char **argv)
192{
193
194   	wchar_t *my_blog = L"欢迎访问我的博客:\0";
195	wchar_t *my_address = L"https://aeneag.xyz/";  
196
197
198
199	if (argc != 3)
200	{
201		printf("Usage : %s <font_file> <angle>\n", argv[0]);
202		return -1;
203	}
204
205
206	fd_fb = open("/dev/fb0", O_RDWR);
207	if (fd_fb < 0)
208	{
209		printf("can't open /dev/fb0\n");
210		return -1;
211	}
212
213	if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
214	{
215		printf("can't get var\n");
216		return -1;
217	}
218
219	if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix))
220	{
221		printf("can't get fix\n");
222		return -1;
223	}
224
225	line_width  = var.xres * var.bits_per_pixel / 8;
226	pixel_width = var.bits_per_pixel / 8;
227	screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
228	fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
229	if (fbmem == (unsigned char *)-1)
230	{
231		printf("can't mmap\n");
232		return -1;
233	}
234
235	fd_hzk16 = open("HZK16", O_RDONLY);
236	if (fd_hzk16 < 0)
237	{
238		printf("can't open HZK16\n");
239		return -1;
240	}
241	if(fstat(fd_hzk16, &hzk_stat))
242	{
243		printf("can't get fstat\n");
244		return -1;
245	}
246	hzkmem = (unsigned char *)mmap(NULL , hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);
247	if (hzkmem == (unsigned char *)-1)
248	{
249		printf("can't mmap for hzk16\n");
250		return -1;
251	}
252
253	/* clear screen ,black */
254	memset(fbmem, 0, screen_size);
255
256	/* show word */
257	error = FT_Init_FreeType( &library );			   /* initialize library */
258	/* error handling omitted */
259
260	error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
261	/* error handling omitted */
262	slot = face->glyph;
263
264	FT_Set_Pixel_Sizes(face, 24, 0);
265
266	show_sentence(var.xres/2 - 96,var.yres/2 + 24,24,9,argv[2],my_blog);
267	show_sentence(var.xres/2 - 108,var.yres/2 ,12,19,argv[2],my_address);
268#if 0
269    show_word(var.xres/2 - 96,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[0]);
270	show_word(var.xres/2 - 72,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[1]);
271	show_word(var.xres/2 - 48,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[2]);
272	show_word(var.xres/2 - 24,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[3]);
273	show_word(var.xres/2 ,      var.yres/2 + 24,argv[2],(wchar_t *)my_blog[4]);
274	show_word(var.xres/2 + 24,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[5]);
275	show_word(var.xres/2 + 48,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[6]);
276	show_word(var.xres/2 + 72,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[7]);
277	show_word(var.xres/2 + 96,  var.yres/2 + 24,argv[2],(wchar_t *)my_blog[8]);
278
279	show_word(var.xres/2 - 108,	var.yres/2 ,argv[2],(wchar_t *)my_address[0]);
280	show_word(var.xres/2 - 96,	var.yres/2 ,argv[2],(wchar_t *)my_address[1]);
281	show_word(var.xres/2 - 84,	var.yres/2 ,argv[2],(wchar_t *)my_address[2]);
282	show_word(var.xres/2 - 72,	var.yres/2 ,argv[2],(wchar_t *)my_address[3]);
283	show_word(var.xres/2 - 60,	var.yres/2 ,argv[2],(wchar_t *)my_address[4]);
284	show_word(var.xres/2 - 48,  var.yres/2 ,argv[2],(wchar_t *)my_address[5]);
285	show_word(var.xres/2 - 36,  var.yres/2 ,argv[2],(wchar_t *)my_address[6]);
286	show_word(var.xres/2 - 24,  var.yres/2 ,argv[2],(wchar_t *)my_address[7]);
287	show_word(var.xres/2 - 12,  var.yres/2 ,argv[2],(wchar_t *)my_address[8]);
288	show_word(var.xres/2 ,      var.yres/2 ,argv[2],(wchar_t *)my_address[9]);
289	show_word(var.xres/2 + 12,  var.yres/2 ,argv[2],(wchar_t *)my_address[10]);
290	show_word(var.xres/2 + 24,  var.yres/2 ,argv[2],(wchar_t *)my_address[11]);
291	show_word(var.xres/2 + 36,  var.yres/2 ,argv[2],(wchar_t *)my_address[12]);
292	show_word(var.xres/2 + 48,  var.yres/2 ,argv[2],(wchar_t *)my_address[13]);
293	show_word(var.xres/2 + 60,  var.yres/2 ,argv[2],(wchar_t *)my_address[14]);
294	show_word(var.xres/2 + 72,  var.yres/2 ,argv[2],(wchar_t *)my_address[15]);
295	show_word(var.xres/2 + 84,  var.yres/2 ,argv[2],(wchar_t *)my_address[16]);
296	show_word(var.xres/2 + 96,  var.yres/2 ,argv[2],(wchar_t *)my_address[17]);
297	show_word(var.xres/2 + 108, var.yres/2 ,argv[2],(wchar_t *)my_address[18]);
298#endif
299
300
301
302	return 0;
303}

代码是这些,有一个警告信息,稍后解决。

警告已解决,优化了代码,代码更新

end

回头看,为什么花了一天时间才搞了这么点东西,自己好菜😭 菜到连个对象都没有。又是流水账的一篇,hhhh

艾恩凝

写于大连

2021/7/14

补充

2021/7/15

显示多行文字,昨天是自己搞的,今天使用了官方例程

code

  1#include <sys/mman.h>
  2#include <sys/types.h>
  3#include <sys/stat.h>
  4#include <unistd.h>
  5#include <linux/fb.h>
  6#include <fcntl.h>
  7#include <stdio.h>
  8#include <string.h>
  9#include <math.h>
 10#include <wchar.h>
 11
 12#include <ft2build.h>
 13#include FT_FREETYPE_H
 14#include FT_GLYPH_H
 15
 16typedef struct TGlyph_ { 
 17	FT_UInt index; /* glyph index */ 
 18	FT_Vector pos; /* glyph origin on the baseline */ 
 19	FT_Glyph image; /* glyph image */ 
 20} TGlyph, *PGlyph; 
 21
 22
 23#define MAX_GLYPHS  100
 24
 25int fd_fb;
 26struct fb_var_screeninfo var;	/* Current var */
 27struct fb_fix_screeninfo fix;	/* Current fix */
 28int screen_size;
 29unsigned char *fbmem;
 30unsigned int line_width;
 31unsigned int pixel_width;
 32
 33
 34/* color : 0x00RRGGBB */
 35void lcd_put_pixel(int x, int y, unsigned int color)
 36{
 37	unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;
 38	unsigned short *pen_16;
 39	unsigned int *pen_32;
 40
 41	unsigned int red, green, blue;
 42
 43	pen_16 = (unsigned short *)pen_8;
 44	pen_32 = (unsigned int *)pen_8;
 45
 46	switch (var.bits_per_pixel)
 47	{
 48		case 8:
 49		{
 50			*pen_8 = color;
 51			break;
 52		}
 53		case 16:
 54		{
 55			/* 565 */
 56			red   = (color >> 16) & 0xff;
 57			green = (color >> 8) & 0xff;
 58			blue  = (color >> 0) & 0xff;
 59			color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
 60			*pen_16 = color;
 61			break;
 62		}
 63		case 32:
 64		{
 65			*pen_32 = color;
 66			break;
 67		}
 68		default:
 69		{
 70			printf("can't surport %dbpp\n", var.bits_per_pixel);
 71			break;
 72		}
 73	}
 74}
 75
 76
 77
 78/* Replace this function with something useful. */
 79
 80void
 81draw_bitmap( FT_Bitmap*  bitmap,
 82             FT_Int      x,
 83             FT_Int      y)
 84{
 85  FT_Int  i, j, p, q;
 86  FT_Int  x_max = x + bitmap->width;
 87  FT_Int  y_max = y + bitmap->rows;
 88
 89	//printf("x = %d, y = %d\n", x, y);
 90
 91  for ( i = x, p = 0; i < x_max; i++, p++ )
 92  {
 93    for ( j = y, q = 0; j < y_max; j++, q++ )
 94    {
 95      if ( i < 0      || j < 0       ||
 96           i >= var.xres || j >= var.yres )
 97        continue;
 98
 99      //image[j][i] |= bitmap->buffer[q * bitmap->width + p];
100      lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]);
101    }
102  }
103}
104
105
106int Get_Glyphs_Frm_Wstr(FT_Face face, wchar_t * wstr, TGlyph glyphs[])
107{
108	int n;
109	PGlyph glyph = glyphs;
110	int pen_x = 0;
111	int pen_y = 0;
112	int error;
113	FT_GlyphSlot  slot = face->glyph;;
114
115
116	for (n = 0; n < wcslen(wstr); n++)
117	{
118		glyph->index = FT_Get_Char_Index( face, wstr[n]); 
119		/* store current pen position */ 
120		glyph->pos.x = pen_x; 
121		glyph->pos.y = pen_y;
122
123		/* load时是把glyph放入插槽face->glyph */
124		error = FT_Load_Glyph(face, glyph->index, FT_LOAD_DEFAULT);
125		if ( error ) 
126			continue;
127
128		error = FT_Get_Glyph(face->glyph, &glyph->image ); 
129		if ( error ) 
130			continue;
131
132		/* translate the glyph image now */ 
133		/* 这使得glyph->image里含有位置信息 */
134		FT_Glyph_Transform(glyph->image, 0, &glyph->pos );
135
136		pen_x += slot->advance.x;  /* 1/64 point */
137
138		/* increment number of glyphs */ 
139		glyph++;
140	}
141
142	/* count number of glyphs loaded */ 
143	return (glyph - glyphs);
144}
145
146void compute_string_bbox(TGlyph glyphs[], FT_UInt num_glyphs, FT_BBox *abbox )
147{
148	FT_BBox bbox; 
149	int n;
150
151	bbox.xMin = bbox.yMin = 32000; 
152	bbox.xMax = bbox.yMax = -32000;
153
154	for ( n = 0; n < num_glyphs; n++ )
155	{
156		FT_BBox glyph_bbox;
157
158		FT_Glyph_Get_CBox(glyphs[n].image, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox );
159
160		if (glyph_bbox.xMin < bbox.xMin)
161			bbox.xMin = glyph_bbox.xMin;
162
163		if (glyph_bbox.yMin < bbox.yMin)
164			bbox.yMin = glyph_bbox.yMin;
165
166		if (glyph_bbox.xMax > bbox.xMax)
167			bbox.xMax = glyph_bbox.xMax;
168
169		if (glyph_bbox.yMax > bbox.yMax)
170			bbox.yMax = glyph_bbox.yMax;
171	}
172
173	*abbox = bbox;
174}
175
176
177void Draw_Glyphs(TGlyph glyphs[], FT_UInt num_glyphs, FT_Vector pen)
178{
179	int n;
180	int error;
181
182	for (n = 0; n < num_glyphs; n++)
183	{
184		FT_Glyph_Transform(glyphs[n].image, 0, &pen);
185		/* convert glyph image to bitmap (destroy the glyph copy!) */ 
186		error = FT_Glyph_To_Bitmap(&glyphs[n].image, FT_RENDER_MODE_NORMAL, 0, /* no additional translation */ 
187                              		1 ); 		/* destroy copy in "image" */
188		if ( !error ) 
189		{ 
190			FT_BitmapGlyph bit = (FT_BitmapGlyph)glyphs[n].image; 
191			draw_bitmap(&bit->bitmap, bit->left, var.yres - bit->top); 
192			FT_Done_Glyph(glyphs[n].image ); 
193		}
194	}
195}
196
197int main(int argc, char **argv)
198{
199	wchar_t *wstr1 = L"欢迎访问我的博客:";
200	wchar_t *wstr2 = L"https://aeneag.xyz/";
201
202	FT_Library	  library;
203	FT_Face 	  face;
204	int error;
205    FT_Vector     pen;
206	FT_GlyphSlot  slot;
207	int i;
208	FT_BBox bbox;
209
210	int line_box_ymin = 10000;
211	int line_box_ymax = 0;
212
213	int line_box_width;
214	int line_box_height;
215
216	TGlyph glyphs[MAX_GLYPHS]; /* glyphs table */ 
217	FT_UInt num_glyphs;
218
219
220	if (argc != 2)
221	{
222		printf("Usage : %s <font_file>\n", argv[0]);
223		return -1;
224	}
225
226
227	fd_fb = open("/dev/fb0", O_RDWR);
228	if (fd_fb < 0)
229	{
230		printf("can't open /dev/fb0\n");
231		return -1;
232	}
233
234	if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
235	{
236		printf("can't get var\n");
237		return -1;
238	}
239
240	if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix))
241	{
242		printf("can't get fix\n");
243		return -1;
244	}
245
246	line_width  = var.xres * var.bits_per_pixel / 8;
247	pixel_width = var.bits_per_pixel / 8;
248	screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
249	fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
250	if (fbmem == (unsigned char *)-1)
251	{
252		printf("can't mmap\n");
253		return -1;
254	}
255
256	/* 清屏: 全部设为黑色 */
257	memset(fbmem, 0, screen_size);
258
259	/* 显示矢量字体 */
260	error = FT_Init_FreeType( &library );			   /* initialize library */
261	/* error handling omitted */
262
263	error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
264	/* error handling omitted */
265	slot = face->glyph;
266
267	FT_Set_Pixel_Sizes(face, 24, 0);
268
269	/* wstr1 */
270	num_glyphs = Get_Glyphs_Frm_Wstr(face, wstr1, glyphs);
271
272	compute_string_bbox(glyphs, num_glyphs, &bbox);
273	line_box_width  = bbox.xMax - bbox.xMin;
274	line_box_height = bbox.yMax - bbox.yMin;
275
276	pen.x = (var.xres - line_box_width)/2 * 64;
277	pen.y = (var.yres - line_box_height)/2 * 64;
278
279	Draw_Glyphs(glyphs, num_glyphs, pen);
280
281	/* wstr2 */
282	num_glyphs = Get_Glyphs_Frm_Wstr(face, wstr2, glyphs);
283
284	compute_string_bbox(glyphs, num_glyphs, &bbox);
285	line_box_width  = bbox.xMax - bbox.xMin;
286	line_box_height = bbox.yMax - bbox.yMin;
287
288	pen.x = (var.xres - line_box_width)/2 * 64;
289	pen.y = pen.y - 24 * 64;
290	Draw_Glyphs(glyphs, num_glyphs, pen);
291
292
293	return 0;
294}

end

艾恩凝

更新写法

艾恩凝

写于大连

2021/7/15

catalogue

[Linux]数码相框&电子书系列

    吾心信其可行,
          则移山填海之难,
                  终有成功之日!
                                  ——孙文
    评论
    0 评论
avatar

取消