1

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):

enter image description here

To this:

enter image description here

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;
}

Source

After a bit more Google searching I found this:

float Lerp(float firstFloat, float secondFloat, float by)
{
     return firstFloat * (1 - by) + secondFloat * by;
}

Source

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?

Ξένη Γήινος
  • 2,181
  • 1
  • 9
  • 35

0 Answers0