57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
import { materialContentUrl } from "@/lib/client/asset-urls";
|
|
import type { PromptMaterial } from "@/lib/prompt/assembler";
|
|
import type { SeedreamAnnotation } from "@/lib/seedream/creation";
|
|
|
|
const markerColor = "#2563eb";
|
|
|
|
export async function createSeedreamMarkedFile(
|
|
source: PromptMaterial,
|
|
annotations: SeedreamAnnotation[],
|
|
imageIndex: number
|
|
) {
|
|
const strokes = annotations.filter((annotation) => annotation.kind === "stroke" && annotation.points && annotation.points.length > 1);
|
|
if (!strokes.length) return null;
|
|
|
|
const response = await fetch(materialContentUrl(source), { credentials: "same-origin" });
|
|
if (!response.ok) throw new Error(`读取图${imageIndex}失败,无法合成蓝色标记`);
|
|
const bitmap = await createImageBitmap(await response.blob());
|
|
try {
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = bitmap.width;
|
|
canvas.height = bitmap.height;
|
|
const context = canvas.getContext("2d");
|
|
if (!context) throw new Error("当前浏览器无法创建标记画布");
|
|
context.drawImage(bitmap, 0, 0);
|
|
context.strokeStyle = markerColor;
|
|
context.fillStyle = markerColor;
|
|
context.lineCap = "round";
|
|
context.lineJoin = "round";
|
|
context.lineWidth = Math.max(5, Math.round(Math.min(bitmap.width, bitmap.height) * 0.012));
|
|
|
|
for (const stroke of strokes) {
|
|
const points = stroke.points || [];
|
|
if (!points.length) continue;
|
|
context.beginPath();
|
|
context.moveTo(points[0].x / 1000 * bitmap.width, points[0].y / 1000 * bitmap.height);
|
|
for (const point of points.slice(1)) {
|
|
context.lineTo(point.x / 1000 * bitmap.width, point.y / 1000 * bitmap.height);
|
|
}
|
|
context.stroke();
|
|
}
|
|
|
|
const blob = await canvasBlob(canvas, "image/png");
|
|
return new File([blob], `seedream-marked-image-${imageIndex}.png`, { type: "image/png" });
|
|
} finally {
|
|
bitmap.close();
|
|
}
|
|
}
|
|
|
|
function canvasBlob(canvas: HTMLCanvasElement, type: string) {
|
|
return new Promise<Blob>((resolve, reject) => {
|
|
canvas.toBlob((blob) => {
|
|
if (blob) resolve(blob);
|
|
else reject(new Error("生成标记图片失败"));
|
|
}, type);
|
|
});
|
|
}
|