// ==UserScript== // @name 图片批量修改自定义尺寸和颜色的背景(树洞先生) // @namespace http://tampermonkey.net/ // @version 2.1 // @description 为图片批量添加自定义尺寸和颜色的背景,支持多种格式 // @author 树洞先生 // @match *://*/* // @license MIT // @grant none // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @downloadURL https://update.greasyfork.icu/scripts/549239/%E5%9B%BE%E7%89%87%E6%89%B9%E9%87%8F%E4%BF%AE%E6%94%B9%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B0%BA%E5%AF%B8%E5%92%8C%E9%A2%9C%E8%89%B2%E7%9A%84%E8%83%8C%E6%99%AF%28%E6%A0%91%E6%B4%9E%E5%85%88%E7%94%9F%29.user.js // @updateURL https://update.greasyfork.icu/scripts/549239/%E5%9B%BE%E7%89%87%E6%89%B9%E9%87%8F%E4%BF%AE%E6%94%B9%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B0%BA%E5%AF%B8%E5%92%8C%E9%A2%9C%E8%89%B2%E7%9A%84%E8%83%8C%E6%99%AF%28%E6%A0%91%E6%B4%9E%E5%85%88%E7%94%9F%29.meta.js // ==/UserScript== (function() { 'use strict'; // 创建工具界面 function createToolInterface() { // 检查是否已存在工具 if (document.getElementById('whiteBackgroundTool')) { return; } // 创建主容器 const toolContainer = document.createElement('div'); toolContainer.id = 'whiteBackgroundTool'; toolContainer.innerHTML = `
批量添加白色背景
📋 功能说明:
  • 创建自定义尺寸白色背景
  • 图片自动居中放置
  • 保持原图宽高比
  • 支持JPG、PNG、BMP等格式
⚙️ 自定义设置:
`; document.body.appendChild(toolContainer); // 绑定事件 bindEvents(); } // 绑定事件处理 function bindEvents() { const toolPanel = document.querySelector('#whiteBackgroundTool > div'); const closeBtn = document.getElementById('closeTool'); const imageInput = document.getElementById('imageInput'); const processBtn = document.getElementById('processImages'); const clearBtn = document.getElementById('clearImages'); const fileList = document.getElementById('fileList'); // 背景设置相关元素 const canvasWidth = document.getElementById('canvasWidth'); const canvasHeight = document.getElementById('canvasHeight'); const backgroundColor = document.getElementById('backgroundColor'); const backgroundColorText = document.getElementById('backgroundColorText'); let selectedFiles = []; // 关闭工具 closeBtn.addEventListener('click', () => { toolPanel.style.display = 'none'; }); // 颜色选择器和文本框同步 backgroundColor.addEventListener('input', (e) => { backgroundColorText.value = e.target.value; }); backgroundColorText.addEventListener('input', (e) => { const color = e.target.value; if (/^#[0-9A-Fa-f]{6}$/.test(color)) { backgroundColor.value = color; } }); // 文件选择 imageInput.addEventListener('change', (e) => { selectedFiles = Array.from(e.target.files); updateFileList(selectedFiles); processBtn.disabled = selectedFiles.length === 0; clearBtn.disabled = selectedFiles.length === 0; }); // 清空文件 clearBtn.addEventListener('click', () => { selectedFiles = []; imageInput.value = ''; updateFileList(selectedFiles); processBtn.disabled = true; clearBtn.disabled = true; }); // 处理图片 processBtn.addEventListener('click', () => { if (selectedFiles.length > 0) { const settings = { width: parseInt(canvasWidth.value) || 800, height: parseInt(canvasHeight.value) || 800, backgroundColor: backgroundColor.value || '#ffffff' }; processImages(selectedFiles, settings); } }); // 更新文件列表显示 function updateFileList(files) { if (files.length === 0) { fileList.style.display = 'none'; return; } fileList.style.display = 'block'; fileList.innerHTML = ` 已选择 ${files.length} 个文件:
${files.map((file, index) => `${index + 1}. ${file.name} (${(file.size / 1024 / 1024).toFixed(2)} MB)` ).join('
')} `; } } // 处理图片主函数 async function processImages(files, settings) { const progressContainer = document.getElementById('progressContainer'); const progressBar = document.getElementById('progressBar'); const progressText = document.getElementById('progressText'); const processBtn = document.getElementById('processImages'); // 显示进度条 progressContainer.style.display = 'block'; processBtn.disabled = true; const zip = new JSZip(); const processedImages = []; for (let i = 0; i < files.length; i++) { const file = files[i]; // 更新进度 const progress = ((i + 1) / files.length) * 100; progressBar.style.width = progress + '%'; progressText.textContent = `处理中... ${i + 1}/${files.length} - ${file.name}`; try { const processedImageBlob = await addWhiteBackground(file, settings); const fileName = getOutputFileName(file.name); zip.file(fileName, processedImageBlob); processedImages.push(fileName); } catch (error) { console.error(`处理文件 ${file.name} 时出错:`, error); } // 添加延迟,避免浏览器卡顿 await new Promise(resolve => setTimeout(resolve, 100)); } // 生成并下载ZIP文件 progressText.textContent = '生成下载文件...'; try { const zipBlob = await zip.generateAsync({type: 'blob'}); const timestamp = new Date().toISOString().slice(0, 19).replace(/[:-]/g, ''); const zipName = `processed_images_${settings.width}x${settings.height}_${timestamp}.zip`; saveAs(zipBlob, zipName); progressText.textContent = `✅ 完成!已处理 ${processedImages.length} 张图片`; setTimeout(() => { progressContainer.style.display = 'none'; processBtn.disabled = false; }, 3000); } catch (error) { console.error('生成ZIP文件出错:', error); progressText.textContent = '❌ 下载失败,请重试'; processBtn.disabled = false; } } // 为单张图片添加背景 function addWhiteBackground(file, settings) { return new Promise((resolve, reject) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = function() { // 设置画布尺寸 canvas.width = settings.width; canvas.height = settings.height; // 填充背景颜色 ctx.fillStyle = settings.backgroundColor; ctx.fillRect(0, 0, settings.width, settings.height); // 计算图片缩放比例(保持宽高比) const imgWidth = img.naturalWidth; const imgHeight = img.naturalHeight; const scale = Math.min(settings.width / imgWidth, settings.height / imgHeight); // 计算绘制尺寸和位置 const drawWidth = imgWidth * scale; const drawHeight = imgHeight * scale; const x = (settings.width - drawWidth) / 2; const y = (settings.height - drawHeight) / 2; // 绘制图片(居中) ctx.drawImage(img, x, y, drawWidth, drawHeight); // 转换为Blob canvas.toBlob(resolve, 'image/jpeg', 0.95); }; img.onerror = () => reject(new Error('图片加载失败')); // 读取文件 const reader = new FileReader(); reader.onload = (e) => { img.src = e.target.result; }; reader.onerror = () => reject(new Error('文件读取失败')); reader.readAsDataURL(file); }); } // 生成输出文件名 function getOutputFileName(originalName) { const lastDotIndex = originalName.lastIndexOf('.'); if (lastDotIndex === -1) { return `${originalName}_with_bg.jpg`; } const name = originalName.substring(0, lastDotIndex); return `${name}_with_bg.jpg`; } // 创建启动按钮 function createLaunchButton() { const button = document.createElement('div'); button.innerHTML = '🖼️'; button.style.cssText = ` position: fixed; top: 20px; right: 20px; width: 50px; height: 50px; background: #4CAF50; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 20px; z-index: 9999; box-shadow: 0 2px 10px rgba(0,0,0,0.3); transition: all 0.3s; `; button.addEventListener('mouseenter', () => { button.style.transform = 'scale(1.1)'; }); button.addEventListener('mouseleave', () => { button.style.transform = 'scale(1)'; }); button.addEventListener('click', () => { createToolInterface(); const toolPanel = document.querySelector('#whiteBackgroundTool > div'); toolPanel.style.display = toolPanel.style.display === 'none' ? 'block' : 'none'; }); document.body.appendChild(button); } // 等待页面加载完成后创建按钮 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createLaunchButton); } else { createLaunchButton(); } })();