Fix canvas scale adjust local edit build
This commit is contained in:
parent
accaaad8f1
commit
c9ed662809
@ -199,6 +199,32 @@ function inferClosestAspectRatio(width: number, height: number) {
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function inferScaleAdjustPatchAspectRatio(width: number, height: number) {
|
||||||
|
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
||||||
|
return "1:1";
|
||||||
|
}
|
||||||
|
const sourceRatio = width / height;
|
||||||
|
const providerSafeRatios = [
|
||||||
|
"1:1",
|
||||||
|
"2:3",
|
||||||
|
"3:2",
|
||||||
|
"3:4",
|
||||||
|
"4:3",
|
||||||
|
"9:16",
|
||||||
|
"16:9",
|
||||||
|
] as const;
|
||||||
|
let closest: (typeof providerSafeRatios)[number] = "1:1";
|
||||||
|
let closestDiff = Number.POSITIVE_INFINITY;
|
||||||
|
for (const candidate of providerSafeRatios) {
|
||||||
|
const diff = Math.abs(parseAspectRatioValue(candidate) - sourceRatio);
|
||||||
|
if (diff < closestDiff) {
|
||||||
|
closest = candidate;
|
||||||
|
closestDiff = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
function resolveLocalEditAspectRatio(input: unknown, sourceWidth: number, sourceHeight: number) {
|
function resolveLocalEditAspectRatio(input: unknown, sourceWidth: number, sourceHeight: number) {
|
||||||
const requested = String(input || "").trim();
|
const requested = String(input || "").trim();
|
||||||
if (
|
if (
|
||||||
@ -339,7 +365,26 @@ function isScaleAdjustFalNanoBananaEditModel(
|
|||||||
const label = `${entry.model.displayName || ""} ${entry.model.modelId || ""}`
|
const label = `${entry.model.displayName || ""} ${entry.model.modelId || ""}`
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replace(/\s+/g, " ");
|
.replace(/\s+/g, " ");
|
||||||
return label.includes("/edit") || /\bedit\b/.test(label);
|
const capabilities =
|
||||||
|
entry.model.capabilities && typeof entry.model.capabilities === "object"
|
||||||
|
? (entry.model.capabilities as Record<string, unknown>)
|
||||||
|
: {};
|
||||||
|
const defaultParams =
|
||||||
|
entry.model.defaultParams && typeof entry.model.defaultParams === "object"
|
||||||
|
? (entry.model.defaultParams as Record<string, unknown>)
|
||||||
|
: {};
|
||||||
|
const editEndpoint =
|
||||||
|
typeof capabilities.editEndpoint === "string"
|
||||||
|
? capabilities.editEndpoint
|
||||||
|
: typeof defaultParams.editEndpoint === "string"
|
||||||
|
? defaultParams.editEndpoint
|
||||||
|
: "";
|
||||||
|
return (
|
||||||
|
label.includes("/edit") ||
|
||||||
|
/\bedit\b/.test(label) ||
|
||||||
|
capabilities.autoRouteEditEndpoint === true ||
|
||||||
|
editEndpoint.toLowerCase().includes("/edit")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isScaleAdjustHealthyModel(
|
function isScaleAdjustHealthyModel(
|
||||||
@ -761,6 +806,51 @@ function expandRectWithMargins(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function expandRectToProviderAspectLimit(
|
||||||
|
rect: NormalizedLocalEditRegion["rect"],
|
||||||
|
sourceWidth: number,
|
||||||
|
sourceHeight: number,
|
||||||
|
maxAspectRatio = 3
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!Number.isFinite(sourceWidth) ||
|
||||||
|
!Number.isFinite(sourceHeight) ||
|
||||||
|
sourceWidth <= 0 ||
|
||||||
|
sourceHeight <= 0 ||
|
||||||
|
maxAspectRatio <= 1
|
||||||
|
) {
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pixelWidth = rect.width * sourceWidth;
|
||||||
|
const pixelHeight = rect.height * sourceHeight;
|
||||||
|
if (pixelWidth <= 0 || pixelHeight <= 0) return rect;
|
||||||
|
|
||||||
|
const ratio = pixelWidth / pixelHeight;
|
||||||
|
let nextWidth = rect.width;
|
||||||
|
let nextHeight = rect.height;
|
||||||
|
|
||||||
|
if (ratio > maxAspectRatio) {
|
||||||
|
nextHeight = Math.min(1, pixelWidth / maxAspectRatio / sourceHeight);
|
||||||
|
} else if (ratio < 1 / maxAspectRatio) {
|
||||||
|
nextWidth = Math.min(1, (pixelHeight / maxAspectRatio) / sourceWidth);
|
||||||
|
} else {
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
const centerX = rect.x + rect.width / 2;
|
||||||
|
const centerY = rect.y + rect.height / 2;
|
||||||
|
const x = clamp(centerX - nextWidth / 2, 0, Math.max(0, 1 - nextWidth));
|
||||||
|
const y = clamp(centerY - nextHeight / 2, 0, Math.max(0, 1 - nextHeight));
|
||||||
|
|
||||||
|
return {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width: nextWidth,
|
||||||
|
height: nextHeight,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function getRectUnion(
|
function getRectUnion(
|
||||||
leftRect: NormalizedLocalEditRegion["rect"],
|
leftRect: NormalizedLocalEditRegion["rect"],
|
||||||
rightRect: NormalizedLocalEditRegion["rect"]
|
rightRect: NormalizedLocalEditRegion["rect"]
|
||||||
@ -938,6 +1028,40 @@ function getScaleAdjustPatchWorkspaceRect(
|
|||||||
return workspaceRects.reduce((combined, rect) => getRectUnion(combined, rect));
|
return workspaceRects.reduce((combined, rect) => getRectUnion(combined, rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shouldUseScaleAdjustEdgeLockedFullFrameReference(params: {
|
||||||
|
regions: NormalizedLocalEditRegion[];
|
||||||
|
scalePercent?: ScaleAdjustPercent | null;
|
||||||
|
sourceHeight: number;
|
||||||
|
sourceWidth: number;
|
||||||
|
}) {
|
||||||
|
const { regions, scalePercent, sourceHeight, sourceWidth } = params;
|
||||||
|
if (!regions.length || !hasScaleAdjustShrinkTarget(regions, scalePercent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!regions.some((region) => isScaleAdjustFurnitureProductLikePrompt(region.prompt))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const workspaceRect = expandRectToProviderAspectLimit(
|
||||||
|
getScaleAdjustPatchWorkspaceRect(regions, scalePercent),
|
||||||
|
sourceWidth,
|
||||||
|
sourceHeight
|
||||||
|
);
|
||||||
|
const pixelWidth = workspaceRect.width * sourceWidth;
|
||||||
|
const pixelHeight = workspaceRect.height * sourceHeight;
|
||||||
|
if (pixelWidth <= 0 || pixelHeight <= 0) return false;
|
||||||
|
|
||||||
|
const ratio = pixelWidth / pixelHeight;
|
||||||
|
const touchesCanvasEdge =
|
||||||
|
workspaceRect.x <= 0.002 ||
|
||||||
|
workspaceRect.y <= 0.002 ||
|
||||||
|
workspaceRect.x + workspaceRect.width >= 0.998 ||
|
||||||
|
workspaceRect.y + workspaceRect.height >= 0.998;
|
||||||
|
const nearProviderAspectLimit = ratio <= 0.42 || ratio >= 2.4;
|
||||||
|
|
||||||
|
return touchesCanvasEdge && nearProviderAspectLimit;
|
||||||
|
}
|
||||||
|
|
||||||
function expandPixelRectForCrop(params: {
|
function expandPixelRectForCrop(params: {
|
||||||
height: number;
|
height: number;
|
||||||
pixelRect: NormalizedLocalEditRegion["pixelRect"];
|
pixelRect: NormalizedLocalEditRegion["pixelRect"];
|
||||||
@ -1336,6 +1460,13 @@ function isScaleAdjustPersonLikePrompt(prompt: string) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isScaleAdjustFurnitureProductLikePrompt(prompt: string) {
|
||||||
|
const text = normalizeScaleAdjustModelText(prompt);
|
||||||
|
return /furniture|product|commodity|goods|object|item|subject|sofa|couch|chair|table|desk|cabinet|shelf|bed|bench|lamp|basket|rack|stool|drawer|wardrobe|主物体|主体|物体|商品|产品|家具|沙发|椅|桌|柜|架|床|凳|灯|篮|抽屉|衣柜/.test(
|
||||||
|
text
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function hasScaleAdjustPersonPixelSignal(params: {
|
function hasScaleAdjustPersonPixelSignal(params: {
|
||||||
box: { left: number; top: number; width: number; height: number };
|
box: { left: number; top: number; width: number; height: number };
|
||||||
raw: Buffer;
|
raw: Buffer;
|
||||||
@ -2781,7 +2912,11 @@ async function createScaleAdjustPatchReference(params: {
|
|||||||
sourceWidth,
|
sourceWidth,
|
||||||
userId,
|
userId,
|
||||||
} = params;
|
} = params;
|
||||||
const workspaceRect = getScaleAdjustPatchWorkspaceRect(regions, scalePercent);
|
const workspaceRect = expandRectToProviderAspectLimit(
|
||||||
|
getScaleAdjustPatchWorkspaceRect(regions, scalePercent),
|
||||||
|
sourceWidth,
|
||||||
|
sourceHeight
|
||||||
|
);
|
||||||
const workspacePixelRect = rectToPixels(workspaceRect, sourceWidth, sourceHeight);
|
const workspacePixelRect = rectToPixels(workspaceRect, sourceWidth, sourceHeight);
|
||||||
const shouldUseStructureLockedDraft = hasScaleAdjustStructureTarget(
|
const shouldUseStructureLockedDraft = hasScaleAdjustStructureTarget(
|
||||||
regions,
|
regions,
|
||||||
@ -3890,7 +4025,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const useFalScaleAdjustCoordinatePrompt =
|
const useFalScaleAdjustCoordinatePrompt =
|
||||||
useScaleAdjustCoordinatePrompt &&
|
useScaleAdjustCoordinatePrompt &&
|
||||||
resolvedScaleAdjustModelEntry?.provider?.type === "fal-image" &&
|
resolvedScaleAdjustModelEntry?.provider?.type === "fal-image" &&
|
||||||
!useScaleAdjustFullFrameFalEdit;
|
getScaleAdjustModelFamily(resolvedScaleAdjustModelEntry) === "nano-banana-2";
|
||||||
const useScaleAdjustVisualLayoutGuide =
|
const useScaleAdjustVisualLayoutGuide =
|
||||||
useScaleAdjustCoordinatePrompt &&
|
useScaleAdjustCoordinatePrompt &&
|
||||||
!useFalScaleAdjustCoordinatePrompt &&
|
!useFalScaleAdjustCoordinatePrompt &&
|
||||||
@ -4152,7 +4287,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const imageRequest: CanvasGenerateImageRequest = {
|
const imageRequest: CanvasGenerateImageRequest = {
|
||||||
allowFailover: isScaleAdjustOperation ? false : undefined,
|
allowFailover: isScaleAdjustOperation ? false : undefined,
|
||||||
aspectRatio: scaleAdjustPatchReference
|
aspectRatio: scaleAdjustPatchReference
|
||||||
? inferClosestAspectRatio(
|
? inferScaleAdjustPatchAspectRatio(
|
||||||
scaleAdjustPatchReference.workspacePixelRect.width,
|
scaleAdjustPatchReference.workspacePixelRect.width,
|
||||||
scaleAdjustPatchReference.workspacePixelRect.height
|
scaleAdjustPatchReference.workspacePixelRect.height
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user