PicRotate / app.py
CyGuy8's picture
Sync from GitHub via hub-sync
9a5111a verified
Raw
History Blame Contribute Delete
2.31 kB
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)