diff --git a/app/api/canvas/local-edit/route.ts b/app/api/canvas/local-edit/route.ts index f465bf017..bfcc61267 100644 --- a/app/api/canvas/local-edit/route.ts +++ b/app/api/canvas/local-edit/route.ts @@ -729,6 +729,7 @@ function buildScaleAdjustPrompt( `4. 放大时,目标主体应围绕原位置视觉中心自然变大到约 ${targetLabel};宽度和高度都要同步变大,不能出现“高度变高但宽度变窄”的非等比变形;主体边缘与遮挡关系要合理,不能产生突兀裁切。`, "5. 如果主体靠近画布边界导致目标尺寸空间不足,请用能完整放入画面的最大统一倍率整体缩放;绝不能为了塞进画面而只压缩宽度或只拉伸高度。", "6. 框选区域内非目标主体的背景、墙面、桌面、植物、文字和其它物体应保持原场景逻辑,不要跟着主体一起缩放。", + "6.1 比例调整后的主体边缘必须和周围环境自然融合,选区边界不能被肉眼看出;不得出现一整块矩形区域清晰度、颜色、光照、纹理或透视突然变化。", "7. 未受比例调整影响的其它画面区域必须保持原图不变,尤其是框选区域外的文字、Logo、标题、尺寸标注、装饰条和页面排版不得被清理、改写、模糊或重绘。", "8. 最终输出必须是一张完整、干净、无缝的照片,不得出现任何选区框、说明文字、对比线、比例数字或 UI 元素。", "9. 输出前自检:如果目标主体大小与原图相比没有明显变化,或者主体宽高比发生非等比变形,必须重新生成;禁止返回看起来和原图相同或被拉伸的结果。", diff --git a/lib/canvas/generate-image.ts b/lib/canvas/generate-image.ts index c4cb34638..9e26919bc 100644 --- a/lib/canvas/generate-image.ts +++ b/lib/canvas/generate-image.ts @@ -112,8 +112,8 @@ class ScaleAdjustOutputRejectedError extends Error { const LOCAL_EDIT_COMPOSITE_PADDING_RATIO = 0.14; const LOCAL_EDIT_COMPOSITE_MIN_PADDING_RATIO = 0.012; const LOCAL_EDIT_COMPOSITE_MAX_PADDING_RATIO = 0.06; -const LOCAL_EDIT_COMPOSITE_FEATHER_MIN_PX = 10; -const LOCAL_EDIT_COMPOSITE_FEATHER_MAX_PX = 44; +const LOCAL_EDIT_COMPOSITE_FEATHER_MIN_PX = 18; +const LOCAL_EDIT_COMPOSITE_FEATHER_MAX_PX = 72; const SCALE_ADJUST_VISUAL_DIFF_THRESHOLD = 14; const SCALE_ADJUST_OUTSIDE_DIFF_THRESHOLD = 18; const SCALE_ADJUST_OUTSIDE_DIFF_MIN_CHANGED_RATIO = 0.28; @@ -678,10 +678,10 @@ function buildLocalEditCompositeMaskSvg(params: { LOCAL_EDIT_COMPOSITE_FEATHER_MIN_PX, Math.min( LOCAL_EDIT_COMPOSITE_FEATHER_MAX_PX, - Math.round(Math.min(width, height) * 0.012) + Math.round(Math.min(width, height) * 0.018) ) ); - const rects = regions + const rectEntries = regions .map((region) => { const left = Math.max(0, Math.round(region.x * width)); const top = Math.max(0, Math.round(region.y * height)); @@ -693,7 +693,33 @@ function buildLocalEditCompositeMaskSvg(params: { height - top, Math.max(1, Math.round(region.height * height)) ); - return ``; + return { left, top, rectHeight, rectWidth }; + }) + .filter(({ rectHeight, rectWidth }) => rectWidth > 0 && rectHeight > 0); + const softRects = rectEntries + .map( + ({ left, top, rectHeight, rectWidth }) => + `` + ) + .join(""); + const coreRects = rectEntries + .map(({ left, top, rectHeight, rectWidth }) => { + const inset = Math.max( + 0, + Math.min( + Math.round(blur * 1.35), + Math.floor(rectWidth / 3), + Math.floor(rectHeight / 3) + ) + ); + const coreWidth = rectWidth - inset * 2; + const coreHeight = rectHeight - inset * 2; + if (coreWidth <= 0 || coreHeight <= 0) return ""; + return ``; }) .join(""); @@ -706,9 +732,9 @@ function buildLocalEditCompositeMaskSvg(params: { - ${rects} + ${softRects} - ${rects} + ${coreRects} `); }