feat: ppt广告图处理
parent
5c8d2b3236
commit
fd21ca5e77
@ -0,0 +1,52 @@
|
|||||||
|
import os
|
||||||
|
import win32com.client
|
||||||
|
from config import Config
|
||||||
|
|
||||||
|
|
||||||
|
# 初始化PPT
|
||||||
|
def init_powerpoint():
|
||||||
|
powerpoint = win32com.client.Dispatch("PowerPoint.Application")
|
||||||
|
powerpoint.Visible = 1
|
||||||
|
return powerpoint
|
||||||
|
|
||||||
|
|
||||||
|
# PPT转png
|
||||||
|
def ppt2png(pptFileName, downLoad_path, powerpoint):
|
||||||
|
try:
|
||||||
|
ppt_path = os.path.abspath(pptFileName)
|
||||||
|
ppt = powerpoint.Presentations.Open(ppt_path)
|
||||||
|
|
||||||
|
# 保存为图片
|
||||||
|
img_path = os.path.abspath(downLoad_path + ".png")
|
||||||
|
ppt.SaveAs(img_path, 18) # 18 为 PNG 格式
|
||||||
|
|
||||||
|
# 关闭打开的ppt文件
|
||||||
|
ppt.Close()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"PPT转png失败: {pptFileName}")
|
||||||
|
else:
|
||||||
|
print("PPT转png成功", pptFileName)
|
||||||
|
|
||||||
|
|
||||||
|
# 批量转换PPT文件
|
||||||
|
def ppt_to_png(filename, ad_img_path):
|
||||||
|
powerpoint = init_powerpoint()
|
||||||
|
|
||||||
|
if filename.endswith(".ppt") or filename.endswith(".pptx"):
|
||||||
|
downLoad_path = os.path.join(ad_img_path, os.path.splitext(os.path.basename(filename))[0])
|
||||||
|
ppt2png(filename, downLoad_path, powerpoint)
|
||||||
|
|
||||||
|
powerpoint.Quit() # 退出PowerPoint
|
||||||
|
|
||||||
|
|
||||||
|
# 示例用法
|
||||||
|
if __name__ == "__main__":
|
||||||
|
filename = Config.EXPORT_AD_PPT_PATH
|
||||||
|
# 获取文件的目录
|
||||||
|
directory = os.path.dirname(filename)
|
||||||
|
# 定义 adImg 文件夹的路径
|
||||||
|
ad_img_path = os.path.join(directory, 'adImg')
|
||||||
|
# 创建输出文件夹
|
||||||
|
os.makedirs(ad_img_path, exist_ok=True)
|
||||||
|
|
||||||
|
ppt_to_png(filename, ad_img_path)
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
const sharp = require('sharp');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { exportAdImg, cover } = require('../config/index');
|
||||||
|
const { getDesktopPath } = require('../utils/index');
|
||||||
|
|
||||||
|
if (!exportAdImg.pptPath) {
|
||||||
|
console.log('未执行广告图片拼图功能,文件路径不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stitchImages(imagePaths, outputName) {
|
||||||
|
// 处理剩余的图片
|
||||||
|
const imagesInfo = await Promise.all(
|
||||||
|
imagePaths.map(async (imagePath) => {
|
||||||
|
const { data, info } = await sharp(imagePath).toBuffer({ resolveWithObject: true });
|
||||||
|
return { data, info }; // 返回图片数据及其高度
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const { width, height } = imagesInfo[0]?.info;
|
||||||
|
|
||||||
|
// 创建拼接后的图片
|
||||||
|
const outputImage = await sharp({
|
||||||
|
create: {
|
||||||
|
width,
|
||||||
|
height: height * imagesInfo.length,
|
||||||
|
channels: 4,
|
||||||
|
background: { r: 255, g: 255, b: 255 },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.composite([
|
||||||
|
...imagesInfo.map(({ data }, index) => {
|
||||||
|
return {
|
||||||
|
input: data,
|
||||||
|
top: index * height,
|
||||||
|
left: 0,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
.toFile(outputName);
|
||||||
|
|
||||||
|
console.log('广告图拼接完成,输出文件为:', outputName);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handle_ad_img() {
|
||||||
|
// 获取文件的目录
|
||||||
|
const directory = path.dirname(exportAdImg.pptPath);
|
||||||
|
// 定义 adImg 文件夹的路径
|
||||||
|
const adImgPath = path.join(directory, 'adImg');
|
||||||
|
const imagePaths = [];
|
||||||
|
fs.readdirSync(adImgPath).forEach((file) => {
|
||||||
|
const ext = file.split('.').pop().toLowerCase();
|
||||||
|
if (cover.imgFormat.has(ext)) {
|
||||||
|
const imgPath = path.join(adImgPath, 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 desktopPath = getDesktopPath();
|
||||||
|
for (let i = 0; i < sortImagePaths.length; i += exportAdImg.column) {
|
||||||
|
// 获取当前分组
|
||||||
|
const chunkImagePaths = sortImagePaths.slice(i, i + exportAdImg.column);
|
||||||
|
// 计算当前分组的索引
|
||||||
|
const groupIndex = Math.floor(i / exportAdImg.column);
|
||||||
|
const outputName = path.join(desktopPath, `${groupIndex + 1}.jpg`);
|
||||||
|
await stitchImages(chunkImagePaths, outputName);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('所有广告图拼接完毕');
|
||||||
|
fs.rmSync(adImgPath, { recursive: true, force: true });
|
||||||
|
console.log('删除adImg文件夹任务完成');
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_ad_img();
|
||||||
Loading…
Reference in New Issue