Rotating a square in PIL

僤鯓⒐⒋嵵緔 提交于 2021-02-07 08:30:03

问题


With PIL, I want to draw a rotated square on an image, by specifying the square side length, and the rotation angle. The square should be white, and the background grey. For example, the following image has a rotation of 45 degrees:

The only way I know how to do rotations in PIL is by rotating the entire image. But if I start with the following image:

And then rotate it by 45 degrees, I get this:

That method just introduces black parts to fill in the "undefined" region of the image.

How can I rotate just the square?

The code to generate my original square (the second figure) is as follows:

from PIL import Image

image = Image.new('L', (100, 100), 127)
pixels = image.load()

for i in range(30, image.size[0] - 30):
    for j in range(30, image.size[1] - 30):
        pixels[i, j] = 255

rotated_image = image.rotate(45)
rotated_image.save("rotated_image.bmp")

回答1:


If all you want to do is draw a solid color square at some arbitrary angle, you can use trigonometry to calculate the vertices of the rotated square, then draw it with polygon.

import math
from PIL import Image, ImageDraw

#finds the straight-line distance between two points
def distance(ax, ay, bx, by):
    return math.sqrt((by - ay)**2 + (bx - ax)**2)

#rotates point `A` about point `B` by `angle` radians clockwise.
def rotated_about(ax, ay, bx, by, angle):
    radius = distance(ax,ay,bx,by)
    angle += math.atan2(ay-by, ax-bx)
    return (
        round(bx + radius * math.cos(angle)),
        round(by + radius * math.sin(angle))
    )

image = Image.new('L', (100, 100), 127)
draw = ImageDraw.Draw(image)

square_center = (50,50)
square_length = 40

square_vertices = (
    (square_center[0] + square_length / 2, square_center[1] + square_length / 2),
    (square_center[0] + square_length / 2, square_center[1] - square_length / 2),
    (square_center[0] - square_length / 2, square_center[1] - square_length / 2),
    (square_center[0] - square_length / 2, square_center[1] + square_length / 2)
)

square_vertices = [rotated_about(x,y, square_center[0], square_center[1], math.radians(45)) for x,y in square_vertices]

draw.polygon(square_vertices, fill=255)

image.save("output.png")

Result:




回答2:


Let's generalize to a rectangle:

  • length l in x and width w in y.
  • using a "rotation matrix".

Rotation code:

import math

def makeRectangle(l, w, theta, offset=(0,0)):
    c, s = math.cos(theta), math.sin(theta)
    rectCoords = [(l/2.0, w/2.0), (l/2.0, -w/2.0), (-l/2.0, -w/2.0), (-l/2.0, w/2.0)]
    return [(c*x-s*y+offset[0], s*x+c*y+offset[1]) for (x,y) in rectCoords]

Drawing code:

from PIL import Image
from PIL import ImageDraw
import math

L=512; W=512
image = Image.new("1", (L, W))
draw = ImageDraw.Draw(image)

vertices = makeRectangle(100, 200, 45*math.pi/180, offset=(L/2, W/2))
draw.polygon(vertices, fill=1)

image.save("test.png")


来源:https://stackoverflow.com/questions/34747946/rotating-a-square-in-pil

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!