diff --git a/server-rs/crates/api-server/src/editor_project.rs b/server-rs/crates/api-server/src/editor_project.rs index 553104c6d..39ec8a3c4 100644 --- a/server-rs/crates/api-server/src/editor_project.rs +++ b/server-rs/crates/api-server/src/editor_project.rs @@ -129,8 +129,6 @@ const EDITOR_BGFILTER_DEFAULT_SEG_MODEL: &str = "birefnet"; const EDITOR_BGFILTER_SEG_MODEL_ANIME_SEG: &str = "anime-seg"; const EDITOR_PUBLICATION_MATERIAL_ASSET_KIND: &str = "editor_publication_material"; const EDITOR_LEGACY_INLINE_IMAGE_ASSET_KIND: &str = "editor_legacy_inline_image"; -const GPT_IMAGE_2_MIN_PIXELS: u64 = 655_360; -const GPT_IMAGE_2_MAX_PIXELS: u64 = 8_294_400; static EDITOR_BGFILTER_CIRCUIT: OnceLock> = OnceLock::new(); @@ -1852,16 +1850,14 @@ fn editor_image_price_size_from_pixels(size: &str) -> &'static str { if width.max(height) > 1536 { "2K" } else { "1K" } } -fn normalize_editor_image_generation_size(model: &str, size: Option<&str>) -> Cow<'static, str> { +fn normalize_editor_image_generation_size(size: Option<&str>) -> Cow<'static, str> { match size.map(str::trim).filter(|value| !value.is_empty()) { Some("1024x1024") | Some("1024*1024") | Some("1:1") => Cow::Borrowed("1024x1024"), Some("1536x1024") | Some("1536*1024") | Some("16:9") => Cow::Borrowed("1536x1024"), Some("2048x1152") | Some("2048*1152") | Some("1920x1080") | Some("1920*1080") | Some("2k-16:9") => Cow::Borrowed("2048x1152"), Some("1024x1536") | Some("1024*1536") | Some("9:16") => Cow::Borrowed("1024x1536"), - Some(value) if is_editor_custom_image_size(value) => { - clamp_custom_size_to_model_budget(model, value) - } + Some(value) if is_editor_custom_image_size(value) => Cow::Owned(value.to_string()), _ => Cow::Borrowed(EDITOR_IMAGE_GENERATION_SIZE), } } @@ -1872,7 +1868,7 @@ fn resolve_editor_image_request_size( has_dimension_options: bool, generation_options: &EditorGenerationOptions, ) -> Cow<'static, str> { - let legacy_size = normalize_editor_image_generation_size(generation_options.model, payload_size); + let legacy_size = normalize_editor_image_generation_size(payload_size); let has_explicit_payload_size = payload_size .map(str::trim) .is_some_and(|value| !value.is_empty()); @@ -1896,37 +1892,6 @@ fn is_editor_custom_image_size(value: &str) -> bool { return false; }; (64..=4096).contains(&width) && (64..=4096).contains(&height) - -} - -fn clamp_custom_size_to_model_budget(model: &str, value: &str) -> Cow<'static, str> { - if model != GPT_IMAGE_2_MODEL { - return Cow::Owned(value.to_string()); - } - let Some((width_str, height_str)) = value.split_once('x') else { - return Cow::Owned(value.to_string()); - }; - let Ok(width) = width_str.parse::() else { - return Cow::Owned(value.to_string()); - }; - let Ok(height) = height_str.parse::() else { - return Cow::Owned(value.to_string()); - }; - let pixels = u64::from(width) * u64::from(height); - - if pixels < GPT_IMAGE_2_MIN_PIXELS { - let ratio = (GPT_IMAGE_2_MIN_PIXELS as f64 / pixels as f64).sqrt(); - let new_w = (width as f64 * ratio).ceil() as u32; - let new_h = (height as f64 * ratio).ceil() as u32; - Cow::Owned(format!("{}x{}", new_w, new_h)) - } else if pixels > GPT_IMAGE_2_MAX_PIXELS { - let ratio = (GPT_IMAGE_2_MAX_PIXELS as f64 / pixels as f64).sqrt(); - let new_w = (width as f64 * ratio).floor() as u32; - let new_h = (height as f64 * ratio).floor() as u32; - Cow::Owned(format!("{}x{}", new_w, new_h)) - } else { - Cow::Owned(value.to_string()) - } } fn normalize_editor_generation_options( @@ -2267,7 +2232,7 @@ pub async fn edit_editor_image( .await?; let generation_options = normalize_editor_generation_options(payload.model.as_deref(), None, None); - let image_size = normalize_editor_image_generation_size(generation_options.model, payload.size.as_deref()); + let image_size = normalize_editor_image_generation_size(payload.size.as_deref()); let price_mud_points = u64::from( resolve_editor_image_edit_price(&state, generation_options.model, image_size.as_ref()) .await?, @@ -2313,7 +2278,7 @@ pub(crate) async fn edit_editor_image_for_owner( } let generation_options = normalize_editor_generation_options(payload.model.as_deref(), None, None); - let requested_image_size = normalize_editor_image_generation_size(generation_options.model, payload.size.as_deref()); + let requested_image_size = normalize_editor_image_generation_size(payload.size.as_deref()); let mut reference_images = Vec::with_capacity(1 + payload.reference_image_srcs.as_ref().map_or(0, Vec::len)); reference_images.push( @@ -7432,29 +7397,25 @@ mod tests { #[test] fn editor_image_generation_size_keeps_quick_edit_canvas_ratio_presets() { + assert_eq!(normalize_editor_image_generation_size(None), "1024x1024"); assert_eq!( - normalize_editor_image_generation_size(GPT_IMAGE_2_MODEL, None), - "1024x1024" - ); - assert_eq!( - normalize_editor_image_generation_size(GPT_IMAGE_2_MODEL, Some("1536x1024")), + normalize_editor_image_generation_size(Some("1536x1024")), "1536x1024" ); assert_eq!( - normalize_editor_image_generation_size(GPT_IMAGE_2_MODEL, Some("1024x1536")), + normalize_editor_image_generation_size(Some("1024x1536")), "1024x1536" ); assert_eq!( - normalize_editor_image_generation_size(GPT_IMAGE_2_MODEL, Some("2048x1152")), + normalize_editor_image_generation_size(Some("2048x1152")), "2048x1152" ); - // 640x640 has 409600 pixels, below gpt-image-2 minimum (655360), so clamp scales up. assert_eq!( - normalize_editor_image_generation_size(GPT_IMAGE_2_MODEL, Some("640x640")), - "810x810" + normalize_editor_image_generation_size(Some("640x640")), + "640x640" ); assert_eq!( - normalize_editor_image_generation_size(GPT_IMAGE_2_MODEL, Some("bad-size")), + normalize_editor_image_generation_size(Some("bad-size")), "1024x1024" ); } @@ -7618,8 +7579,6 @@ mod tests { let options = normalize_editor_generation_options(Some("gpt-image-2"), Some("4:3"), Some("1K")); - // 720x540 = 388800 pixels, below gpt-image-2 minimum (655360), clamp scales up to 935x702. - // This preserves the publication-material routing (legacy size wins) but with budget enforcement. assert_eq!( resolve_editor_image_request_size( Some("publication-material"), @@ -7627,9 +7586,8 @@ mod tests { true, &options, ), - "935x702" + "720x540" ); - // Non-publication-material path still falls through to structured options size. assert_eq!( resolve_editor_image_request_size(Some("generate"), Some("720x540"), true, &options), "1536x1024"