fix: stabilize detail replacement result images

This commit is contained in:
Your Name 2026-06-02 14:35:44 +08:00
parent 537a9d10c2
commit fa4b4183cf
2 changed files with 51 additions and 32 deletions

View File

@ -118,42 +118,48 @@ export async function normalizeReplacementResultImage(params: {
const generatedBuffer = await fetchImageBufferFromUrl(params.generatedImageUrl);
let targetWidth = params.referenceGeometry?.width;
let targetHeight = params.referenceGeometry?.height;
if (!targetWidth || !targetHeight) {
const referenceBuffer = await fetchImageBufferFromUrl(params.referenceImageUrl);
const referenceMetadata = await sharp(referenceBuffer, { failOn: "none" })
.rotate()
.metadata();
targetWidth = referenceMetadata.width;
targetHeight = referenceMetadata.height;
}
if (!targetWidth || !targetHeight) {
throw new Error("无法读取参考图尺寸");
}
const generatedMetadata = await sharp(generatedBuffer, { failOn: "none" })
.rotate()
.metadata();
if (generatedMetadata.width === targetWidth && generatedMetadata.height === targetHeight) {
return {
originalUrl: params.generatedImageUrl,
thumbnailUrl: params.generatedThumbnailUrl || params.generatedImageUrl,
imageSize: `${targetWidth}x${targetHeight}`,
};
if (!targetWidth || !targetHeight) {
try {
const referenceBuffer = await fetchImageBufferFromUrl(params.referenceImageUrl);
const referenceMetadata = await sharp(referenceBuffer, { failOn: "none" })
.rotate()
.metadata();
targetWidth = referenceMetadata.width;
targetHeight = referenceMetadata.height;
} catch (error) {
chatApiLogger.warn("[Chat API] Failed to read replacement reference size, hosting generated output as-is:", {
referenceImageUrl: params.referenceImageUrl,
generatedImageUrl: params.generatedImageUrl,
error: error instanceof Error ? error.message : "unknown",
});
}
}
const normalizedBuffer = await sharp(generatedBuffer, { failOn: "none" })
.rotate()
.resize(targetWidth, targetHeight, {
// Keep the model output proportional when adapting it back to the reference page.
// `fill` stretches the picture and can squash products; `cover` behaves like a screenshot crop.
fit: "cover",
position: "centre",
withoutEnlargement: false,
})
.png()
.toBuffer();
const outputWidth = targetWidth || generatedMetadata.width;
const outputHeight = targetHeight || generatedMetadata.height;
if (!outputWidth || !outputHeight) {
throw new Error("无法读取结果图尺寸");
}
const imagePipeline = sharp(generatedBuffer, { failOn: "none" }).rotate();
const normalizedBuffer =
targetWidth && targetHeight
? await imagePipeline
.resize(targetWidth, targetHeight, {
// Keep the model output proportional when adapting it back to the reference page.
// `fill` stretches the picture and can squash products; `cover` behaves like a screenshot crop.
fit: "cover",
position: "centre",
withoutEnlargement: false,
})
.png()
.toBuffer()
: await imagePipeline.png().toBuffer();
const thumbnailBuffer = await createAgentImageThumbnailBuffer(normalizedBuffer);
const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
@ -167,7 +173,7 @@ export async function normalizeReplacementResultImage(params: {
return {
originalUrl: originalUpload.url,
thumbnailUrl: thumbnailUpload.url,
imageSize: `${targetWidth}x${targetHeight}`,
imageSize: `${outputWidth}x${outputHeight}`,
};
}

View File

@ -249,6 +249,7 @@ import {
ensureStructuredAgentFriendlyMessage,
extractMessageImageAssetIds,
extractMessageImageUrls,
isRemoteImageAccessible,
injectHistoryImagesToLastUserMessage,
normalizeAssistantImageMarkdown,
normalizeResolvedTargetImageUrls,
@ -3544,6 +3545,12 @@ export async function POST(request: Request) {
? normalizeError.message
: "unknown",
});
const rawResultAccessible = await isRemoteImageAccessible(
firstImage.originalUrl
).catch(() => false);
if (!rawResultAccessible) {
throw normalizeError;
}
}
await emitReplacementResultMessage({
@ -4341,6 +4348,12 @@ export async function POST(request: Request) {
? normalizeError.message
: "unknown",
});
const rawResultAccessible = await isRemoteImageAccessible(
firstImage.originalUrl
).catch(() => false);
if (!rawResultAccessible) {
throw normalizeError;
}
}
chatApiLogger.info("[Chat API] Replacement image generation completed:", {
mode: replacementSourceType,