File size: 2,395 Bytes
2472459
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import math


TARGET_OUTPUT_AREA = 1024 * 1024
ORIGINAL_ASPECT_RATIO_VALUE = "original"
DEFAULT_NEGATIVE_PROMPT = (
    "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, "
    "extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
)
ASPECT_RATIO_OPTIONS = [
    (ORIGINAL_ASPECT_RATIO_VALUE, "Original"),
    ("3:4", "3:4"),
    ("2:3", "2:3"),
    ("9:16", "9:16"),
    ("1:1", "1:1"),
    ("16:9", "16:9"),
    ("3:2", "3:2"),
    ("4:3", "4:3"),
]
ASPECT_RATIO_MAP = {
    value: float(width) / float(height)
    for value, _ in ASPECT_RATIO_OPTIONS
    if value != ORIGINAL_ASPECT_RATIO_VALUE
    for width, height in [value.split(":")]
}


def _round_down_to_multiple(value, multiple):
    return max(multiple, int(value) // multiple * multiple)


def _round_to_nearest_multiple(value, multiple):
    return max(multiple, round(float(value) / multiple) * multiple)


def resize_like_original_upload(image, max_side=1024, multiple_of=8):
    width, height = image.size
    if width > height:
        target_width = max_side
        target_height = int(target_width * height / width)
    else:
        target_height = max_side
        target_width = int(target_height * width / height)
    return (
        _round_down_to_multiple(target_width, multiple_of),
        _round_down_to_multiple(target_height, multiple_of),
    )


def calculate_dimensions_for_ratio(ratio, target_area=TARGET_OUTPUT_AREA, multiple_of=32):
    width = math.sqrt(target_area * ratio)
    height = width / ratio
    return (
        _round_to_nearest_multiple(width, multiple_of),
        _round_to_nearest_multiple(height, multiple_of),
    )


def resolve_output_dimensions(image, aspect_ratio):
    normalized_ratio = str(aspect_ratio or ORIGINAL_ASPECT_RATIO_VALUE).strip().lower()
    if normalized_ratio in ("", ORIGINAL_ASPECT_RATIO_VALUE, "raw", "原始"):
        return resize_like_original_upload(image)
    ratio = ASPECT_RATIO_MAP.get(normalized_ratio)
    if ratio is None:
        return resize_like_original_upload(image)
    return calculate_dimensions_for_ratio(ratio)


def build_negative_prompt(guidance_scale):
    try:
        normalized_scale = float(guidance_scale)
    except (TypeError, ValueError):
        normalized_scale = 1.0
    if normalized_scale <= 1.0:
        return None
    return DEFAULT_NEGATIVE_PROMPT