You've already forked Nano-Banana-AI-Image-Editor
修复内存溢出问题
This commit is contained in:
@@ -6,16 +6,16 @@ const genAI = new GoogleGenAI({ apiKey: API_KEY })
|
||||
|
||||
export interface GenerationRequest {
|
||||
prompt: string
|
||||
referenceImages?: string[] // base64数组
|
||||
referenceImages?: Blob[] // Blob数组
|
||||
temperature?: number
|
||||
seed?: number
|
||||
}
|
||||
|
||||
export interface EditRequest {
|
||||
instruction: string
|
||||
originalImage: string // base64
|
||||
referenceImages?: string[] // base64数组
|
||||
maskImage?: string // base64
|
||||
originalImage: Blob // Blob
|
||||
referenceImages?: Blob[] // Blob数组
|
||||
maskImage?: Blob // Blob
|
||||
temperature?: number
|
||||
seed?: number
|
||||
}
|
||||
@@ -27,18 +27,37 @@ export interface UsageMetadata {
|
||||
}
|
||||
|
||||
export interface SegmentationRequest {
|
||||
image: string // base64
|
||||
image: Blob // Blob
|
||||
query: string // "像素(x,y)处的对象" 或 "红色汽车"
|
||||
}
|
||||
|
||||
export class GeminiService {
|
||||
async generateImage(request: GenerationRequest): Promise<{ images: string[]; usageMetadata?: any }> {
|
||||
// 将Blob转换为base64的辅助函数
|
||||
private async blobToBase64(blob: Blob): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
const result = reader.result as string;
|
||||
const base64 = result.split(',')[1]; // Remove data:image/png;base64, prefix
|
||||
resolve(base64);
|
||||
};
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
async generateImage(request: GenerationRequest): Promise<{ images: Blob[]; usageMetadata?: any }> {
|
||||
try {
|
||||
const contents: any[] = [{ text: request.prompt }]
|
||||
|
||||
// 如果提供了参考图像则添加
|
||||
if (request.referenceImages && request.referenceImages.length > 0) {
|
||||
request.referenceImages.forEach(image => {
|
||||
// 将Blob转换为base64以发送到API
|
||||
const base64Images = await Promise.all(
|
||||
request.referenceImages.map(blob => this.blobToBase64(blob))
|
||||
);
|
||||
|
||||
base64Images.forEach(image => {
|
||||
contents.push({
|
||||
inlineData: {
|
||||
mimeType: 'image/png',
|
||||
@@ -82,13 +101,22 @@ export class GeminiService {
|
||||
}
|
||||
}
|
||||
|
||||
const images: string[] = []
|
||||
const images: Blob[] = []
|
||||
|
||||
// 检查响应是否存在以及是否有内容
|
||||
if (response.candidates && response.candidates.length > 0 && response.candidates[0].content && response.candidates[0].content.parts) {
|
||||
for (const part of response.candidates[0].content.parts) {
|
||||
if (part.inlineData) {
|
||||
images.push(part.inlineData.data)
|
||||
// 将返回的base64数据转换为Blob
|
||||
const byteString = atob(part.inlineData.data);
|
||||
const mimeString = part.inlineData.mimeType || 'image/png';
|
||||
const ab = new ArrayBuffer(byteString.length);
|
||||
const ia = new Uint8Array(ab);
|
||||
for (let i = 0; i < byteString.length; i++) {
|
||||
ia[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
const blob = new Blob([ab], { type: mimeString });
|
||||
images.push(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,21 +134,29 @@ export class GeminiService {
|
||||
}
|
||||
}
|
||||
|
||||
async editImage(request: EditRequest): Promise<{ images: string[]; usageMetadata?: any }> {
|
||||
async editImage(request: EditRequest): Promise<{ images: Blob[]; usageMetadata?: any }> {
|
||||
try {
|
||||
// 将Blob转换为base64以发送到API
|
||||
const originalImageBase64 = await this.blobToBase64(request.originalImage);
|
||||
|
||||
const contents = [
|
||||
{ text: this.buildEditPrompt(request) },
|
||||
{
|
||||
inlineData: {
|
||||
mimeType: 'image/png',
|
||||
data: request.originalImage,
|
||||
data: originalImageBase64,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// 如果提供了参考图像则添加
|
||||
if (request.referenceImages && request.referenceImages.length > 0) {
|
||||
request.referenceImages.forEach(image => {
|
||||
// 将Blob转换为base64以发送到API
|
||||
const base64ReferenceImages = await Promise.all(
|
||||
request.referenceImages.map(blob => this.blobToBase64(blob))
|
||||
);
|
||||
|
||||
base64ReferenceImages.forEach(image => {
|
||||
contents.push({
|
||||
inlineData: {
|
||||
mimeType: 'image/png',
|
||||
@@ -131,10 +167,12 @@ export class GeminiService {
|
||||
}
|
||||
|
||||
if (request.maskImage) {
|
||||
// 将Blob转换为base64以发送到API
|
||||
const maskImageBase64 = await this.blobToBase64(request.maskImage);
|
||||
contents.push({
|
||||
inlineData: {
|
||||
mimeType: 'image/png',
|
||||
data: request.maskImage,
|
||||
data: maskImageBase64,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -170,13 +208,22 @@ export class GeminiService {
|
||||
}
|
||||
}
|
||||
|
||||
const images: string[] = []
|
||||
const images: Blob[] = []
|
||||
|
||||
// 检查响应是否存在以及是否有内容
|
||||
if (response.candidates && response.candidates.length > 0 && response.candidates[0].content && response.candidates[0].content.parts) {
|
||||
for (const part of response.candidates[0].content.parts) {
|
||||
if (part.inlineData) {
|
||||
images.push(part.inlineData.data)
|
||||
// 将返回的base64数据转换为Blob
|
||||
const byteString = atob(part.inlineData.data);
|
||||
const mimeString = part.inlineData.mimeType || 'image/png';
|
||||
const ab = new ArrayBuffer(byteString.length);
|
||||
const ia = new Uint8Array(ab);
|
||||
for (let i = 0; i < byteString.length; i++) {
|
||||
ia[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
const blob = new Blob([ab], { type: mimeString });
|
||||
images.push(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,6 +243,9 @@ export class GeminiService {
|
||||
|
||||
async segmentImage(request: SegmentationRequest): Promise<any> {
|
||||
try {
|
||||
// 将Blob转换为base64以发送到API
|
||||
const imageBase64 = await this.blobToBase64(request.image);
|
||||
|
||||
const prompt = [
|
||||
{
|
||||
text: `分析此图像并为以下对象创建分割遮罩: ${request.query}
|
||||
@@ -216,7 +266,7 @@ export class GeminiService {
|
||||
{
|
||||
inlineData: {
|
||||
mimeType: 'image/png',
|
||||
data: request.image,
|
||||
data: imageBase64,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user