fix: avoid broad mask in product lock scale adjust
This commit is contained in:
parent
a201ebb346
commit
40ce24feb8
@ -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(
|
||||
`<rect x="${repairLeft}" y="${repairTop}" width="${Math.max(
|
||||
1,
|
||||
repairRight - repairLeft
|
||||
)}" height="${Math.max(1, repairBottom - repairTop)}" rx="${Math.max(
|
||||
8,
|
||||
Math.round(blur * 0.9)
|
||||
)}" ry="${Math.max(8, Math.round(blur * 0.9))}" fill="#ffffff" filter="url(#soft-repair)" />`
|
||||
);
|
||||
|
||||
const workspaceBox = rectToPixels(
|
||||
getScaleAdjustPatchWorkspaceRect([region], scalePercent),
|
||||
sourceWidth,
|
||||
sourceHeight
|
||||
);
|
||||
const panelBottom = clamp(
|
||||
sourceBox.top + Math.round(sourceBox.height * 0.38),
|
||||
repairTop + 1,
|
||||
sourceHeight
|
||||
);
|
||||
repairRects.push(
|
||||
`<rect x="${workspaceBox.left}" y="${repairTop}" width="${Math.max(
|
||||
1,
|
||||
workspaceBox.width
|
||||
)}" height="${Math.max(1, panelBottom - repairTop)}" rx="${Math.max(
|
||||
8,
|
||||
Math.round(blur * 0.9)
|
||||
)}" ry="${Math.max(8, Math.round(blur * 0.9))}" fill="#ffffff" filter="url(#soft-repair)" />`
|
||||
);
|
||||
|
||||
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(
|
||||
`<rect x="${protectLeft}" y="${protectTop}" width="${Math.max(
|
||||
1,
|
||||
sourceWidth - protectLeft
|
||||
)}" height="${Math.max(1, sourceHeight - protectTop)}" fill="#000000" filter="url(#soft-protect)" />`
|
||||
);
|
||||
} 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(
|
||||
`<rect x="0" y="${protectTop}" width="${protectRight}" height="${Math.max(
|
||||
1,
|
||||
sourceHeight - protectTop
|
||||
)}" fill="#000000" filter="url(#soft-protect)" />`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const repairSvg = Buffer.from(
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" width="${sourceWidth}" height="${sourceHeight}" viewBox="0 0 ${sourceWidth} ${sourceHeight}">
|
||||
<defs>
|
||||
<filter id="soft-repair" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur stdDeviation="${blur}" />
|
||||
</filter>
|
||||
<filter id="soft-protect" x="-8%" y="-8%" width="116%" height="116%">
|
||||
<feGaussianBlur stdDeviation="${Math.max(4, Math.round(blur * 0.55))}" />
|
||||
</filter>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="${sourceWidth}" height="${sourceHeight}" fill="#000000" />
|
||||
${repairRects.join("\n")}
|
||||
${protectRects.join("\n")}
|
||||
</svg>`
|
||||
);
|
||||
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,
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user