搜索
bottom↓
回复: 29

接上一贴,继续介绍抗锯齿方法

  [复制链接]

出25入84汤圆

发表于 2017-6-23 17:53:39 | 显示全部楼层 |阅读模式
本帖最后由 chun2495 于 2017-6-23 17:58 编辑

上一贴中(给大家介绍一种做界面的去锯齿方法  ),介绍了一种不采用gui的抗锯齿方法,后来经15楼大神redroof点拨,终于参透了gui中的抗锯齿算法思路。
下来,给大家分享一下该方法和程序。
首先,在上贴中提到需要准备一副含有黑纸白字的图片,如下


然后用彩色字模读取数据


注意这里选择256灰阶,如果内存小的话,也可以取16灰阶,不过最大的抗锯齿就只能到16,如果是256阶的话,抗锯齿级别可以是256,128,64,62,16,4,2,这在后面的程序中会介绍。这也是gui的抗锯齿级别。
建议最好别小于16。16比256的数据量小一倍,相当于一个字节保存两个数据点。
然后开始写程序,我这边没有用画点函数drawpoint,而是直接用显示器的buffer。

  1. void Char_UbuntuMono_16(int x, int y, unsigned char c, unsigned short color, unsigned short back_color)
  2. {//12*32 = 384 wide
  3.   //26*5 =  130 high
  4.     unsigned int i, j, factor;
  5.     unsigned char alpha;
  6.     float alpha_factor;
  7.     unsigned char color_R,color_G,color_B;
  8.     unsigned char back_color_R,back_color_G,back_color_B;
  9.    
  10.     color_R = color >> 11 << 3;
  11.     color_G = color << 5 >> 10 << 2;
  12.     color_B = color << 3;
  13.    
  14.     back_color_R = back_color >> 11 << 3;
  15.     back_color_G = back_color << 5 >> 10 << 2;
  16.     back_color_B = back_color << 3;
  17.    
  18.     if(c < 128)    c = c - ' ';
  19.     else           c = c - 96;
  20.    
  21.     factor = c/32;
  22.    
  23.     for(i = 0;i < 26; i++){
  24.         for(j = 0; j < 12; j++){
  25.            alpha = font_16[384*(factor*26 + i) + (c - factor*32)*12 + j];//>>4
  26.            if(alpha == 255/*15*/) frambuf[800*(i + x) + j + y] = color;
  27.            else if(alpha == 0)    frambuf[800*(i + x) + j + y] = back_color;
  28.            else{
  29.                alpha_factor = 1.0*alpha/255/*15*/;
  30.                frambuf[800*(i + x) + j + y] = (((char)(alpha_factor*(color_R - back_color_R)) + back_color_R) >> 3) << 11 |
  31.                                               (((char)(alpha_factor*(color_G - back_color_G)) + back_color_G) >> 2) <<  5 |
  32.                                               (((char)(alpha_factor*(color_B - back_color_B)) + back_color_B) >> 3) ;
  33.            }
  34.         }
  35.     }
  36. }
复制代码


这是显示一个字符的函数,color_R,color_G,color_B是先将RGB565的数据拆分为R、G、B,背景色同理。
alpha 就是我们刚才存储的数据像素点的值。
alpha_factor*(color_R - back_color_R)) + back_color_R这个公式我解释一下,像素点的颜色=(alpha/255)*color + (255 - alpha)*back_color,转换下就是(alpha/255)*(color - back_color) + back_color;
然后将R/G/B分量各自计算出来,最后按位或成565数据。
因为数据中其实大部分都是255和0,为了显示提高显示速度和节省CPU资源,就将他们分别列出来
  1.   if(alpha == 255/*15*/) frambuf[800*(i + x) + j + y] = color;
  2.   else if(alpha == 0)    frambuf[800*(i + x) + j + y] = back_color;
复制代码

前面提到过抗锯齿级别,我这里直接用的是255级别,直接写死了,如果需要调节锯齿级别,需要自己定义一个级别数,修改三个地方即可(我已经在注释/* */里把16级别的写出来了)。

字符串函数还是那样写
  1. void String_UbuntuMono_16(int x,int y, unsigned char *str, unsigned short color, unsigned short back_color)
  2. {
  3.     unsigned char *p = str;
  4.     while (*p != 0){
  5.         Char_UbuntuMono_16(x, y, *p, color, back_color);
  6.         y = y + 12;
  7.         p++;
  8.     }
  9. }
复制代码


最后显示一下带有抗锯齿功能的字体
  1.     String_UbuntuMono_16(200, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", COLOR_WHITE, COLOR_BACK_GROUND);
  2.     String_UbuntuMono_16(230, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", COLOR_GREEN, COLOR_WHITE);
  3.     String_UbuntuMono_16(260, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", COLOR_RED, COLOR_BLUE);
  4.     String_UbuntuMono_16(290, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", COLOR_YELLOW, COLOR_BLACK);
复制代码

显示如下


再次感谢大神redroof!

往期帖子 :
给大家介绍一种做界面的去锯齿方法  https://www.amobbs.com/thread-5675562-1-1.html
液晶多级菜单实现加强版  https://www.amobbs.com/thread-5599589-1-1.html
嵌入式全键盘拼音输入法分享  https://www.amobbs.com/thread-5668320-1-1.html
ucgui下制作漂亮按键 https://www.amobbs.com/thread-5551143-1-1.html

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出10入0汤圆

发表于 2017-6-23 23:41:06 来自手机 | 显示全部楼层
关注一下,谢谢分享!

出0入0汤圆

发表于 2017-6-24 03:05:14 | 显示全部楼层
谢谢分享

出25入84汤圆

 楼主| 发表于 2017-6-27 09:21:28 | 显示全部楼层
如果需要显示透明字符,需要改动如下

  1. void Char_UbuntuMono_16(int x, int y, unsigned char c, unsigned short color)
  2. {//12*32 = 384 wide
  3.   //26*5 =  130 high
  4.     unsigned int i, j, factor;
  5.     unsigned char alpha;
  6.     float alpha_factor;
  7.     unsigned char color_R,color_G,color_B;
  8.     unsigned short int back_color;
  9.     unsigned char back_color_R,back_color_G,back_color_B;
  10.    
  11.     color_R = color >> 11 << 3;
  12.     color_G = color << 5 >> 10 << 2;
  13.     color_B = color << 3;
  14.    
  15.     if(c < 128)    c = c - ' ';
  16.     else           c = c - 96;
  17.    
  18.     factor = c/32;
  19.    
  20.     for(i = 0;i < 26; i++){
  21.         for(j = 0; j < 12; j++){
  22.            alpha = font_16[384*(factor*26 + i) + (c - factor*32)*12 + j];//>>4
  23.            if(alpha == 255/*15*/) frambuf[800*(i + x) + j + y] = color;
  24.            else if(alpha == 0);//显示为原来的背景色,不做改变。
  25.            else{
  26.                back_color =  frambuf[800*(i + x) + j + y];//取当前背景颜色为back_color。
  27.                   back_color_R = back_color >> 11 << 3;
  28.                  back_color_G = back_color << 5 >> 10 << 2;
  29.                  back_color_B = back_color << 3;
  30.                alpha_factor = 1.0*alpha/255/*15*/;
  31.                frambuf[800*(i + x) + j + y] = (((char)(alpha_factor*(color_R - back_color_R)) + back_color_R) >> 3) << 11 |
  32.                                               (((char)(alpha_factor*(color_G - back_color_G)) + back_color_G) >> 2) <<  5 |
  33.                                               (((char)(alpha_factor*(color_B - back_color_B)) + back_color_B) >> 3) ;
  34.            }
  35.         }
  36.     }
  37. }
复制代码

出0入0汤圆

发表于 2017-6-27 09:35:03 | 显示全部楼层
chun2495 发表于 2017-6-27 09:21
如果需要显示透明字符,需要改动如下

透明是指直接显示背景色还是有x%透明度的半透明?

出25入84汤圆

 楼主| 发表于 2017-6-27 09:48:47 | 显示全部楼层
shower.xu 发表于 2017-6-27 09:35
透明是指直接显示背景色还是有x%透明度的半透明?

指的是直接显示背景,如果背景只有x%透明度,那么和周围背景将会不一样。

出0入0汤圆

发表于 2017-6-27 09:58:09 | 显示全部楼层
chun2495 发表于 2017-6-27 09:48
指的是直接显示背景,如果背景只有x%透明度,那么和周围背景将会不一样。 ...

受教了,谢谢

出0入0汤圆

发表于 2017-6-27 10:08:48 | 显示全部楼层
感谢分享。不过楼主给指点一下,楼主位的最后一张图片中那4行字符除了颜色外有什么区别?没看懂是怎么回事

出5入10汤圆

发表于 2017-6-27 10:33:38 | 显示全部楼层
先顶起来,回头腾出时间再仔细看,最近有点忙

出130入20汤圆

发表于 2017-6-27 10:35:29 | 显示全部楼层
一直用的EMWIN自带的抗锯齿挺好的

出25入84汤圆

 楼主| 发表于 2017-6-27 10:41:50 | 显示全部楼层
winterw 发表于 2017-6-27 10:08
感谢分享。不过楼主给指点一下,楼主位的最后一张图片中那4行字符除了颜色外有什么区别?没看懂是怎么回事 ...

就是只用一个黑底白字的图片数据,可以生成任意颜色和背景色的抗锯齿字体,而且锯齿级别还能调整。

出25入84汤圆

 楼主| 发表于 2017-6-27 10:48:12 | 显示全部楼层
shuiluo2 发表于 2017-6-27 10:35
一直用的EMWIN自带的抗锯齿挺好的

这个是自己写gui,原理和emwin差不多。

出0入0汤圆

发表于 2017-6-27 11:08:34 | 显示全部楼层
chun2495 发表于 2017-6-27 10:48
这个是自己写gui,原理和emwin差不多。

这个和emwin的抗锯齿原理不一样吧,emwin的字库是单色的,1位表示一个点

出25入84汤圆

 楼主| 发表于 2017-6-27 11:22:19 | 显示全部楼层
modbus 发表于 2017-6-27 11:08
这个和emwin的抗锯齿原理不一样吧,emwin的字库是单色的,1位表示一个点

哦 想起来了,的确不一样,emwin应该还有把单色转换为过渡色的一套算法,我这个直接由photoshop完成。

出870入263汤圆

发表于 2017-7-20 13:59:16 | 显示全部楼层
emwin的xbf和sif字库本身就支持抗锯齿的。

出0入0汤圆

发表于 2017-7-20 16:12:31 | 显示全部楼层
以前做过一个外发光效果的字库生成工具,

字体分为:
前景每个点16级Alpha值,占4位
背景发光体16级Alpha值,占4位
即1个点,1个字节表示。
可实现发光边,Shadow等效果。

出0入0汤圆

发表于 2017-7-27 11:38:16 | 显示全部楼层
关注一下,谢谢分享!

出0入0汤圆

发表于 2017-7-27 11:48:36 | 显示全部楼层
用emwin自带的比这个好多了,这样只能是等宽的字体。

出25入84汤圆

 楼主| 发表于 2017-7-27 13:25:24 | 显示全部楼层
czg1411 发表于 2017-7-27 11:48
用emwin自带的比这个好多了,这样只能是等宽的字体。

用emwin的就不用看了,本身就是给不带gui的写的。

出0入0汤圆

发表于 2017-7-27 13:55:48 | 显示全部楼层
chun2495 发表于 2017-7-27 13:25
用emwin的就不用看了,本身就是给不带gui的写的。

用他的取字模工具和带不带gui没关系

出25入84汤圆

 楼主| 发表于 2017-7-27 13:58:24 | 显示全部楼层
czg1411 发表于 2017-7-27 13:55
用他的取字模工具和带不带gui没关系

求软件   

出0入0汤圆

发表于 2017-7-27 14:04:54 | 显示全部楼层

FontCvt.exe

出25入84汤圆

 楼主| 发表于 2017-7-27 15:37:25 | 显示全部楼层

的确可以,只是中文的好像没有,不知道中文是怎样的思路。

出0入0汤圆

发表于 2017-7-27 15:47:43 | 显示全部楼层
chun2495 发表于 2017-7-27 15:37
的确可以,只是中文的好像没有,不知道中文是怎样的思路。

有中文

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2017-7-28 21:29:42 来自手机 | 显示全部楼层
原理应该和emwin一样吧,都是多位表示一个点,用工具生成的字库也是工具计算好的,内部自带的不知道是什么样的

出25入84汤圆

 楼主| 发表于 2017-11-21 17:53:24 | 显示全部楼层
修改一个bug,最后三行的char改为unsigned char 否则有的字体过渡色会出现跳色的情况。
  1. void Char_UbuntuMono_12_26(int x, int y, unsigned char c, unsigned short color, unsigned short color_ground)
  2. {//12*32 = 384 wide
  3.   //26*5 =  130 high
  4.     unsigned int i, j, factor;
  5.     unsigned char alpha;
  6.     float alpha_factor;
  7.     unsigned char color_R,color_G,color_B;
  8.     unsigned char back_color_R,back_color_G,back_color_B;
  9.    
  10.     color_R = color >> 11 << 3;
  11.     color_G = color << 5 >> 10 << 2;
  12.     color_B = color << 3;
  13.    
  14.     back_color_R = color_ground >> 11 << 3;
  15.     back_color_G = color_ground << 5 >> 10 << 2;
  16.     back_color_B = color_ground << 3;
  17.    
  18.     if(c < 128)    c = c - ' ';
  19.     else           c = c - 96;
  20.    
  21.     factor = c/32;
  22.    
  23.     for(j = 0;j < 26; j++){
  24.         for(i = 0; i < 12; i++){
  25.            alpha = UbuntuMono_12_26[384*(factor*26 + j) + (c - factor*32)*12 + i];
  26.            if(alpha == 255)       LCD_DrawPoint(i + x, j + y, color);
  27.            else if(alpha == 0)    LCD_DrawPoint(i + x, j + y, color_ground);
  28.            else{
  29.                alpha_factor = 1.0*alpha/255;
  30.                LCD_DrawPoint(i + x, j + y, (((unsigned char)(alpha_factor*(color_R - back_color_R)) + back_color_R) >> 3) << 11 |
  31.                                            (((unsigned char)(alpha_factor*(color_G - back_color_G)) + back_color_G) >> 2) <<  5 |
  32.                                            (((unsigned char)(alpha_factor*(color_B - back_color_B)) + back_color_B) >> 3)) ;
  33.            }
  34.         }
  35.     }
  36. }
复制代码

出25入84汤圆

 楼主| 发表于 2017-11-22 10:21:08 | 显示全部楼层
显示字符较长时,能够明显感觉到延时卡顿现象,最后发现原来是浮点型运算导致的。现在去掉浮点型运算改动程序后,发现显示速度非常快,代码如下:
  1. void Char_UbuntuMono_12_26(int x, int y, unsigned char c, unsigned short color, unsigned short color_ground)
  2. {//12*32 = 384 wide
  3.   //26*5 =  130 high
  4.     unsigned int i, j, factor;
  5.     unsigned char alpha;
  6. //    short alpha_factor;
  7.     unsigned char color_R,color_G,color_B;
  8.     unsigned char back_color_R,back_color_G,back_color_B;
  9.    
  10.     color_R = color >> 11 << 3;
  11.     color_G = color << 5 >> 10 << 2;
  12.     color_B = color << 3;
  13.    
  14.     back_color_R = color_ground >> 11 << 3;
  15.     back_color_G = color_ground << 5 >> 10 << 2;
  16.     back_color_B = color_ground << 3;
  17.    
  18.     if(c < 128)    c = c - ' ';
  19.     else           c = c - 96;
  20.    
  21.     factor = c/32;
  22.    
  23.     for(j = 0;j < 26; j++){
  24.         for(i = 0; i < 12; i++){
  25.            alpha = UbuntuMono_12_26[384*(factor*26 + j) + (c - factor*32)*12 + i];
  26.            if(alpha == 255)       LCD_DrawPoint(i + x, j + y, color);
  27.            else if(alpha == 0)    LCD_DrawPoint(i + x, j + y, color_ground);
  28.            else{
  29. //               alpha_factor = 1*alpha/255;
  30.                LCD_DrawPoint(i + x, j + y, (((unsigned char)(alpha*(color_R - back_color_R)/255) + back_color_R) >> 3) << 11 |
  31.                                            (((unsigned char)(alpha*(color_G - back_color_G)/255) + back_color_G) >> 2) <<  5 |
  32.                                            (((unsigned char)(alpha*(color_B - back_color_B)/255) + back_color_B) >> 3)) ;
  33.            }
  34.         }
  35.     }
  36. }
复制代码

出0入0汤圆

发表于 2019-6-22 09:15:15 | 显示全部楼层
chun2495 发表于 2017-11-22 10:21
显示字符较长时,能够明显感觉到延时卡顿现象,最后发现原来是浮点型运算导致的。现在去掉浮点型运算改动程 ...

谢谢分享 学习了   最近想玩彩屏   这个看起来很有用

出0入0汤圆

发表于 2019-6-22 15:28:35 | 显示全部楼层
请问楼主到底解决没解决汉字抗锯齿啊?

出25入84汤圆

 楼主| 发表于 2019-7-1 14:21:27 | 显示全部楼层
carryonli 发表于 2019-6-22 15:28
请问楼主到底解决没解决汉字抗锯齿啊?


因为汉字数量多,按照这个方法抗锯齿也能做,将汉字存储在flash中,每次来读取就行。
如果用字不是很多的话,将汉字数据放入内存中。我就是用这个来显示汉字。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-19 06:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表