我正在寻找一种快速算法来绘制轮廓线。对于此应用,轮廓只需要1像素宽。无论是默认还是通过选项,都应该可以使两条线无缝连接在一起,如果它们共享一个公共点。
请原谅ASCII艺术,但这可能是展示它的最佳方式。
正常线:
##
##
##
##
##
##
“概述”行:
**
*##**
**##**
**##**
**##**
**##**
**##*
**
我正在研究dsPIC33FJ128GP802。它是一个小型微控制器/数字信号处理器,能够达到40 MIPS(每秒百万条指令)。它只能进行整数数学运算(加,减和乘:它可以进行除法,但需要约19个周期。)它正在被使用为了同时处理OSD层,只有3-4 MIPS的处理时间可用于计算,因此速度至关重要。像素占据三种状态:黑色,白色和透明;视频场是192x128像素。这适用于Super OSD,一个开源项目:http://code.google.com/p/super-osd/
我想到的第一个解决方案是在第一遍中绘制带有轮廓像素的3x3矩形,在第二遍上绘制普通像素,但这可能很慢,因为每个像素都会覆盖至少3个像素并且绘制时间他们浪费了。所以我正在寻找一种更快捷的方式。每个像素花费大约30个周期。目标是<50,000次循环以绘制100像素长度的线。
答案 0 :(得分:1)
我建议这个(C /伪代码混合):
void draw_outline(int x1, int y1, int x2, int y2)
{
int x, y;
double slope;
if (abs(x2-x1) >= abs(y2-y1)) {
// line closer to horizontal than vertical
if (x2 < x1) swap_points(1, 2);
// now x1 <= x2
slope = 1.0*(y2-y1)/(x2-x1);
draw_pixel(x1-1, y1, '*');
for (x = x1; x <= x2; x++) {
y = y1 + round(slope*(x-x1));
draw_pixel(x, y-1, '*');
draw_pixel(x, y+1, '*');
// here draw_line() does draw_pixel(x, y, '#');
}
draw_pixel(x2+1, y2, '*');
}
else {
// same as above, but swap x and y
}
}
编辑:如果您希望连续的线路无缝连接,我
认为你必须在第一遍中绘制所有轮廓,并且
然后是线条。我编辑了上面的代码,只绘制了轮廓。该
draw_line()
函数将完全相同但只有一个
draw_pixel(x, y, '#');
代替四个draw_pixel(..., ..., '*');
。
然后你就是:
void draw_polyline(point p[], int n)
{
int i;
for (i = 0; i < n-1; i++)
draw_outline(p[i].x, p[i].y, p[i+1].x, p[i+1].y);
for (i = 0; i < n-1; i++)
draw_line(p[i].x, p[i].y, p[i+1].x, p[i+1].y);
}
答案 1 :(得分:0)
我的方法是使用Bresenham绘制多条线。看看你的ASCII艺术,你会注意到轮廓线与Bresenham线相同,只是向上和向下移动了1个像素 - 加上第一个点左边的一个像素和最后一个点的右边
对于通用版本,您需要确定您的线路是平坦的还是陡峭的 - 即是否abs(y1 - y0) <= abs(x1 - x0)
。对于陡峭的线条,轮廓向左和向右移动1个像素,关闭像素高于开始点和结束点。
通过为每个线像素一次性绘制线条和两个轮廓像素,可能值得优化。但是,如果您需要无缝轮廓,最简单的解决方案是首先绘制所有轮廓,然后绘制线条本身 - 这不适用于“三像素 - 布雷森汉姆”优化。