File size: 2,314 Bytes
aa9ec19 9a5111a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | from __future__ import annotations
from typing import Literal
import gradio as gr
from PIL import Image
RotationMode = Literal["Clockwise 90", "Counterclockwise 90", "Custom angle"]
def rotate_image(
image: Image.Image | None,
rotation_mode: RotationMode,
custom_angle: float | None,
) -> Image.Image | None:
if image is None:
return None
if rotation_mode == "Clockwise 90":
angle = -90
elif rotation_mode == "Counterclockwise 90":
angle = 90
else:
angle = -(custom_angle or 0)
return image.rotate(
angle,
expand=True,
resample=Image.Resampling.BICUBIC,
fillcolor=(255, 255, 255, 0) if image.mode == "RGBA" else None,
)
def show_custom_angle(rotation_mode: RotationMode):
return gr.update(visible=rotation_mode == "Custom angle")
def build_app() -> gr.Blocks:
with gr.Blocks(title="PicRotate", theme=gr.themes.Soft()) as demo:
gr.Markdown("# PicRotate")
with gr.Row():
input_image = gr.Image(
label="Image",
sources=["upload", "clipboard"],
type="pil",
image_mode="RGBA",
height=460,
)
output_image = gr.Image(
label="Rotated image",
type="pil",
image_mode="RGBA",
height=460,
)
with gr.Row():
rotation_mode = gr.Radio(
choices=["Clockwise 90", "Counterclockwise 90", "Custom angle"],
value="Clockwise 90",
label="Rotation",
)
custom_angle = gr.Number(
value=45,
label="Custom angle in degrees clockwise",
precision=2,
visible=False,
)
rotate_button = gr.Button("Rotate", variant="primary")
rotation_mode.change(
fn=show_custom_angle,
inputs=rotation_mode,
outputs=custom_angle,
)
rotate_button.click(
fn=rotate_image,
inputs=[input_image, rotation_mode, custom_angle],
outputs=output_image,
)
return demo
if __name__ == "__main__":
build_app().launch(server_name="0.0.0.0", server_port=7860)
|