I want to implement Paint.NET's polar inversion effect in Python.
If you don't know Paint.NET's polar inversion effect, basically, it transforms this (I created the image using Python):
To this:
After a bit of Google searching I found this:
protected override void InverseTransform(ref WarpEffectBase.TransformData data)
{
double x = data.X;
double y = data.Y;
double invertDistance = DoubleUtil.Lerp(1.0, base.DefaultRadius2 / (x * x + y * y), this.amount);
data.X = x * invertDistance;
data.Y = y * invertDistance;
}
After a bit more Google searching I found this:
float Lerp(float firstFloat, float secondFloat, float by)
{
return firstFloat * (1 - by) + secondFloat * by;
}
So putting the pieces together, this is the transformation that needs to be applied to every pixel, implemented in Python:
def lerp(x, y, by):
return x * (1 - by) + y * by
def transform_xy(x, y, width, height):
cx = width/2
cy = height/2
return x-cx, cy-y
def base_radius_squared(width, height):
radius = min(width, height) / 2
return radius ** 2
def polar_inversion(x, y, radius, strength):
invertDistance = lerp(1, radius/(x**2+y**2), strength)
return x*invertDistance, y*invertDistance
Strength is a float between -4 and 4 (inclusive). x and y are not the pixel coordinates of the pixel in the image, namely the origin is not at the upper left corner of the image, and y axis isn't downwards.
The x, y values used here are relative to the center of transformation, the origin is at the center of transformation, the center of transformation is defaulted at the center of image, and the y axis is upwards. I just want to clarify the coordinate system here.
So how do I apply the transformation to every pixel of an image as efficiently as possible without using for loop to iterate every pixel? How do I apply the transformation in a vectorized way?