someone-in-the-world Claude Sonnet 4.6 commited on
Commit
2837b03
·
1 Parent(s): 56450ae

Extract dimension calc, add pytest, fix aspect ratio rounding

Browse files

- Extract compute_output_dimensions() into dimensions.py with comment
explaining why round-to-8 is used instead of floor
- Add tests/test_dimensions.py (23 cases) covering multiples-of-8,
long-side pinning, aspect ratio error bound, and round-beats-floor
- Add pytest to requirements.txt
- app.py delegates to compute_output_dimensions()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (5) hide show
  1. app.py +2 -7
  2. dimensions.py +15 -0
  3. requirements.txt +1 -0
  4. tests/conftest.py +4 -0
  5. tests/test_dimensions.py +99 -0
app.py CHANGED
@@ -29,6 +29,7 @@ print("Using device:", device)
29
  torch.backends.cuda.matmul.allow_tf32 = True
30
  torch.backends.cudnn.allow_tf32 = True
31
 
 
32
  from diffusers import FlowMatchEulerDiscreteScheduler
33
  from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
34
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
@@ -154,13 +155,7 @@ def update_dimensions_on_upload(image):
154
  if image is None:
155
  return MAX_OUTPUT_DIM, MAX_OUTPUT_DIM
156
  w, h = image.size
157
- if w > h:
158
- nw = MAX_OUTPUT_DIM
159
- nh = int(nw * h / w)
160
- else:
161
- nh = MAX_OUTPUT_DIM
162
- nw = int(nh * w / h)
163
- return (nw // 8) * 8, (nh // 8) * 8
164
 
165
 
166
  @spaces.GPU
 
29
  torch.backends.cuda.matmul.allow_tf32 = True
30
  torch.backends.cudnn.allow_tf32 = True
31
 
32
+ from dimensions import compute_output_dimensions
33
  from diffusers import FlowMatchEulerDiscreteScheduler
34
  from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
35
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
 
155
  if image is None:
156
  return MAX_OUTPUT_DIM, MAX_OUTPUT_DIM
157
  w, h = image.size
158
+ return compute_output_dimensions(w, h)
 
 
 
 
 
 
159
 
160
 
161
  @spaces.GPU
dimensions.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MAX_OUTPUT_DIM = 2048
2
+
3
+
4
+ def compute_output_dimensions(w, h, max_dim=MAX_OUTPUT_DIM):
5
+ # Pin the long side to max_dim and scale the short side proportionally.
6
+ # We snap to the nearest multiple of 8 (not floor) to minimise aspect ratio
7
+ # distortion: floor always undershoots, whereas rounding keeps the error
8
+ # within ±4px, which halves the worst-case ratio deviation.
9
+ if w > h:
10
+ nw = max_dim
11
+ nh = round(nw * h / w / 8) * 8
12
+ else:
13
+ nh = max_dim
14
+ nw = round(nh * w / h / 8) * 8
15
+ return nw, nh
requirements.txt CHANGED
@@ -10,6 +10,7 @@ kernels
10
  spaces
11
  hf_xet
12
  gradio
 
13
  torch
14
  numpy
15
  av
 
10
  spaces
11
  hf_xet
12
  gradio
13
+ pytest
14
  torch
15
  numpy
16
  av
tests/conftest.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import sys
2
+ import os
3
+
4
+ sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
tests/test_dimensions.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+ from dimensions import compute_output_dimensions, MAX_OUTPUT_DIM
3
+
4
+
5
+ def aspect_ratio_error(w_in, h_in, w_out, h_out):
6
+ return abs(w_out / h_out - w_in / h_in)
7
+
8
+
9
+ # --- output constraints ---
10
+
11
+ @pytest.mark.parametrize("w, h", [
12
+ (1920, 1080),
13
+ (1080, 1920),
14
+ (1000, 1000),
15
+ (1000, 381),
16
+ (381, 1000),
17
+ (3840, 2160),
18
+ (1, 1),
19
+ ])
20
+ def test_output_is_multiple_of_8(w, h):
21
+ nw, nh = compute_output_dimensions(w, h)
22
+ assert nw % 8 == 0
23
+ assert nh % 8 == 0
24
+
25
+
26
+ @pytest.mark.parametrize("w, h", [
27
+ (1920, 1080),
28
+ (1000, 381),
29
+ (3840, 2160),
30
+ ])
31
+ def test_landscape_long_side_is_max_dim(w, h):
32
+ nw, nh = compute_output_dimensions(w, h)
33
+ assert nw == MAX_OUTPUT_DIM
34
+
35
+
36
+ @pytest.mark.parametrize("w, h", [
37
+ (1080, 1920),
38
+ (381, 1000),
39
+ ])
40
+ def test_portrait_long_side_is_max_dim(w, h):
41
+ nw, nh = compute_output_dimensions(w, h)
42
+ assert nh == MAX_OUTPUT_DIM
43
+
44
+
45
+ def test_square_stays_square():
46
+ nw, nh = compute_output_dimensions(1000, 1000)
47
+ assert nw == nh == MAX_OUTPUT_DIM
48
+
49
+
50
+ # --- aspect ratio preservation ---
51
+
52
+ @pytest.mark.parametrize("w, h", [
53
+ (1920, 1080),
54
+ (1080, 1920),
55
+ (1000, 381),
56
+ (381, 1000),
57
+ (3840, 2160),
58
+ ])
59
+ def test_aspect_ratio_error_within_one_step(w, h):
60
+ nw, nh = compute_output_dimensions(w, h)
61
+ # Rounding to nearest-8 introduces at most 4px error on the short side.
62
+ # Ratio error = long * delta_short / short^2, so max = long * 4 / short^2.
63
+ max_allowed = max(nw, nh) * 4 / min(nw, nh) ** 2
64
+ assert aspect_ratio_error(w, h, nw, nh) <= max_allowed
65
+
66
+
67
+ @pytest.mark.parametrize("w, h", [
68
+ (1000, 381),
69
+ (381, 1000),
70
+ ])
71
+ def test_round_beats_floor_on_tricky_ratio(w, h):
72
+ """Cases where floor-to-8 and round-to-8 disagree: round must be at least as accurate."""
73
+ nw, nh = compute_output_dimensions(w, h)
74
+ # Reproduce floor-to-8 result for comparison
75
+ if w > h:
76
+ nh_floor = (int(MAX_OUTPUT_DIM * h / w) // 8) * 8
77
+ nw_floor = MAX_OUTPUT_DIM
78
+ else:
79
+ nw_floor = (int(MAX_OUTPUT_DIM * w / h) // 8) * 8
80
+ nh_floor = MAX_OUTPUT_DIM
81
+ assert aspect_ratio_error(w, h, nw, nh) <= aspect_ratio_error(w, h, nw_floor, nh_floor)
82
+
83
+
84
+ # --- exact known values ---
85
+
86
+ def test_16_9_landscape():
87
+ nw, nh = compute_output_dimensions(1920, 1080)
88
+ assert (nw, nh) == (2048, 1152)
89
+
90
+
91
+ def test_16_9_portrait():
92
+ nw, nh = compute_output_dimensions(1080, 1920)
93
+ assert (nw, nh) == (1152, 2048)
94
+
95
+
96
+ def test_custom_max_dim():
97
+ nw, nh = compute_output_dimensions(1920, 1080, max_dim=1024)
98
+ assert nw == 1024
99
+ assert nh % 8 == 0