位图缩放的快速方法

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

网上有介绍位图快速拉伸的算法,如下: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

就用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都重新求,精度会不会稍有些不同?

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/13771794/viewspace-664847/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/13771794/viewspace-664847/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值