恢复旧图片链路字节类型
撤回非 raw_edit 的全局 Bytes 迁移 保留既有 VectorEngine 与编辑器路径的 Vec 字节契约
This commit is contained in:
@@ -19,7 +19,7 @@ use module_assets::{
|
||||
AssetObjectAccessPolicy, AssetObjectFieldError, AssetObjectUpsertInput,
|
||||
build_asset_object_upsert_input, generate_asset_object_id,
|
||||
};
|
||||
use platform_image::{DownloadedImage, GPT_IMAGE_2_2K_LONG_EDGE_THRESHOLD};
|
||||
use platform_image::DownloadedImage;
|
||||
use platform_oss::{
|
||||
LegacyAssetPrefix, OssHeadObjectRequest, OssObjectAccess, OssSignedGetObjectUrlRequest,
|
||||
};
|
||||
@@ -3841,11 +3841,7 @@ fn editor_image_price_size_from_pixels(size: &str) -> &'static str {
|
||||
let Ok(height) = height.parse::<u32>() else {
|
||||
return "1K";
|
||||
};
|
||||
if width.max(height) > GPT_IMAGE_2_2K_LONG_EDGE_THRESHOLD {
|
||||
"2K"
|
||||
} else {
|
||||
"1K"
|
||||
}
|
||||
if width.max(height) > 1536 { "2K" } else { "1K" }
|
||||
}
|
||||
|
||||
fn editor_image_edit_uses_nanobanana_generate_content(model: &str) -> bool {
|
||||
@@ -3894,11 +3890,7 @@ fn infer_editor_image_edit_size_tier(model: &str, size: Option<&str>) -> Option<
|
||||
if model == EDITOR_IMAGE_MODEL_NANOBANANA2 && long_edge <= 768 {
|
||||
return Some("0.5K");
|
||||
}
|
||||
Some(if long_edge > GPT_IMAGE_2_2K_LONG_EDGE_THRESHOLD {
|
||||
"2K"
|
||||
} else {
|
||||
"1K"
|
||||
})
|
||||
Some(if long_edge > 1536 { "2K" } else { "1K" })
|
||||
}
|
||||
|
||||
fn parse_editor_image_edit_pixel_size(size: &str) -> Option<(u32, u32)> {
|
||||
@@ -4646,7 +4638,7 @@ fn prepare_editor_image_edit_references(
|
||||
);
|
||||
}
|
||||
for (index, reference) in reference_images.iter_mut().enumerate() {
|
||||
let decoded = image::load_from_memory(reference.bytes.as_ref()).map_err(|error| {
|
||||
let decoded = image::load_from_memory(reference.bytes.as_slice()).map_err(|error| {
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
|
||||
"provider": "editor-image-edit",
|
||||
"message": format!("图片改造参考图不是有效图片:{error}"),
|
||||
@@ -4677,8 +4669,7 @@ fn prepare_editor_image_edit_references(
|
||||
image::DynamicImage::ImageRgba8(aligned),
|
||||
StatusCode::BAD_REQUEST,
|
||||
"图片改造参考图 16 对齐失败",
|
||||
)?
|
||||
.into();
|
||||
)?;
|
||||
reference.mime_type = "image/png".to_string();
|
||||
reference.file_name = format!("editor-image-edit-reference-{}.png", index + 1);
|
||||
}
|
||||
@@ -13522,7 +13513,7 @@ pub(crate) async fn read_editor_reference_image_object_with_client(
|
||||
.to_string();
|
||||
let extension = editor_reference_image_extension(mime_type.as_str());
|
||||
Ok(OpenAiReferenceImage {
|
||||
bytes: bytes.into(),
|
||||
bytes,
|
||||
mime_type,
|
||||
file_name: format!("editor-reference.{extension}"),
|
||||
})
|
||||
@@ -13536,7 +13527,7 @@ async fn download_editor_persisted_image_object(
|
||||
Ok(DownloadedOpenAiImage {
|
||||
extension: editor_reference_image_extension(image.mime_type.as_str()).to_string(),
|
||||
mime_type: image.mime_type,
|
||||
bytes: image.bytes.to_vec(),
|
||||
bytes: image.bytes,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19064,7 +19055,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn icon_spritesheet_expired_deadline_skips_blocking_image_work() {
|
||||
let source = DownloadedImage {
|
||||
bytes: bytes::Bytes::from_static(b"not-an-image"),
|
||||
bytes: b"not-an-image".to_vec(),
|
||||
mime_type: "image/png".to_string(),
|
||||
extension: "png".to_string(),
|
||||
};
|
||||
|
||||
@@ -1107,7 +1107,7 @@ mod tests {
|
||||
|
||||
fn reference_image(index: usize) -> ReferenceImage {
|
||||
ReferenceImage {
|
||||
bytes: bytes::Bytes::from(vec![index as u8]),
|
||||
bytes: vec![index as u8],
|
||||
mime_type: "image/png".to_string(),
|
||||
file_name: format!("reference-{index}.png"),
|
||||
}
|
||||
|
||||
@@ -5,10 +5,3 @@ pub const VECTOR_ENGINE_GPT_IMAGE_2_MODEL: &str = GPT_IMAGE_2_MODEL;
|
||||
pub const VECTOR_ENGINE_PROVIDER: &str = "vector-engine";
|
||||
pub const VECTOR_ENGINE_IMAGE_EDIT_MAX_REFERENCE_IMAGES: usize = 5;
|
||||
pub const VECTOR_ENGINE_NANOBANANA_MAX_REFERENCE_IMAGES: usize = 14;
|
||||
/// GPT-Image-2 pricing uses 1K through this inclusive long-edge threshold.
|
||||
pub const GPT_IMAGE_2_2K_LONG_EDGE_THRESHOLD: u32 = 1536;
|
||||
|
||||
pub(crate) const GPT_IMAGE_2_MIN_PIXELS: u64 = 655_360;
|
||||
pub(crate) const GPT_IMAGE_2_MAX_PIXELS: u64 = 8_294_400;
|
||||
pub(crate) const GPT_IMAGE_2_MAX_EDGE: u32 = 3_840;
|
||||
pub(crate) const GPT_IMAGE_2_DIMENSION_ALIGNMENT: u32 = 16;
|
||||
|
||||
@@ -257,7 +257,7 @@ fn send_multipart_edit_request_with_curl_blocking(
|
||||
form.part("image")
|
||||
.buffer(
|
||||
reference_image.file_name.as_str(),
|
||||
reference_image.bytes.to_vec(),
|
||||
reference_image.bytes.clone(),
|
||||
)
|
||||
.content_type(reference_image.mime_type.as_str())
|
||||
.add()?;
|
||||
@@ -338,7 +338,7 @@ mod tests {
|
||||
"1024x1024",
|
||||
1,
|
||||
&[ReferenceImage {
|
||||
bytes: bytes::Bytes::from_static(b"reference"),
|
||||
bytes: b"reference".to_vec(),
|
||||
mime_type: "image/png".to_string(),
|
||||
file_name: "reference.png".to_string(),
|
||||
}],
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STANDARD};
|
||||
use bytes::Bytes;
|
||||
use reqwest::header;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -52,7 +51,7 @@ pub async fn download_remote_image(
|
||||
Ok(DownloadedImage {
|
||||
extension: mime_to_extension(normalized_mime_type.as_str()).to_string(),
|
||||
mime_type: normalized_mime_type,
|
||||
bytes: body,
|
||||
bytes: body.to_vec(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -214,7 +213,7 @@ pub(crate) fn parse_reference_image_data_url(
|
||||
})?;
|
||||
let mime_type = normalize_downloaded_image_mime_type(mime_type);
|
||||
Ok(Some(ReferenceImage {
|
||||
bytes: Bytes::from(bytes),
|
||||
bytes,
|
||||
file_name: format!(
|
||||
"reference-{index}.{}",
|
||||
mime_to_extension(mime_type.as_str())
|
||||
@@ -248,7 +247,7 @@ pub(crate) fn decode_generated_image_base64(raw: &str) -> Option<DownloadedImage
|
||||
Some(DownloadedImage {
|
||||
extension: mime_to_extension(mime_type.as_str()).to_string(),
|
||||
mime_type,
|
||||
bytes: bytes.into(),
|
||||
bytes,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use serde_json::{Map, Value, json};
|
||||
|
||||
use super::{
|
||||
constants::{
|
||||
GPT_IMAGE_2_C_MODEL, GPT_IMAGE_2_DIMENSION_ALIGNMENT, GPT_IMAGE_2_MAX_EDGE,
|
||||
GPT_IMAGE_2_MAX_PIXELS, GPT_IMAGE_2_MIN_PIXELS, GPT_IMAGE_2_MODEL,
|
||||
},
|
||||
constants::{GPT_IMAGE_2_C_MODEL, GPT_IMAGE_2_MODEL},
|
||||
types::{ReferenceImage, VectorEngineImageSettings},
|
||||
};
|
||||
|
||||
@@ -65,7 +62,7 @@ pub fn build_vector_engine_nanobanana_generate_content_request_body(
|
||||
"mime_type": reference_image.mime_type,
|
||||
"data": base64::Engine::encode(
|
||||
&base64::engine::general_purpose::STANDARD,
|
||||
reference_image.bytes.as_ref()
|
||||
reference_image.bytes.as_slice()
|
||||
),
|
||||
},
|
||||
}));
|
||||
@@ -132,10 +129,10 @@ fn normalize_explicit_pixel_size(value: &str) -> String {
|
||||
}
|
||||
|
||||
fn clamp_gpt_image_2_pixel_size(size: &str) -> String {
|
||||
const MIN_PIXELS: u64 = GPT_IMAGE_2_MIN_PIXELS;
|
||||
const MAX_PIXELS: u64 = GPT_IMAGE_2_MAX_PIXELS;
|
||||
const MAX_EDGE: u32 = GPT_IMAGE_2_MAX_EDGE;
|
||||
const DIMENSION_ALIGNMENT: u32 = GPT_IMAGE_2_DIMENSION_ALIGNMENT;
|
||||
const MIN_PIXELS: u64 = 655_360;
|
||||
const MAX_PIXELS: u64 = 8_294_400;
|
||||
const MAX_EDGE: u32 = 3_840;
|
||||
const DIMENSION_ALIGNMENT: u32 = 16;
|
||||
const MAX_ASPECT_RATIO: f64 = 3.0;
|
||||
|
||||
// 中文注释:这里是 VectorEngine 的共享发送边界,只处理 gpt-image-2 的显式像素尺寸。
|
||||
@@ -346,12 +343,12 @@ mod tests {
|
||||
9,
|
||||
&[
|
||||
ReferenceImage {
|
||||
bytes: bytes::Bytes::from_static(&[1, 2, 3, 4, 5]),
|
||||
bytes: vec![1, 2, 3, 4, 5],
|
||||
mime_type: "image/png".to_string(),
|
||||
file_name: "reference-a.png".to_string(),
|
||||
},
|
||||
ReferenceImage {
|
||||
bytes: bytes::Bytes::from(vec![8; 7]),
|
||||
bytes: vec![8; 7],
|
||||
mime_type: "image/jpeg".to_string(),
|
||||
file_name: "reference-b.jpg".to_string(),
|
||||
},
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use super::audit::PlatformImageFailureAudit;
|
||||
use bytes::Bytes;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VectorEngineImageSettings {
|
||||
@@ -17,23 +16,16 @@ pub struct GeneratedImages {
|
||||
pub recovered_failure_audits: Vec<PlatformImageFailureAudit>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RawImageEditResult {
|
||||
pub b64_images: Vec<String>,
|
||||
pub recovered_failure_audits: Vec<PlatformImageFailureAudit>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DownloadedImage {
|
||||
/// Shared immutable image bytes so callers can pass downloaded buffers downstream without copying.
|
||||
pub bytes: Bytes,
|
||||
pub bytes: Vec<u8>,
|
||||
pub mime_type: String,
|
||||
pub extension: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ReferenceImage {
|
||||
pub bytes: Bytes,
|
||||
pub bytes: Vec<u8>,
|
||||
pub mime_type: String,
|
||||
pub file_name: String,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user