位图缩放的快速方法
位图缩放的快速方法
来来叔叔 发表于4个月前
位图缩放的快速方法
  • 发表于 4个月前
  • 阅读 1
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

 

在嵌入式系统中快速地进行屏幕拉伸,不能采用线性插值之类的算法,那样太慢。只能采用复制或抽取像素行的方式实现。

网上有介绍位图快速拉伸的算法,如下:http://www.abcdown.net/InfoView/Article_212765.html

  假设欲将长度为N1的像素列变成长度为N2的像素列,首先,设立两个指针,一个作为源指针,指向原来的像素列,读取源像素,另一个作为目的指针,指向变换后的像素列,写入读取到的像素。然后,以拉伸后像素列的长度为循环次数,循环N2次,每次循环中由源指针处COPY一个像素到目的指针处,然后目的指针加一,源指针根据每次循环的不同需要增加一定步长(放大时步长是零或一,缩小时步长大于等于一)。
  算法的框架解决了,但是中心内容仍没有解决:如何确定每次循环里源指针增加的步长?或者说,每次循环里如何更新源指针的位置?容易看出,通过浮点运算很容易解决这个问题:设立一个初值为零的浮点变量,每次循环中,把这个浮点变量加上N1/N2,并将其结果的整数部分作为源指针距离起始位置的偏移量;这样,经过N2次循环,浮点变量的值恰好达到N1,源指针也恰好“走”到原像素列的末尾。
  这个方法可行,但是太慢。如果能将浮点运算转化成整数运算就快多了。那么如何转化呢?我们可以设立一个值域为N1*N2的整数计数器,每次循环递增N1,并且规定,计数器每增加N2,源指针就前进一个像素。这样,经过N2次循环,计数器共增加了N1*N2,源指针则增加了N1个单元,恰好“走”完全程。实际编程中,我们是用一个值域为N2的整数计数器,超出值域部分取模处理。算法大致如下:

int m = 0, count = 0;

for (int n = 0; n < N2; n++)
    {
      dest_pixels[n] = src_pixels[m];
      count += N1;
      while (count >= N2)
      {
        count -= N2;
        m++;
        }
    }

上面已经说得比较明白了,不过对于愚钝的我来说,还是不容易理解。于是再分解如下:

用插值的思维来看,目的像素与源像素的关系其实如下:

dest_pixels[(n)=src_pixels(n*N1/N2) ,n=1,2,...,N2
由于只有整数点像素,其中的n*N1/N2要进行取整。
[n*N1/N2]就是n*N1除以N2得到的整数部分嘛,怎么用算法来求整数部分呢?

设p=[n*N1/N2]=n*N1-m*N2   (m为一整数,p<N2)

就用n*N1每次减一个N2,m增加1, 直到p<=0为止,得到的m值就是n*N1/N2的整数部分。

m=0;
c=n*N1;
while(c>0)
{
c-=N2;
m++;
}

这样最上面的源程序就容易明白了,里面的while循环其实就是用来求n*N1/N2的整数部分的。稍微不同的是,最上面的源程序中的count、m是从一开始就累减和累加的,不用每个n都重新求,精度会不会稍有些不同?

共有 人打赏支持
粉丝 0
博文 100
码字总数 55732
×
来来叔叔
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: