【绘图算法】Bresenham算法(草稿)

起点

在使用单片机做LCD屏显示的时候遇到画直线(实际上是线段)的问题。

具体的问题就是如何将直线的公式(或者是已知两点)转变为点阵结构,找到相应的点。

搜索了下,大多利用Bresenham较简单的绘制直线,以下就是如何理解该算法。

算法一

最简单的算法,莫过于直接采用直线的公式,y=kx+b,利用x每次自增1,来计算y的值,利用取整来获得像素点。

例如:y = 0.8 *x + 1;

x=0,y=1

x=1,y=1.8 =2

x=2,y=2.6 = 3

x=3,y=3.4=3

x=4,y=4.2=4

x=5,y=5.0=5

x=6,y=5.8=6

x=7,y=6.6=7

x=8,y=7.4=7

x=9,y=8.2=8

x=10,y=9

……

如下图:

(放大看)

计算机实际算法(两点直线)如下:

DrawLine(int x1,int y1,int x2,int y2)
{
   int i,y;
  double k = (y2-y1)/(x2-x1);
   double b = y1 - k*x1;
   for(i=x1;i<=x2;i++)
   {
      y = (int)(k*i + b);
      DrawPoint(i,y);  
   }
}

但实际画图中会出现下图情况,绘制的效果并不好:

例如:y=1.6x+1

x=0,y=1

x=1,y=2.6=3

x=2,y=4.2=4

x=3,y=5.8=6

x=4,y=7.4=7

x=5,y=9

x=6,y=10.6=11

x=7,y=12.2=12

x=8,y=13.8=14

x=9,y=15.4=15

x=10,y=17

(放大看)

可以看出,直线有间断,解决的方法是,将x,y对调,增量从x变为y。

那么对应的算法中,应该是判断直线在x与y方向上,谁的增量大,谁就应该作为每次自增1的量。

算法改进如下:

DrawLine(int x1,int y1,int x2,int y2)
{
   int i,n;
   if(abs(x2-x1)>abs(y2-y1))
   { 
    double k = (y2-y1)/(x2-x1);
     double b = y1 - k*x1;
     for(i=x1;i<=x2;i++)
     {
        n = (int)(k*i + b);
        DrawPoint(i,n);  
     }
   }
   else
   { 
     double k = (x2-x1)/(y2-y1);
     double b = x1 - k*y1;
     for(i=y1;i<=y2;i++)
     {
        n = (int)(k*i + b);
        DrawPoint(n,i);  
     }
 } 
  
 } 
  
 
  

Bresenham算法

以上算法有个很大的问题:

对于计算机来说,浮点数计算并不算复杂,但是对于单片机来说,整数计算远比浮点数计算方便,

Bresenham算法即是以上算法的改进,采用整数运算,避免了浮点数计算。

 
  
 
  
 
 

你可能感兴趣的:(图像处理,MCS-51,STM32F103)