102 lines
2.7 KiB
TypeScript
102 lines
2.7 KiB
TypeScript
import type { AgentPsdTemplateReplaceMode } from "@/lib/agents/psd-template-config";
|
|
|
|
export interface AgentPsdImagePlacement {
|
|
scale: number;
|
|
offsetX: number;
|
|
offsetY: number;
|
|
}
|
|
|
|
export interface AgentPsdImageSize {
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
export function getDefaultAgentPsdImagePlacement(): AgentPsdImagePlacement {
|
|
return {
|
|
scale: 1,
|
|
offsetX: 0,
|
|
offsetY: 0,
|
|
};
|
|
}
|
|
|
|
export function normalizeAgentPsdImagePlacement(
|
|
value: Partial<AgentPsdImagePlacement> | null | undefined
|
|
): AgentPsdImagePlacement {
|
|
const scale = Number(value?.scale);
|
|
const offsetX = Number(value?.offsetX);
|
|
const offsetY = Number(value?.offsetY);
|
|
|
|
return {
|
|
scale: Number.isFinite(scale) && scale > 0 ? Math.max(0.1, Math.min(8, scale)) : 1,
|
|
offsetX: Number.isFinite(offsetX) ? offsetX : 0,
|
|
offsetY: Number.isFinite(offsetY) ? offsetY : 0,
|
|
};
|
|
}
|
|
|
|
function resolveBaseFittedSize(params: {
|
|
containerWidth: number;
|
|
containerHeight: number;
|
|
imageWidth: number;
|
|
imageHeight: number;
|
|
replaceMode: AgentPsdTemplateReplaceMode;
|
|
}) {
|
|
const { containerWidth, containerHeight, imageWidth, imageHeight, replaceMode } = params;
|
|
const safeImageWidth = Math.max(1, imageWidth);
|
|
const safeImageHeight = Math.max(1, imageHeight);
|
|
|
|
if (replaceMode === "stretch") {
|
|
return {
|
|
width: containerWidth,
|
|
height: containerHeight,
|
|
left: 0,
|
|
top: 0,
|
|
};
|
|
}
|
|
|
|
const fitRatio =
|
|
replaceMode === "contain"
|
|
? Math.min(containerWidth / safeImageWidth, containerHeight / safeImageHeight)
|
|
: Math.max(containerWidth / safeImageWidth, containerHeight / safeImageHeight);
|
|
|
|
const width = safeImageWidth * fitRatio;
|
|
const height = safeImageHeight * fitRatio;
|
|
|
|
return {
|
|
width,
|
|
height,
|
|
left: (containerWidth - width) / 2,
|
|
top: (containerHeight - height) / 2,
|
|
};
|
|
}
|
|
|
|
export function resolveAgentPsdImagePlacementFrame(params: {
|
|
containerWidth: number;
|
|
containerHeight: number;
|
|
imageWidth: number;
|
|
imageHeight: number;
|
|
replaceMode: AgentPsdTemplateReplaceMode;
|
|
placement?: Partial<AgentPsdImagePlacement> | null;
|
|
}) {
|
|
const { containerWidth, containerHeight, imageWidth, imageHeight, replaceMode } = params;
|
|
const placement = normalizeAgentPsdImagePlacement(params.placement);
|
|
const baseFrame = resolveBaseFittedSize({
|
|
containerWidth,
|
|
containerHeight,
|
|
imageWidth,
|
|
imageHeight,
|
|
replaceMode,
|
|
});
|
|
|
|
const width = baseFrame.width * placement.scale;
|
|
const height = baseFrame.height * placement.scale;
|
|
const left = baseFrame.left - (width - baseFrame.width) / 2 + placement.offsetX;
|
|
const top = baseFrame.top - (height - baseFrame.height) / 2 + placement.offsetY;
|
|
|
|
return {
|
|
width,
|
|
height,
|
|
left,
|
|
top,
|
|
};
|
|
}
|