I am trying to implement an application which uses shpere distortion filter. I am using an the algorithm from here which changes pixels location by getPixel() and setpixel() methods. My problem is it is too slow for Android devices and there are applications which implements same sphere(and others) filter way faster than my approach. ( for example Picsay Pro app) Could anyone share or give direction to find or implement fast distortion algorithms.
Actual filter that implements the algorithm:
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;
}
The code that replaces the calculated pixels' positions.
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;
}
I am currently using same algorithm with the one on your link already and it is still too slow for android devices
From my link in the comments above:
Given r = Sqrt((x - 0.5)^2 + (y - 0.5)^2) a = ArcTan2(y - 0.5, x - 0.5) n = Bulge factor (default = 1) Set x' = r^n * Cos(a) + 0.5 y' = r^n * Sin(a) + 0.5
(Remember that, in this equation, x
and y
span from 0 to 1. If your dimensions span from 0 to w
, replace 0.5
with w/2
)
Using a bit of math, we can see that
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
This makes the final resulting equation
r = (x - 0.5)^2 + (y - 0.5)^2 n = Bulge factor (default = 0) Set x' = r^n * (x - 0.5) + 0.5 y' = r^n * (y - 0.5) + 0.5
(I removed the square-root since we take the result to a real-power anyways... so really to make this equivalent we should use n/2
instead of n
, but since we are defining "bulge-factor," we can just leave out the extra division)
With only a handful of multiplications and a single real-exponentiation, this is probably the fastest you can hope to get.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With