我正在尝试实现使用shpere失真滤波器的应用程序。我使用的是从算法在这里,改变由getPixel像素位置()和setpixel()方法。我的问题是,对于Android设备而言,它太慢了,并且有些应用程序比我的方法更快地实现相同的sphere(和其他)过滤器方法。(例如Picsay Pro应用程序)任何人都可以分享或提供指导,以查找或实施快速失真算法。
实现该算法的实际过滤器:
public boolean sphereFilter(Bitmap b, boolean bSmoothing) { int nWidth = b.getWidth(); int nHeight = b.getHeight(); Point [][] pt = new Point[nWidth][nHeight]; Point mid = new Point(); mid.x = nWidth/2; mid.y = nHeight/2; double theta, radius; double newX, newY; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { pt[x][y]= new Point(); } for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { int trueX = x - mid.x; int trueY = y - mid.y; theta = Math.atan2((trueY),(trueX)); radius = Math.sqrt(trueX*trueX + trueY*trueY); double newRadius = radius * radius/(Math.max(mid.x, mid.y)); newX = mid.x + (newRadius * Math.cos(theta)); if (newX > 0 && newX < nWidth) { pt[x][y].x = (int) newX; } else { pt[x][y].x = 0; pt[x][y].y = 0; } newY = mid.y + (newRadius * Math.sin(theta)); if (newY > 0 && newY < nHeight && newX > 0 && newX < nWidth) { pt[x][ y].y = (int) newY; } else { pt[x][y].x = pt[x][y].y = 0; } } offsetFilterAbs(b, pt); return true; }
替换计算出的像素位置的代码。
public boolean offsetFilterAbs(Bitmap b, Point[][] offset ) { int nWidth = b.getWidth(); int nHeight = b.getHeight(); int xOffset, yOffset; for(int y=0;y < nHeight;++y) { for(int x=0; x < nWidth; ++x ) { xOffset = offset[x][y].x; yOffset = offset[x][y].y; if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth) { b.setPixel(x, y, b.getPixel(xOffset, yOffset)); } } } return true; }
我目前正在使用与您链接上相同的算法,对于Android设备来说仍然太慢
从上面评论中的链接:
给定 r = Sqrt((x-0.5)^ 2 +(y-0.5)^ 2) a = ArcTan2(y-0.5,x-0.5) n =膨胀系数(默认= 1) 组 x'= r ^ n * Cos(a)+ 0.5 y'= r ^ n * Sin(a)+ 0.5
(请记住,在这个等式中,x并且y跨度从0到1.如果您的尺寸跨度从0到w,更换0.5用w/2)
x
y
w
0.5
w/2
通过一点数学,我们可以看到
Cos(a)= Cos(ArcTan2(y-0.5,x-0.5)) =(x-0.5)/ r Sin(a)= Sin(ArcTan2(y-0.5,x-0.5)) =(y-0.5)/ r
这使得最终的方程式
r =(x-0.5)^ 2 +(y-0.5)^ 2 n =膨胀系数(默认= 0) 组 x'= r ^ n *(x-0.5)+ 0.5 y'= r ^ n *(y-0.5)+ 0.5
(我删除了平方根,因为无论如何我们都将结果取为实数…因此,要真正使之等效,我们应该使用n/2而不是n,但是由于我们_定义的是 “膨胀因子”,因此我们可以省略额外的划分)_
n/2
n
仅需少量的乘法运算和一个实数乘积,这可能是您希望获得的最快速度。