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)