pythonpython-imaging-libraryaffinetransform

Pillow (PIL) affine image transform wrong direction


Using Python's Pillow (PIL) module I'm trying to shift an image 85 pixels to the right using an affine transform. The below code should to this, but instead shifts the image seemingly in the wrong direction to the left. Am I misunderstanding something?

from PIL import Image
test_image = Image.open('Test image.png')
affine_params = [1, 0, 85, 0, 1, 0]
trans_image = test_image.transform(test_image.size, Image.AFFINE, affine_params, Image.BILINEAR, fillcolor = (150,150,150))
trans_image.save('Transformed image.png')

Input image: Input image

Output image: Output image

The documentation isn't all in one place, but this says given affine_params = [a, b, c, d, e, f] a pixel's new position is x_new, y_new = (a*x_old + b*y_old + c, d*x_old + e*y_old + f) so a positive value for c ?should? give a shift the right?


Solution

  • From: https://pillow.readthedocs.io/en/stable/reference/ImageTransform.html#PIL.ImageTransform.AffineTransform

    class PIL.ImageTransform.AffineTransform(data: Sequence[Any])[source]

    Bases: Transform

    Define an affine image transform.

    This function takes a 6-tuple (a, b, c, d, e, f) which contain the first two rows from the inverse of an affine transform matrix. For each pixel (x, y) in the output image, the new value is taken from a position (a x + b y + c, d x + e y + f) in the input image, rounded to nearest pixel.

    This function can be used to scale, translate, rotate, and shear the original image.

    (Emphasis mine)

    To be explicit: the new value of the pixel at (x,y) is the current value of the pixel at (a x + b y + c, d x + e y + f). This means you want to use [1,0,-85,0,1,0] to shift the image to the right (since each pixel (x,y) will end up with the value of the current image at (x-85,y)).