新增图片批量处理

This commit is contained in:
yinsx
2026-01-15 10:24:02 +08:00
parent 1de2ac8491
commit 943bf4bbd4
18 changed files with 1208 additions and 123 deletions

View File

@ -0,0 +1,138 @@
import { Jimp } from "jimp";
import path from "path";
import fs from "fs";
export async function compressImage(inputPath, quality = 80) {
const ext = path.extname(inputPath).toLowerCase();
const basename = path.basename(inputPath, ext);
const outputDir = path.join(path.dirname(inputPath), "compressed");
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const outputPath = path.join(outputDir, `${basename}${ext}`);
const image = await Jimp.read(inputPath);
await image.write(outputPath, { quality });
return outputPath;
}
export async function resizeImage(inputPath, sizes = [{ width: 800 }, { width: 400 }, { width: 200 }]) {
const ext = path.extname(inputPath).toLowerCase();
const basename = path.basename(inputPath, ext);
const outputDir = path.join(path.dirname(inputPath), "resized");
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const outputs = [];
for (const size of sizes) {
const outputPath = path.join(outputDir, `${basename}_${size.width}w${ext}`);
const image = await Jimp.read(inputPath);
image.resize({ w: size.width });
await image.write(outputPath);
outputs.push(outputPath);
}
return outputs;
}
export async function addWatermark(inputPath, watermarkPath, position = "southeast") {
const ext = path.extname(inputPath).toLowerCase();
const basename = path.basename(inputPath, ext);
const outputDir = path.join(path.dirname(inputPath), "watermarked");
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const outputPath = path.join(outputDir, `${basename}${ext}`);
const image = await Jimp.read(inputPath);
const watermark = await Jimp.read(watermarkPath);
watermark.resize({ w: Math.floor(image.bitmap.width * 0.2) });
const positions = {
northwest: { x: 10, y: 10 },
northeast: { x: image.bitmap.width - watermark.bitmap.width - 10, y: 10 },
southwest: { x: 10, y: image.bitmap.height - watermark.bitmap.height - 10 },
southeast: { x: image.bitmap.width - watermark.bitmap.width - 10, y: image.bitmap.height - watermark.bitmap.height - 10 }
};
const pos = positions[position];
image.composite(watermark, pos.x, pos.y);
await image.write(outputPath);
return outputPath;
}
export async function unifyBackground(inputPath, bgColor = 0xFFFFFFFF) {
const ext = path.extname(inputPath).toLowerCase();
const basename = path.basename(inputPath, ext);
const outputDir = path.join(path.dirname(inputPath), "background");
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const outputPath = path.join(outputDir, `${basename}${ext}`);
const image = await Jimp.read(inputPath);
const bg = new Jimp({ width: image.bitmap.width, height: image.bitmap.height, color: bgColor });
bg.composite(image, 0, 0);
await bg.write(outputPath);
return outputPath;
}
export async function cropWithPadding(inputPath, targetWidth, targetHeight, bgColor = 0xFFFFFFFF) {
const ext = path.extname(inputPath).toLowerCase();
const basename = path.basename(inputPath, ext);
const outputDir = path.join(path.dirname(inputPath), "cropped");
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const outputPath = path.join(outputDir, `${basename}_${targetWidth}x${targetHeight}${ext}`);
const image = await Jimp.read(inputPath);
const aspectRatio = image.bitmap.width / image.bitmap.height;
const targetRatio = targetWidth / targetHeight;
if (aspectRatio > targetRatio) {
image.resize({ w: targetWidth });
} else {
image.resize({ h: targetHeight });
}
const bg = new Jimp({ width: targetWidth, height: targetHeight, color: bgColor });
const x = Math.floor((targetWidth - image.bitmap.width) / 2);
const y = Math.floor((targetHeight - image.bitmap.height) / 2);
bg.composite(image, x, y);
await bg.write(outputPath);
return outputPath;
}
export async function processImage(file, operation, params) {
switch (operation) {
case "compress":
return await compressImage(file, params.quality);
case "resize":
return await resizeImage(file, params.sizes);
case "watermark":
return await addWatermark(file, params.watermarkPath, params.position);
case "background":
return await unifyBackground(file, params.bgColor);
case "crop":
return await cropWithPadding(file, params.width, params.height, params.bgColor);
default:
throw new Error(`未知操作: ${operation}`);
}
}