2

I'd like to control the slantiness (italic) of a text according a given degree and direction (left or right tilt) similar as presented in the image below:

enter image description here

I have stumble upon this great answer: How does perspective transformation work in PIL?, played with the code, and read the documentation of AFFINE but it's still isn't clear enough for me.

Can someone please explain me (mathematic and logic wise), how can I do this? Thank you.

alyssaeliyah
  • 2,214
  • 6
  • 33
  • 80
JammingThebBits
  • 732
  • 11
  • 31
  • I've added a mirror to the broken link in the referenced answer. Does that help? – Caramiriel Aug 05 '18 at 12:51
  • @Caramiriel Thank you, but the mirror is a bit too technical for me, I just know in context of the transform function: The data is a 6-tuple ( a, b, c, d, e, f) which contain the first two rows from an affine transform matrix. For each pixel (x,y) in the output image, the new value is taken from a position (ax+by+c,dx+ey+f) in the input image, rounded to nearest pixel. – JammingThebBits Aug 05 '18 at 13:22
  • A great explanation I found is written here in the following document: https://people.cs.clemson.edu/~dhouse/courses/401/notes/affines-matrices.pdf – JammingThebBits Aug 05 '18 at 13:43

1 Answers1

4

To generate some text we can use any method, here I am using ImageFont to get a black and white mask.

def generate_text(text):
    fnt = ImageFont.truetype('arial.ttf', 72)
    img = Image.new('1', fnt.getsize(text))
    mask = [x for x in fnt.getmask(text, mode='1')]
    img.putdata(mask)
    img = img.convert('RGB')
    return img

enter image description here

Then, I would like to add padding on the left and right because we will be shearing the text horizontally.

def add_border(img, width):
    new = Image.new('RGB', (img.width + 2 * width, img.height), (0, 0, 0))
    new.paste(img, (width, 0))
    return new

enter image description here

Finally, I will use an affine transformation using the b value, which if you look a the formula, it is the coefficient of y that will be added to x. So, a larger b will shear horizontally more. In this case I am using 2.

def shear(img, shear):
    shear = img.transform(img.size, Image.AFFINE, (1, shear, 0, 0, 1, 0))
    return shear

enter image description here

The calling code:

img = generate_text('test')
img = add_border(img, 200)
img = shear(img, 2)
Alistair Carscadden
  • 1,198
  • 5
  • 18