From 40ce24feb8c786fac96244d6c9e79a0e836d058f Mon Sep 17 00:00:00 2001 From: 134 Date: Tue, 7 Jul 2026 19:44:10 +0800 Subject: [PATCH] fix: avoid broad mask in product lock scale adjust --- app/api/canvas/local-edit/route.ts | 153 +++-------------------------- 1 file changed, 15 insertions(+), 138 deletions(-) diff --git a/app/api/canvas/local-edit/route.ts b/app/api/canvas/local-edit/route.ts index 749243a38..d7e12b77a 100644 --- a/app/api/canvas/local-edit/route.ts +++ b/app/api/canvas/local-edit/route.ts @@ -2297,15 +2297,11 @@ async function buildScaleAdjustOpaqueEditMaskFromOpacityMask(params: { async function buildScaleAdjustProductLockBackgroundRepairMaskBuffer(params: { productSourceMaskBuffer: Buffer; - regions: NormalizedLocalEditRegion[]; - scalePercent?: ScaleAdjustPercent | null; sourceHeight: number; sourceWidth: number; }) { const { productSourceMaskBuffer, - regions, - scalePercent, sourceHeight, sourceWidth, } = params; @@ -2318,141 +2314,16 @@ async function buildScaleAdjustProductLockBackgroundRepairMaskBuffer(params: { .raw() .toBuffer(); const minSide = Math.max(1, Math.min(sourceWidth, sourceHeight)); - const blur = Math.max(8, Math.min(34, Math.round(minSide * 0.018))); - const repairRects: string[] = []; - const protectRects: string[] = []; - - for (const region of regions) { - const targetRect = getScaleAdjustTargetRect(region, scalePercent); - const unionBox = rectToPixels( - getRectUnion(region.rect, targetRect), - sourceWidth, - sourceHeight - ); - const sourceBox = region.pixelRect; - const protectedPersonSide = getScaleAdjustProtectedPersonSide(region.prompt); - const leftPad = Math.max(10, Math.round(sourceBox.width * 0.09)); - const rightPad = - protectedPersonSide === "right" - ? Math.max(6, Math.round(sourceBox.width * 0.025)) - : Math.max(10, Math.round(sourceBox.width * 0.09)); - const topPad = Math.max(10, Math.round(sourceBox.height * 0.055)); - const bottomPad = Math.max(10, Math.round(sourceBox.height * 0.035)); - const repairLeft = clamp( - Math.min(unionBox.left, sourceBox.left) - leftPad, - 0, - Math.max(0, sourceWidth - 1) - ); - const repairTop = clamp( - Math.min(unionBox.top, sourceBox.top) - topPad, - 0, - Math.max(0, sourceHeight - 1) - ); - const repairRight = clamp( - Math.max(unionBox.left + unionBox.width, sourceBox.left + sourceBox.width) + - rightPad, - repairLeft + 1, - sourceWidth - ); - const repairBottom = clamp( - Math.max( - unionBox.top + unionBox.height, - sourceBox.top + sourceBox.height - ) + bottomPad, - repairTop + 1, - sourceHeight - ); - repairRects.push( - `` - ); - - const workspaceBox = rectToPixels( - getScaleAdjustPatchWorkspaceRect([region], scalePercent), - sourceWidth, - sourceHeight - ); - const panelBottom = clamp( - sourceBox.top + Math.round(sourceBox.height * 0.38), - repairTop + 1, - sourceHeight - ); - repairRects.push( - `` - ); - - if (protectedPersonSide === "right") { - const protectLeft = clamp( - sourceBox.left + Math.round(sourceBox.width * 0.73), - 0, - Math.max(0, sourceWidth - 1) - ); - const protectTop = clamp( - sourceBox.top + Math.round(sourceBox.height * 0.26), - 0, - Math.max(0, sourceHeight - 1) - ); - protectRects.push( - `` - ); - } else if (protectedPersonSide === "left") { - const protectRight = clamp( - sourceBox.left + Math.round(sourceBox.width * 0.27), - 1, - sourceWidth - ); - const protectTop = clamp( - sourceBox.top + Math.round(sourceBox.height * 0.26), - 0, - Math.max(0, sourceHeight - 1) - ); - protectRects.push( - `` - ); - } - } - - const repairSvg = Buffer.from( - ` - - - - - - - - - - ${repairRects.join("\n")} - ${protectRects.join("\n")} - ` - ); - const repairAlpha = await sharp(repairSvg, { failOn: "none" }) - .resize(sourceWidth, sourceHeight, { fit: "fill" }) - .greyscale() + const repairAlpha = await sharp(productAlpha, { + raw: { channels: 1, height: sourceHeight, width: sourceWidth }, + }) + .blur(Math.max(1.4, Math.min(10, Math.round(minSide * 0.0045)))) .raw() .toBuffer(); const rgba = Buffer.alloc(sourceWidth * sourceHeight * 4); for (let index = 0; index < sourceWidth * sourceHeight; index += 1) { const offset = index * 4; - const value = Math.max(repairAlpha[index] || 0, productAlpha[index] || 0); + const value = Math.max(productAlpha[index] || 0, repairAlpha[index] || 0); rgba[offset] = 255; rgba[offset + 1] = 255; rgba[offset + 2] = 255; @@ -3920,12 +3791,18 @@ async function buildScaleAdjustVisualLayoutGuideBuffer(params: { width: sourceWidth, }) : null; + const sourceOnlyRepairMaskBuffer = compositeClipComposites.length + ? await buildScaleAdjustCompositeClipMaskBuffer({ + height: sourceHeight, + sourceMaskComposites: compositeClipComposites, + targetMaskComposites: [], + width: sourceWidth, + }) + : null; const productLockBackgroundRepairMaskBuffer = - productLockComposites.length && compositeClipMaskBuffer + productLockComposites.length && sourceOnlyRepairMaskBuffer ? await buildScaleAdjustProductLockBackgroundRepairMaskBuffer({ - productSourceMaskBuffer: compositeClipMaskBuffer, - regions, - scalePercent, + productSourceMaskBuffer: sourceOnlyRepairMaskBuffer, sourceHeight, sourceWidth, })