|
|
const sharp = require('sharp');
|
|
|
const fs = require('fs');
|
|
|
const path = require('path');
|
|
|
const { getInputDir } = require('../utils/index');
|
|
|
const { merge, cover } = require('../config/index');
|
|
|
|
|
|
//工作目录文件夹路径
|
|
|
const inputDir = getInputDir();
|
|
|
if (!inputDir) {
|
|
|
console.log('未执行ppt拼图功能,工作目录不存在');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//需要拼图的文件夹
|
|
|
const merageImgDir = `${inputDir}/img`;
|
|
|
const pdfDir = `${inputDir}/pdf`;
|
|
|
if (!merageImgDir) {
|
|
|
console.log('未执行ppt拼图功能,工作目录下的图片文件夹不存在');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//创建预览图输出文件夹
|
|
|
const previewDir = `${inputDir}/预览图`;
|
|
|
if (!fs.existsSync(previewDir)) {
|
|
|
fs.mkdirSync(previewDir);
|
|
|
}
|
|
|
|
|
|
async function stitchImages(imagePaths, { row, bgColor, width, margin, padding }, outputName) {
|
|
|
if (imagePaths.length >= 25) {
|
|
|
row = 3; // 超过25张图片时,每行最多3张图片
|
|
|
}
|
|
|
|
|
|
// 获取第一张图片的信息
|
|
|
const firstImageInfo = await sharp(imagePaths[0]).metadata();
|
|
|
const firstImageHeight = Math.floor((firstImageInfo.height / firstImageInfo.width) * width); // 根据比例计算高度
|
|
|
|
|
|
// 处理剩余的图片
|
|
|
const remainingImagesInfo = await Promise.all(
|
|
|
imagePaths.slice(1).map(async (imagePath) => {
|
|
|
const { data, info } = await sharp(imagePath)
|
|
|
.resize({ width: Math.floor((width - padding * 2 * row) / row), fit: 'inside' })
|
|
|
.toBuffer({ resolveWithObject: true });
|
|
|
return { data, info }; // 返回图片数据及其高度
|
|
|
})
|
|
|
);
|
|
|
|
|
|
const rows = Math.ceil(remainingImagesInfo.length / row); // 计算剩余图片的行数
|
|
|
const totalHeight = margin * 2 + (padding * 2 + firstImageHeight) + (remainingImagesInfo[0]?.info.height + padding * 2) * rows; // 总高度
|
|
|
const totalWidth = width + 2 * margin; // 总宽度,包括外层间隙
|
|
|
|
|
|
// 创建拼接后的图片
|
|
|
const outputImage = await sharp({
|
|
|
create: {
|
|
|
width: totalWidth,
|
|
|
height: totalHeight,
|
|
|
channels: 4,
|
|
|
background: bgColor,
|
|
|
},
|
|
|
})
|
|
|
.composite([
|
|
|
{
|
|
|
input: await sharp(imagePaths[0])
|
|
|
.resize(width - 2 * padding, firstImageHeight)
|
|
|
.toBuffer(),
|
|
|
top: margin + padding, // 第一张图片顶部留出外层间隙
|
|
|
left: margin + padding, // 第一张图片左侧留出外层间隙
|
|
|
},
|
|
|
...remainingImagesInfo.map(({ data, info }, index) => {
|
|
|
const currentRow = Math.floor(index / row);
|
|
|
const currentCol = index % row;
|
|
|
return {
|
|
|
input: data,
|
|
|
top: margin + padding + firstImageHeight + 2 * padding + currentRow * (info.height + padding * 2), // 计算纵向位置
|
|
|
left: margin + padding + currentCol * padding * 2 + currentCol * info.width, // 计算横向位置并取整
|
|
|
};
|
|
|
}),
|
|
|
])
|
|
|
.toFile(outputName);
|
|
|
|
|
|
console.log('拼接完成,输出文件为:', outputName);
|
|
|
}
|
|
|
|
|
|
const stitchPromises = []; // 存储所有拼图任务的 Promise
|
|
|
// 读取输入目录下所有文件夹,将每个文件夹内的图片拼图
|
|
|
fs.readdirSync(merageImgDir, { withFileTypes: true }).forEach((imgDir) => {
|
|
|
if (imgDir.isDirectory()) {
|
|
|
const inputPath = path.join(merageImgDir, imgDir.name);
|
|
|
const imagePaths = [];
|
|
|
fs.readdirSync(inputPath).forEach((file) => {
|
|
|
const ext = file.split('.').pop().toLowerCase();
|
|
|
if (cover.imgFormat.has(ext)) {
|
|
|
const imgPath = path.join(inputPath, file);
|
|
|
imagePaths.push(imgPath);
|
|
|
}
|
|
|
});
|
|
|
const sortImagePaths = imagePaths.sort((a, b) => {
|
|
|
// 提取数字部分
|
|
|
const numA = parseInt(a.match(/幻灯片(\d+)\.png/)[1], 10);
|
|
|
const numB = parseInt(b.match(/幻灯片(\d+)\.png/)[1], 10);
|
|
|
|
|
|
return numA - numB; // 按数字排序
|
|
|
});
|
|
|
const outputName = path.join(previewDir, `${imgDir.name}.jpg`);
|
|
|
stitchPromises.push(stitchImages(sortImagePaths, merge, outputName));
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 等待所有拼图任务完成
|
|
|
Promise.all(stitchPromises)
|
|
|
.then(() => {
|
|
|
console.log('所有拼图任务完成');
|
|
|
fs.rmSync(merageImgDir, { recursive: true, force: true });
|
|
|
fs.rmSync(pdfDir, { recursive: true, force: true });
|
|
|
console.log('删除img和pdf文件夹任务完成');
|
|
|
})
|
|
|
.catch((err) => {
|
|
|
console.error('发生错误:', err);
|
|
|
});
|