import { useEffect, useMemo, useState } from "react"; import { Button, Modal, Segmented } from "antd"; import { ImagePlus } from "lucide-react"; import { readImageMeta } from "@/lib/image-utils"; import { MAX_UPSCALE_LONG_EDGE, resolveUpscaleSize, type ImageUpscaleAlgorithm, type ImageUpscaleParams } from "@/lib/canvas/canvas-image-data"; export type CanvasImageUpscaleParams = ImageUpscaleParams; const algorithms: Array<{ value: ImageUpscaleAlgorithm; title: string; description: string }> = [ { value: "high", title: "高清插值", description: "适合照片和细节图" }, { value: "bilinear", title: "双线性", description: "平滑、速度快" }, { value: "nearest", title: "最近邻", description: "适合像素风格" }, ]; const targetOptions = [ { label: "1K", value: 1024 }, { label: "2K", value: 2048 }, { label: "4K", value: MAX_UPSCALE_LONG_EDGE }, ]; const defaultParams: CanvasImageUpscaleParams = { targetLongEdge: 2048, algorithm: "high", }; export function CanvasNodeUpscaleDialog({ dataUrl, open, onClose, onConfirm }: { dataUrl: string; open: boolean; onClose: () => void; onConfirm: (params: CanvasImageUpscaleParams) => void }) { const [params, setParams] = useState(defaultParams); const [image, setImage] = useState<{ width: number; height: number } | null>(null); const sourceLongEdge = image ? Math.max(image.width, image.height) : 0; const outputSize = useMemo(() => (image ? resolveUpscaleSize(image.width, image.height, params.targetLongEdge) : null), [image, params.targetLongEdge]); const canUpscale = Boolean(image && sourceLongEdge < params.targetLongEdge && params.targetLongEdge <= MAX_UPSCALE_LONG_EDGE); const reachedMax = Boolean(image && sourceLongEdge >= MAX_UPSCALE_LONG_EDGE); useEffect(() => { if (!open) return; setParams(defaultParams); setImage(null); }, [dataUrl, open]); useEffect(() => { if (!open) return; void readImageMeta(dataUrl).then(setImage); }, [dataUrl, open]); useEffect(() => { if (!image) return; const nextTarget = targetOptions.find((option) => sourceLongEdge < option.value)?.value || MAX_UPSCALE_LONG_EDGE; setParams((current) => ({ ...current, targetLongEdge: nextTarget })); }, [image, sourceLongEdge]); return (

图片放大

源图 {image ? `${image.width} x ${image.height} px` : "读取中"}
目标像素
({ label: `${option.label} · ${option.value}px`, value: option.value, disabled: Boolean(image && sourceLongEdge >= option.value) }))} onChange={(value) => setParams((current) => ({ ...current, targetLongEdge: Number(value) }))} /> {image && !canUpscale ?
{reachedMax ? "图片已达到 4K,无需放大" : "图片已达到当前目标像素,无需放大"}
: null}
放大算法
({ value: item.value, label: ( {item.title} {item.description} ), }))} onChange={(value) => setParams((current) => ({ ...current, algorithm: value as ImageUpscaleAlgorithm }))} />
输出尺寸 {outputSize ? `${outputSize.width} x ${outputSize.height} px` : "未知"}
); }