2

这是对这个问题的跟进。

我正在开发一个低级 C 应用程序,我必须在其中绘制文本。我决定将我想使用的字体存储为一个数组(黑白,每个字符 128x256,也许),然后我会用一些算法将它缩小到我需要的大小(作为灰度,所以我可以有一些粗略的字体平滑)。

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

问题是,哪种算法?

我抬头看了看2xSaI,还是挺复杂的。我想要一些我可以阅读描述并自己编写代码的东西(我是一个初学者,并且已经用 C/C++ 编码不到一年)。

建议,有人吗?

谢谢你的时间!

编辑:请注意,输入是黑白的,输出应该是平滑的灰度

4

5 回答 5

4

找出源图像中与目标像素对应的矩形。例如,如果您的源图像是 50x100,而目标是 20x40,则目标中左上角的像素对应于源图像中从 (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 的因子),而那些不是完全错误的则实施起来更痛苦,可能不会给你更好的结果.

于 2010-11-14T22:28:58.343 回答
3

考虑您的图像是 N*M BW 位图。为简单起见char Letter[N][M],当允许的值为0和时,我们将考虑它1。现在考虑您要将其缩小到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);
};

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

于 2010-11-14T22:22:03.010 回答
2

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

于 2010-11-14T22:03:34.923 回答
1

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

必须处理分数映射是一种编程练习,但不能提高质量。

于 2010-11-14T22:41:15.477 回答
0

如果将缩小限制为 2 的倍数(50%、25%、12.5% 等)是可以接受的,那么一个非常简单且相当好的算法是创建每个缩小的像素作为所有源像素的多数票。例如,在 50% 时,一个由四个像素组成的正方形构成了一个缩小的像素:如果其中 0 个或其中一个打开,则输出关闭;如果三个或四个打开,则输出打开。艺术案例(两个像素打开),要么总是选择打开或关闭,要么查看其他周围的像素以进行平局。

于 2010-11-14T22:06:21.527 回答