缩小位图字体的算法

这是这个问题的后续行动。

我正在开发一个低级别的C应用程序,我必须在其中绘制文本。 我决定存储我想用作数组的字体(黑色和白色,每个char 128×256,也许),然后我用一些算法将它缩小到我需要的尺寸(作为灰度,所以我可以有一些原油字体平滑)。

注意:这是一个玩具项目,请忽略诸如在运行时进行计算之类的事情。

问题是, 哪种算法?

2xSaI2xSaI ,但它相当复杂。 我想要一些我可以阅读描述并自己编写代码的东西(我是一名初学者,并且已经用C / C ++编写了不到一年的时间)。

建议,有人吗?

谢谢你的时间!

编辑:请注意,输入为B&W,输出应平滑灰度

找出源图像中与目标像素对应的矩形。 例如,如果源图像为50×100且目标为20×40,则目标中的左上角像素对应于源图像中从(0,0)到(2.2,2.2)的矩形。 现在,对这些像素进行面积平均:

  • 面积为2.2 * 2.2 = 4.84。 您将结果缩放1 / 4.84。
  • (0,0),(0,1),(1,0)和(1,1)处的像素均为1个单位。
  • (0,2),(1,2),(2,0)和(2,1)处的像素均为0.2单位(因为矩形仅覆盖其中的20%)。
  • (2,2)处的像素重量为0.04(因为矩形仅覆盖其中的4%)。
  • 总重量当然是4 * 1 + 4 * 0.2 + 0.04 = 4.84。

这个很简单,因为您开始使用源图像和目标像素均匀地排列在图像的边缘。 通常,您将在滑动矩形的所有4个边/ 4个角上进行部分覆盖。

不要使用区域平均以外的算法来减小尺寸。 它们中的大多数是完全错误的 (它们导致可怕的混叠,至少有一个小于1/2的因子)并且那些不是完全错误的那些实现起来会更加痛苦,并且可能不会给你带来更好的结果。

考虑您的图像是N * M BW位图。 为简单起见,当允许值为01时,我们将其视为char Letter[N][M] 。 现在考虑你要将它缩减为unsigned char letter[n][m] 。 这意味着来自letter每个灰度像素将被计算为大位图中的白色像素数:

 char Letter[N][M]; unsigned char letter[n][m]; int rect_sz_X = N / n; // the size of rectangle that will map to a single pixel int rect_sz_Y = M / m; // in the downscaled image int i, j, x, y; for (i = 0; i < n; i++) for (j = 0; j < m; j++){ int sum = 0; for (x = 0; x < rect_sz_X; x++) for (y = 0; y < rect_sz_Y; y++) sum += Letter[i*rect_sz_X + x][j*rect_sz_Y + y]; letter[n][m] = ( sum * 255) / (rect_sz_X * rect_sz_Y); }; 

请注意,创建像素的矩形可能会重叠(如果大小不可分割)。 原始位图越大越好。

缩放位图字体与缩放任何其他位图的问题相同。 你所追求的一般算法类是插值 。 有很多方法可以做到这一点 – 通常,结果在视觉上越准确,算法就越复杂。 您可以从查看(按复杂程度递增顺序)开始:

  • 最近邻
  • 双线性插值
  • 双立方插值

这很简单。 如果你所拥有的只是一个位图字体而不是轮廓字体,那么你在选择抗锯齿像素颜色方面的选择非常有限。 例如,如果位图字体点大小恰好是所需显示点大小的四倍,那么您只能获得16个不同的选择。 4×4映射矩形中“点亮”像素的数量。

必须处理分数映射是一项编程工作,但不是提高质量的工作。

如果将缩减约束为2的倍数(50%,25%,12.5%等)是可接受的,则一个非常简单且相当好的算法是将每个缩小的像素创建为所有源像素的多数投票。 例如,在50%时,四个像素的正方形形成一个缩小的像素:如果它们中的一个或一个打开,则输出关闭; 如果打开三个或四个,则输出打开。 艺术案例(对于两个像素),要么总是选择打开,要么关闭,或者查看其他周围像素以进行打破。