You've already forked Nano-Banana-AI-Image-Editor
初始化提交
This commit is contained in:
@@ -22,9 +22,9 @@ export const useImageGeneration = () => {
|
||||
type: 'output',
|
||||
url: `data:image/png;base64,${base64}`,
|
||||
mime: 'image/png',
|
||||
width: 1024, // Default Gemini output size
|
||||
width: 1024, // 默认Gemini输出尺寸
|
||||
height: 1024,
|
||||
checksum: base64.slice(0, 32) // Simple checksum
|
||||
checksum: base64.slice(0, 32) // 简单校验和
|
||||
}));
|
||||
|
||||
const generation: Generation = {
|
||||
@@ -60,11 +60,11 @@ export const useImageGeneration = () => {
|
||||
addGeneration(generation);
|
||||
setCanvasImage(outputAssets[0].url);
|
||||
|
||||
// Create project if none exists
|
||||
// 如果没有项目则创建项目
|
||||
if (!currentProject) {
|
||||
const newProject = {
|
||||
id: generateId(),
|
||||
title: 'Untitled Project',
|
||||
title: '未命名项目',
|
||||
generations: [generation],
|
||||
edits: [],
|
||||
createdAt: Date.now(),
|
||||
@@ -76,7 +76,7 @@ export const useImageGeneration = () => {
|
||||
setIsGenerating(false);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Generation failed:', error);
|
||||
console.error('生成失败:', error);
|
||||
setIsGenerating(false);
|
||||
}
|
||||
});
|
||||
@@ -104,16 +104,16 @@ export const useImageEditing = () => {
|
||||
|
||||
const editMutation = useMutation({
|
||||
mutationFn: async (instruction: string) => {
|
||||
// Always use canvas image as primary target if available, otherwise use first uploaded image
|
||||
// 如果可用,始终使用画布图像作为主要目标,否则使用第一张上传的图像
|
||||
const sourceImage = canvasImage || uploadedImages[0];
|
||||
if (!sourceImage) throw new Error('No image to edit');
|
||||
if (!sourceImage) throw new Error('没有要编辑的图像');
|
||||
|
||||
// Convert canvas image to base64
|
||||
// 将画布图像转换为base64
|
||||
const base64Image = sourceImage.includes('base64,')
|
||||
? sourceImage.split('base64,')[1]
|
||||
: sourceImage;
|
||||
|
||||
// Get reference images for style guidance
|
||||
// 获取用于样式指导的参考图像
|
||||
let referenceImages = editReferenceImages
|
||||
.filter(img => img.includes('base64,'))
|
||||
.map(img => img.split('base64,')[1]);
|
||||
@@ -121,26 +121,26 @@ export const useImageEditing = () => {
|
||||
let maskImage: string | undefined;
|
||||
let maskedReferenceImage: string | undefined;
|
||||
|
||||
// Create mask from brush strokes if any exist
|
||||
// 如果存在画笔描边,则从描边创建遮罩
|
||||
if (brushStrokes.length > 0) {
|
||||
// Create a temporary image to get actual dimensions
|
||||
// 创建临时图像以获取实际尺寸
|
||||
const tempImg = new Image();
|
||||
tempImg.src = sourceImage;
|
||||
await new Promise<void>((resolve) => {
|
||||
tempImg.onload = () => resolve();
|
||||
});
|
||||
|
||||
// Create mask canvas with exact image dimensions
|
||||
// 创建具有确切图像尺寸的遮罩画布
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
canvas.width = tempImg.width;
|
||||
canvas.height = tempImg.height;
|
||||
|
||||
// Fill with black (unmasked areas)
|
||||
// 用黑色填充(未遮罩区域)
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Draw white strokes (masked areas)
|
||||
// 绘制白色描边(遮罩区域)
|
||||
ctx.strokeStyle = 'white';
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
@@ -158,20 +158,20 @@ export const useImageEditing = () => {
|
||||
}
|
||||
});
|
||||
|
||||
// Convert mask to base64
|
||||
// 将遮罩转换为base64
|
||||
const maskDataUrl = canvas.toDataURL('image/png');
|
||||
maskImage = maskDataUrl.split('base64,')[1];
|
||||
|
||||
// Create masked reference image (original image with mask overlay)
|
||||
// 创建遮罩参考图像(带遮罩叠加的原始图像)
|
||||
const maskedCanvas = document.createElement('canvas');
|
||||
const maskedCtx = maskedCanvas.getContext('2d')!;
|
||||
maskedCanvas.width = tempImg.width;
|
||||
maskedCanvas.height = tempImg.height;
|
||||
|
||||
// Draw original image
|
||||
// 绘制原始图像
|
||||
maskedCtx.drawImage(tempImg, 0, 0);
|
||||
|
||||
// Draw mask overlay with transparency
|
||||
// 绘制带透明度的遮罩叠加
|
||||
maskedCtx.globalCompositeOperation = 'source-over';
|
||||
maskedCtx.globalAlpha = 0.4;
|
||||
maskedCtx.fillStyle = '#A855F7';
|
||||
@@ -198,7 +198,7 @@ export const useImageEditing = () => {
|
||||
const maskedDataUrl = maskedCanvas.toDataURL('image/png');
|
||||
maskedReferenceImage = maskedDataUrl.split('base64,')[1];
|
||||
|
||||
// Add the masked image as a reference for the model
|
||||
// 将遮罩图像作为参考添加到模型中
|
||||
referenceImages = [maskedReferenceImage, ...referenceImages];
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ export const useImageEditing = () => {
|
||||
checksum: base64.slice(0, 32)
|
||||
}));
|
||||
|
||||
// Create mask reference asset if we have one
|
||||
// 如果有遮罩参考图像则创建遮罩参考资产
|
||||
const maskReferenceAsset: Asset | undefined = maskedReferenceImage ? {
|
||||
id: generateId(),
|
||||
type: 'mask',
|
||||
@@ -252,7 +252,7 @@ export const useImageEditing = () => {
|
||||
|
||||
addEdit(edit);
|
||||
|
||||
// Automatically load the edited image in the canvas
|
||||
// 自动在画布中加载编辑后的图像
|
||||
const { selectEdit, selectGeneration } = useAppStore.getState();
|
||||
setCanvasImage(outputAssets[0].url);
|
||||
selectEdit(edit.id);
|
||||
@@ -261,7 +261,7 @@ export const useImageEditing = () => {
|
||||
setIsGenerating(false);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Edit failed:', error);
|
||||
console.error('编辑失败:', error);
|
||||
setIsGenerating(false);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user