diff --git a/backend/internal/service/provider.go b/backend/internal/service/provider.go index 5471093e1..06fda3c75 100644 --- a/backend/internal/service/provider.go +++ b/backend/internal/service/provider.go @@ -819,6 +819,17 @@ func normalizeGrokImageAspectRatio(size string) string { return "4:3" case h*3 == w*4 || (ratio > 0.7 && ratio < 0.85): return "3:4" + // 像素尺寸路径必须显式覆盖 2:3 / 3:2 / 1:2 / 2:1:冒号字符串能直达(见上方 switch), + // 但像素路径只靠 w>h 兜底会把 768x1152(2:3,ratio 0.667)错标成 9:16、 + // 1152x768(3:2,ratio 1.5)错标成 16:9,xAI 按错比例裁切生成图。 + case w*3 == h*2 || (ratio >= 0.6 && ratio < 0.72): + return "2:3" + case w*2 == h*3 || (ratio > 1.35 && ratio < 1.6): + return "3:2" + case h == w*2 || (ratio > 0.45 && ratio < 0.55): + return "1:2" + case w == h*2 || (ratio > 1.85 && ratio < 2.2): + return "2:1" case w > h: return "16:9" default: diff --git a/backend/internal/service/provider_test.go b/backend/internal/service/provider_test.go index 82086e85d..235a9fabc 100644 --- a/backend/internal/service/provider_test.go +++ b/backend/internal/service/provider_test.go @@ -252,6 +252,36 @@ func TestGrokImageRequestBodyMapsAspectRatio(t *testing.T) { } } +func TestNormalizeGrokImageAspectRatioPixelSizes(t *testing.T) { + // 像素尺寸路径必须覆盖 2:3 / 3:2 / 1:2 / 2:1:修复前 768x1152 会被 w>h 兜底错标成 9:16、 + // 1152x768 错标成 16:9,xAI 按错比例裁切生成图。 + cases := []struct { + size string + want string + }{ + {"768x1152", "2:3"}, // 1280x1920 同族:竖图 2:3 + {"1280x1920", "2:3"}, // 审查复现用例 + {"1152x768", "3:2"}, + {"1920x1280", "3:2"}, + {"540x1080", "1:2"}, + {"1080x540", "2:1"}, + {"1280x720", "16:9"}, + {"720x1280", "9:16"}, + {"800x800", "1:1"}, + } + for _, tc := range cases { + if got := normalizeGrokImageAspectRatio(tc.size); got != tc.want { + t.Errorf("normalizeGrokImageAspectRatio(%q) = %q, want %q", tc.size, got, tc.want) + } + } + // 冒号字符串路径回归:2:3 等比值字符串应原样透传。 + for _, size := range []string{"2:3", "3:2", "1:2", "2:1"} { + if got := normalizeGrokImageAspectRatio(size); got != size { + t.Errorf("normalizeGrokImageAspectRatio(%q) = %q, want passthrough %q", size, got, size) + } + } +} + func TestNormalizeGrokImageResolution(t *testing.T) { if got := normalizeGrokImageResolution("1k"); got != "1k" { t.Fatalf("1k = %q", got)