---原理、实现---
这一次来关注一下PS的缩放问题,PS使用的缩放方法是近邻取样插值(nearest neighbor interpolation)算法。但相比一般邻近算法作了改进,我们要做的就是找到这个改进的算法。
下面先简单说明近邻取样插值的一般方法:按照缩放比例使用公式Sx=Dx*(Sw/Dw)求出目标像素对应的源像素(参见参考文章1)。开始我也使用的这种方法,但缩放结果与PS相比,像素插入位置不同,主要区别PS中是以中线为基准两边对称的。但沿着对称的思路想了几个方法,都达不到要求,上网搜也没有头绪。
这个状况让我想起当初解决蚂蚁线问题时情形(link):从对流动蚂蚁线表面现象的简单模拟到经过仔细观察思考发现,流动的线条只是一种更简单高效算法的外在表现。意识到这点之后,不再乱试,试着从定义出发重新审视这个问题,目标是找到一个计算方便、形式简单乃至具有美感的(对称)、最好不用除法,可以精确描述位置的算法。
举个例子重新描述一下问题,一个10 x 10的图像,放大130%,会生成一个13 x 13的图像,因为纵横向放大比例相同,只需要计算一行数据即可,从10个点到13个点,多了3个点,现在问题来了,要把10个像素插到13个空位的哪10个位置?同时多出来的3个空位用10个中的哪个像素重复填充?
想象这样一种需要一个像素一个像素处理的插值算法,再结合上面的算法要求——插值、一步一步处理、对称、不用除法、精确描述——灵感出现,这些东西与Bresenham算法的要素特点是不是很相似呢?那是不是可以使用Bresenham算法解决这个问题呢?有点小激动,马上动手,一番画图推导计算之后,不出意外确实可以,并且有了Bresenham关键字,也很容易的搜索到了参考文章2。
下面说一下基本思路,就是把像素放大,原来的10个像素,放大成10个13x13的像素,13个像素放大成13个10x10的像素,使13个"像素"能无缝填充到10"像素"的空间中去,然后通过对比确定填充的对应像素。此时可以看作是一个填格子的游戏,10个长度13的大格子排一列,然后用13个长度为10的小格子填充,最后做一个对比,小格子落到哪个大格子的部分多,就填到哪个大格子,如果落入不同大格子的两个部分相同,算哪个都可以,但填入后一个格子计算简单(一图顶千言,参见图1)。
图1
---代码及程序(masm32)---
http://files.cnblogs.com/hhh2000/Zoom.zip
---参考文章---
1、高质量的快速的图像缩放 上篇 近邻取样插值和其速度优化 http://blog.csdn.net/housisong/article/details/1404896
一般的近邻取样插值算法
2、基于Bresenham算法的图像快速缩放处理 http://www.doc88.com/p-699581250411.html
相同的算法、有推导、有公式
3、Quick image scaling algorithms and code http://www.compuphase.com/graphic/scale.htm http://willperone.net/Code/codescaling.php
另一种Bresenham类算法,形式更简单但不对称