Skip to content

Commit bcd983d

Browse files
committed
Fix order-dependent preset matching
1 parent 6c11b31 commit bcd983d

2 files changed

Lines changed: 60 additions & 13 deletions

File tree

core/auto_detect.py

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
log = create_module_logger(__name__)
88

99

10+
ASPECT_RATIO_TOLERANCE = 0.01
11+
12+
1013
def safe_int(value, default=0):
1114
try:
1215
return int(value)
@@ -62,9 +65,7 @@ def find_closest_preset(width, height, presets):
6265

6366
input_aspect = width / height
6467
input_pixels = width * height
65-
closest = None
66-
closest_aspect_diff = math.inf
67-
closest_pixel_diff = math.inf
68+
candidates = []
6869

6970
for preset_name, preset in presets.items():
7071
preset_width = safe_int(preset.get("width") if isinstance(preset, dict) else None)
@@ -76,16 +77,30 @@ def find_closest_preset(width, height, presets):
7677
preset_aspect = orientation_width / orientation_height
7778
preset_pixels = orientation_width * orientation_height
7879
aspect_diff = abs(input_aspect - preset_aspect)
79-
if aspect_diff < closest_aspect_diff + 0.01:
80-
pixel_diff = abs(math.log(input_pixels / preset_pixels))
81-
if aspect_diff < closest_aspect_diff or (
82-
abs(aspect_diff - closest_aspect_diff) < 0.01 and pixel_diff < closest_pixel_diff
83-
):
84-
closest_aspect_diff = aspect_diff
85-
closest_pixel_diff = pixel_diff
86-
closest = {"name": preset_name, "width": orientation_width, "height": orientation_height}
87-
88-
return closest
80+
candidates.append(
81+
{
82+
"name": preset_name,
83+
"width": orientation_width,
84+
"height": orientation_height,
85+
"aspect_diff": aspect_diff,
86+
"pixel_diff": abs(math.log(input_pixels / preset_pixels)),
87+
}
88+
)
89+
90+
if not candidates:
91+
return None
92+
93+
minimum_aspect_diff = min(candidate["aspect_diff"] for candidate in candidates)
94+
aspect_matched_candidates = (
95+
candidate
96+
for candidate in candidates
97+
if candidate["aspect_diff"] <= minimum_aspect_diff + ASPECT_RATIO_TOLERANCE
98+
)
99+
closest = min(
100+
aspect_matched_candidates,
101+
key=lambda candidate: (candidate["pixel_diff"], candidate["aspect_diff"]),
102+
)
103+
return {"name": closest["name"], "width": closest["width"], "height": closest["height"]}
89104

90105

91106
def apply_flux_like_calculation(width, height, max_mp, max_dim, min_dim, multiple):

tests/test_auto_detect.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import unittest
2+
3+
from core.auto_detect import find_closest_preset
4+
5+
6+
class FindClosestPresetTests(unittest.TestCase):
7+
def test_equal_aspect_ratio_uses_pixel_count_tiebreaker(self):
8+
presets = {
9+
"small": {"width": 1200, "height": 800},
10+
"large": {"width": 1500, "height": 1000},
11+
}
12+
13+
closest = find_closest_preset(1600, 1000, presets)
14+
15+
self.assertEqual(closest, {"name": "large", "width": 1500, "height": 1000})
16+
17+
def test_selection_is_independent_of_preset_order(self):
18+
presets = {
19+
"A": {"width": 402, "height": 400},
20+
"B": {"width": 759, "height": 750},
21+
"C": {"width": 1021, "height": 1000},
22+
}
23+
24+
forward = find_closest_preset(1000, 1000, presets)
25+
reversed_order = find_closest_preset(1000, 1000, dict(reversed(list(presets.items()))))
26+
27+
self.assertEqual(forward, reversed_order)
28+
self.assertEqual(forward["name"], "B")
29+
30+
31+
if __name__ == "__main__":
32+
unittest.main()

0 commit comments

Comments
 (0)