add_background上传图片如果非透明背景自动取出背景
This commit is contained in:
parent
07417af024
commit
1e140aa967
@ -1031,8 +1031,6 @@
|
||||
"Publish failed, please check permission and server logs": "发布失败,请检查权限和服务器日志",
|
||||
"Node published to marketplace successfully": "节点已成功发布到市场",
|
||||
"Are you sure you want to publish node \"{0}\" to the marketplace?": "确定要将节点 \"{0}\" 发布到市场吗?",
|
||||
"Confirm": "确认",
|
||||
|
||||
"Agent Marketplace": "智能体市场",
|
||||
"Browse and install agents from Jingrow Agent Marketplace": "浏览并安装来自 Jingrow 智能体市场的智能体",
|
||||
"Loading agents...": "加载智能体中...",
|
||||
@ -1050,22 +1048,17 @@
|
||||
"Untitled Agent": "未命名智能体",
|
||||
"Failed to load agents": "加载智能体失败",
|
||||
"Failed to load agent details": "加载智能体详情失败",
|
||||
"Agent execution started successfully": "智能体执行已启动",
|
||||
"Execution failed": "执行失败",
|
||||
"Please save the agent first": "请先保存智能体",
|
||||
"Are you sure you want to publish agent \"{0}\" to the marketplace?": "确定要将智能体 \"{0}\" 发布到市场吗?",
|
||||
"Agent flow data or name is missing": "智能体流程数据或名称不存在",
|
||||
"Agent already exists": "智能体已存在",
|
||||
"Agent \"{0}\" is already installed, do you want to overwrite?": "智能体 \"{0}\" 已安装,是否覆盖安装?",
|
||||
"Confirm Overwrite": "确认覆盖",
|
||||
"Preparing installation...": "正在准备安装...",
|
||||
"Fetching agent details...": "正在获取智能体详情...",
|
||||
"Failed to fetch agent details": "获取智能体详情失败",
|
||||
"Installing agent...": "正在安装智能体...",
|
||||
"Agent installed successfully!": "智能体安装成功!",
|
||||
"Agent installed successfully": "智能体安装成功",
|
||||
"Agent flow data is missing": "智能体流程数据不存在",
|
||||
"Installation failed": "安装失败",
|
||||
"Installing Agent": "正在安装智能体",
|
||||
"Installing Node": "正在安装节点",
|
||||
|
||||
@ -1104,7 +1097,6 @@
|
||||
"Use route name for internal navigation (recommended)": "使用路由名进行内部导航(推荐)",
|
||||
"Enter URL path": "请输入URL路径",
|
||||
"Internal path: /example": "内部路径:/example",
|
||||
"External link: starts with http:// or https://": "外部链接:以 http:// 或 https:// 开头",
|
||||
"Please enter tool name": "请输入工具名称",
|
||||
"Please enter tool title": "请输入工具标题",
|
||||
"Enter tool title": "请输入工具标题",
|
||||
@ -1114,7 +1106,6 @@
|
||||
"Tool updated successfully": "工具更新成功",
|
||||
"Tool added successfully": "工具添加成功",
|
||||
"Are you sure you want to delete tool": "确定要删除工具",
|
||||
"Tool deleted successfully": "工具删除成功",
|
||||
"Route not found: ": "路由未找到:",
|
||||
"Remove Background": "图片去背景",
|
||||
"Add Background": "添加背景",
|
||||
@ -1123,59 +1114,30 @@
|
||||
"add background, background color, image background, transparent background, online background tool, image processing, background editor, free tool": "添加背景、背景颜色、图片背景、透明背景、在线背景工具、图片处理、背景编辑器、免费工具",
|
||||
"Background Color": "背景颜色",
|
||||
"Color Tones": "色调",
|
||||
"Upload Image": "上传图片",
|
||||
"or": "或",
|
||||
"Paste image URL here": "在此粘贴图片URL",
|
||||
"Drag and drop your image anywhere, or paste image directly": "将图片拖放到任意位置,或直接粘贴图片",
|
||||
"Supports JPG, PNG, WebP formats": "支持 JPG、PNG、WebP 格式",
|
||||
"Loading image from URL...": "正在从URL加载图片...",
|
||||
"Apply Background": "应用背景",
|
||||
"Applying background...": "正在应用背景...",
|
||||
"Change Image": "更换图片",
|
||||
"Add New Image": "添加新图片",
|
||||
"Drop image anywhere to add background": "将图片拖放到任意位置以添加背景",
|
||||
"Please upload an image first": "请先上传图片",
|
||||
"Please enter a valid hex color code": "请输入有效的十六进制颜色代码",
|
||||
"Background applied successfully": "背景应用成功",
|
||||
"Failed to apply background": "应用背景失败",
|
||||
"Please enter an image URL": "请输入图片URL",
|
||||
"Please enter a valid image URL": "请输入有效的图片URL",
|
||||
"Unsupported image format. Please use JPG, PNG, or WebP": "不支持的图片格式,请使用 JPG、PNG 或 WebP",
|
||||
"Image size exceeds 10MB limit": "图片大小超过10MB限制",
|
||||
"Image processing failed, please try again": "图片处理失败,请重试",
|
||||
"Failed to load image from URL": "从URL加载图片失败",
|
||||
"CORS error. The image server does not allow cross-origin access.": "跨域错误,图片服务器不允许跨域访问",
|
||||
"Failed to load image. Please check the URL and try again.": "加载图片失败,请检查URL后重试",
|
||||
"Failed to load image": "加载图片失败",
|
||||
"Please upload an image file": "请上传图片文件",
|
||||
"Remove Background - Free AI Background Removal Tool": "图片去背景 - 免费AI背景移除工具",
|
||||
"Remove background from images using AI technology": "使用AI技术去除图片背景",
|
||||
"Remove background from images using AI technology. Free online tool to remove image backgrounds instantly. Supports JPG, PNG, WebP formats.": "使用AI技术去除图片背景。免费在线工具,即时去除图片背景。支持 JPG、PNG、WebP 格式。",
|
||||
"remove background, AI background removal, online background remover, image processing, background removal tool, transparent background, free tool, JPG background removal, PNG background removal": "图片去背景,AI去背景,在线去背景,图片处理,背景移除,透明背景,免费工具,JPG去背景,PNG去背景",
|
||||
"Upload Image": "上传图片",
|
||||
"Drag and drop your image here, or click to browse": "拖拽图片到此处,或点击浏览",
|
||||
"Supports JPG, PNG, WebP formats": "支持 JPG、PNG、WebP 格式",
|
||||
"Drop image anywhere to remove background": "拖拽图片到任意位置开始去背景",
|
||||
"Image Preview": "图片预览",
|
||||
"Change Image": "更换图片",
|
||||
"Original": "原图",
|
||||
"Background Removed": "去背景后",
|
||||
"Result will appear here": "处理结果将显示在这里",
|
||||
"Processing...": "处理中...",
|
||||
"Download": "下载",
|
||||
"How it works": "使用说明",
|
||||
"Upload an image with a clear subject": "上传一张主体清晰的图片",
|
||||
"Click \"Remove Background\" to process": "点击\"去背景\"按钮进行处理",
|
||||
"Download the result with transparent background": "下载透明背景的处理结果",
|
||||
"Please upload an image file": "请上传图片文件",
|
||||
"Unsupported image format. Please use JPG, PNG, or WebP": "不支持的图片格式,请使用 JPG、PNG 或 WebP 格式",
|
||||
"Image size exceeds 10MB limit": "图片大小超过 10MB 限制",
|
||||
"Please upload an image first": "请先上传图片",
|
||||
"Background removed successfully!": "背景移除成功!",
|
||||
"Failed to remove background": "背景移除失败",
|
||||
"Failed to upload image: ": "图片上传失败:",
|
||||
"Download started": "下载已开始",
|
||||
"Failed to download image": "下载失败",
|
||||
"Hide Default Tool": "隐藏默认工具",
|
||||
"Are you sure you want to hide default tool": "确定要隐藏默认工具",
|
||||
"You can show it again later": "您可以稍后再次显示",
|
||||
@ -1194,46 +1156,22 @@
|
||||
"Please login to download": "请先登录后才能下载",
|
||||
"Session expired. Please login again.": "会话已过期,请重新登录",
|
||||
"Session expired. Please login again to use this feature.": "会话已过期,请重新登录以使用此功能",
|
||||
"or": "或",
|
||||
"Paste image URL here": "在此处粘贴图片URL",
|
||||
"Or paste image URL here": "或在此处粘贴图片URL",
|
||||
"Drag and drop your image anywhere, or paste image directly": "拖拽图片到任意位置,或直接粘贴图片",
|
||||
"Loading image from URL...": "正在从URL加载图片...",
|
||||
"Please enter an image URL": "请输入图片URL",
|
||||
"Please enter a valid image URL": "请输入有效的图片URL",
|
||||
"Failed to load image from URL": "从URL加载图片失败",
|
||||
"CORS error. The image server does not allow cross-origin access.": "CORS错误,图片服务器不允许跨域访问",
|
||||
"Failed to load image. Please check the URL and try again.": "加载图片失败,请检查URL后重试",
|
||||
|
||||
"Tool Marketplace": "工具市场",
|
||||
"Browse and install tools from Jingrow Tool Marketplace": "浏览和安装来自 Jingrow 工具市场的工具",
|
||||
"Search tools...": "搜索工具...",
|
||||
"Sort by": "排序方式",
|
||||
"Latest": "最新",
|
||||
"Oldest": "最旧",
|
||||
"Name A-Z": "名称 A-Z",
|
||||
"Name Z-A": "名称 Z-A",
|
||||
"Most Popular": "最受欢迎",
|
||||
"Installed": "已安装",
|
||||
"Loading tools...": "正在加载工具...",
|
||||
"No tools found": "未找到工具",
|
||||
"Failed to load tools": "加载工具失败",
|
||||
"Tool Details": "工具详情",
|
||||
"Loading tool details...": "正在加载工具详情...",
|
||||
"Failed to load tool details": "加载工具详情失败",
|
||||
"Untitled Tool": "未命名工具",
|
||||
"Tool Name": "工具名称",
|
||||
"Author": "作者",
|
||||
"Developer": "开发者",
|
||||
"Route Name": "路由名称",
|
||||
"URL": "URL",
|
||||
"Created": "创建时间",
|
||||
"Last Updated": "最后更新",
|
||||
"Click image to try": "点击图片快速体验",
|
||||
"Remove Background": "去除背景",
|
||||
"Download": "下载",
|
||||
"Change Image": "更换图片",
|
||||
"Upload Image": "上传图片",
|
||||
"or": "或",
|
||||
"Paste image URL here": "粘贴图片URL",
|
||||
"Drag and drop your image anywhere, or paste image directly": "拖放图片到任意位置,或直接粘贴图片",
|
||||
@ -1243,7 +1181,6 @@
|
||||
"Background Removed": "去背景后",
|
||||
"Processing...": "处理中...",
|
||||
"Add new image": "添加新图片",
|
||||
"Delete": "删除",
|
||||
"Unsupported image format. Please use JPG, PNG, or WebP": "不支持的图片格式,请使用 JPG、PNG 或 WebP",
|
||||
"Image size exceeds 10MB limit": "图片大小超过 10MB 限制",
|
||||
"Please upload an image first": "请先上传图片",
|
||||
@ -1254,6 +1191,10 @@
|
||||
"Failed to load sample image": "加载示例图片失败",
|
||||
"Failed to remove background": "去背景失败",
|
||||
"Failed to load image from URL": "从URL加载图片失败",
|
||||
"Detecting non-transparent background, auto-removing...": "检测到非透明背景,正在自动去除...",
|
||||
"Auto remove background failed, using original image": "自动去除背景失败,使用原始图片",
|
||||
"Please login first to use auto remove background feature": "请先登录以使用自动去除背景功能",
|
||||
"Background removed successfully": "背景去除成功",
|
||||
"Sign up successful, but auto login failed. Please login manually": "注册成功,但自动登录失败,请手动登录",
|
||||
"WeChat": "微信",
|
||||
"Weibo": "微博",
|
||||
@ -1284,7 +1225,6 @@
|
||||
"Failed to create API key": "创建 API 密钥失败",
|
||||
"You don't have an API key yet. Click the button above to create one.": "您还没有 API 密钥。请点击上方按钮创建一个。",
|
||||
"Please copy the API secret now. You won't be able to see it again!": "请立即复制 API 密钥。您将无法再次查看它!",
|
||||
"API Secret": "API 密钥",
|
||||
"SSH Keys": "SSH 密钥",
|
||||
"Add SSH Key": "添加 SSH 密钥",
|
||||
"Add New SSH Key": "添加新的 SSH 密钥",
|
||||
@ -1387,7 +1327,6 @@
|
||||
"Scan the QR code": "扫描二维码",
|
||||
"Enter the code from the authenticator app": "输入身份验证器应用中的代码",
|
||||
"Enter the code from the authenticator app below": "在下方输入身份验证器应用中的代码",
|
||||
"Note": "注意",
|
||||
"If you cannot access the authenticator app, your account will be locked. Please ensure you back up your vault/key.": "如果您无法访问身份验证器应用,您的账户将被锁定。请确保您已备份您的密钥。",
|
||||
"Setup Key": "设置密钥",
|
||||
"Verify the code in the app to enable two-factor authentication": "输入应用中的验证码以启用双因素认证",
|
||||
|
||||
@ -552,6 +552,35 @@ const processFile = async (file: File) => {
|
||||
mode: 'contain'
|
||||
})
|
||||
|
||||
// Check if image has transparency
|
||||
const hasTransparency = await checkImageTransparency(compressedFile)
|
||||
|
||||
if (!hasTransparency) {
|
||||
// No transparency detected, auto remove background silently
|
||||
processing.value = true
|
||||
|
||||
try {
|
||||
const removedBgImage = await removeBackground(compressedFile)
|
||||
if (removedBgImage) {
|
||||
uploadedImage.value = removedBgImage
|
||||
resultImage.value = ''
|
||||
currentHistoryIndex.value = -1
|
||||
|
||||
const reader = new FileReader()
|
||||
reader.onload = async (e) => {
|
||||
uploadedImageUrl.value = e.target?.result as string
|
||||
await initializeCanvas()
|
||||
}
|
||||
reader.readAsDataURL(removedBgImage)
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auto remove background failed:', error)
|
||||
// Fall through to use original image silently
|
||||
}
|
||||
}
|
||||
|
||||
// Use image directly (already has transparency or removal failed)
|
||||
uploadedImage.value = compressedFile
|
||||
resultImage.value = ''
|
||||
currentHistoryIndex.value = -1
|
||||
@ -564,6 +593,135 @@ const processFile = async (file: File) => {
|
||||
reader.readAsDataURL(compressedFile)
|
||||
} catch (error) {
|
||||
message.error(t('Image processing failed, please try again'))
|
||||
processing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// Check if image has transparent pixels
|
||||
const checkImageTransparency = (file: File): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
const img = new Image()
|
||||
img.onload = () => {
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = img.width
|
||||
canvas.height = img.height
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
if (!ctx) {
|
||||
resolve(false)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.drawImage(img, 0, 0)
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
||||
const pixels = imageData.data
|
||||
|
||||
// Sample pixels to check for transparency
|
||||
// Check every 10th pixel for performance
|
||||
let transparentPixels = 0
|
||||
const sampleRate = 10
|
||||
|
||||
for (let i = 3; i < pixels.length; i += 4 * sampleRate) {
|
||||
if (pixels[i] < 255) {
|
||||
transparentPixels++
|
||||
}
|
||||
}
|
||||
|
||||
// If more than 1% pixels are transparent, consider it has transparency
|
||||
const totalSampledPixels = Math.floor(pixels.length / (4 * sampleRate))
|
||||
const transparencyRatio = transparentPixels / totalSampledPixels
|
||||
|
||||
resolve(transparencyRatio > 0.01)
|
||||
}
|
||||
img.onerror = () => resolve(false)
|
||||
img.src = e.target?.result as string
|
||||
}
|
||||
reader.onerror = () => resolve(false)
|
||||
reader.readAsDataURL(file)
|
||||
})
|
||||
}
|
||||
|
||||
// Remove background using API
|
||||
const removeBackground = async (file: File): Promise<File | null> => {
|
||||
if (!authStore.isLoggedIn) {
|
||||
message.warning(t('Please login first to use auto remove background feature'))
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), 180000)
|
||||
|
||||
const response = await fetch('/api/v1/tools/rmbg/file/free', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
signal: controller.signal
|
||||
})
|
||||
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const reader = response.body?.getReader()
|
||||
const decoder = new TextDecoder()
|
||||
let buffer = ''
|
||||
|
||||
if (!reader) {
|
||||
throw new Error('Response body is not readable')
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) break
|
||||
|
||||
buffer += decoder.decode(value, { stream: true })
|
||||
const lines = buffer.split('\n')
|
||||
buffer = lines.pop() || ''
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.trim()) {
|
||||
try {
|
||||
const result = JSON.parse(line.trim())
|
||||
if (result.status === 'success' && result.image_url) {
|
||||
// Download the image and convert to File
|
||||
const imgResponse = await fetch(result.image_url)
|
||||
const blob = await imgResponse.blob()
|
||||
const removedFile = new File([blob], 'removed-bg.png', { type: 'image/png' })
|
||||
return removedFile
|
||||
}
|
||||
} catch (parseError) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process last line
|
||||
if (buffer.trim()) {
|
||||
try {
|
||||
const result = JSON.parse(buffer.trim())
|
||||
if (result.status === 'success' && result.image_url) {
|
||||
const imgResponse = await fetch(result.image_url)
|
||||
const blob = await imgResponse.blob()
|
||||
const removedFile = new File([blob], 'removed-bg.png', { type: 'image/png' })
|
||||
return removedFile
|
||||
}
|
||||
} catch (parseError) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
} catch (error: any) {
|
||||
console.error('Remove background error:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user