好友
阅读权限10
听众
最后登录1970-1-1
|
5#
楼主|
sdds
发表于 2026-8-8 20:48
|楼主
// ============================================
// 批量替换PSD样机智能对象 - Photoshop 2020专用版
// 版本:3.1
// 日期:2026-08-07
// 兼容性:Photoshop 2020(21.x)及以上
// 功能:替换智能对象,等比缩放至最大填满
// 优化:每个样机跑完所有参考再保存,按样机名字新建文件夹
// ============================================
// 主函数
function batchReplaceMockup() {
// 1. 选择样机文件夹
var mockupFolder = Folder.selectDialog("请选择包含PSD样机文件的文件夹");
if (mockupFolder == null) return;
// 2. 选择素材图片文件夹
var imageFolder = Folder.selectDialog("请选择素材图片文件夹(JPEG/JPG/PNG)");
if (imageFolder == null) return;
// 3. 选择输出文件夹
var outputFolder = Folder.selectDialog("请选择输出文件夹");
if (outputFolder == null) return;
// 4. 获取文件列表
var mockupFiles = mockupFolder.getFiles(/\.(psd|PSD)$/);
if (mockupFiles.length === 0) {
alert("未找到PSD文件,请检查文件夹路径。");
return;
}
var imageFiles = imageFolder.getFiles(/\.(jpg|jpeg|png)$/i);
if (imageFiles.length === 0) {
alert("未找到JPEG/JPG/PNG格式的图片素材,请检查文件夹路径。");
return;
}
// 5. 设置选项
var exportFormat = "png";
var totalMockups = mockupFiles.length;
var totalImages = imageFiles.length;
var successCount = 0;
var errorCount = 0;
var errorLog = "";
// 关闭对话框提示,加快处理速度
app.displayDialogs = DialogModes.NO;
// 6. 遍历处理每个样机文件
for (var m = 0; m < totalMockups; m++) {
var mockupDoc = null;
try {
// 获取样机文件名(不含扩展名)
var mockupName = mockupFiles[m].name.replace(/\.(psd|PSD)$/, "");
// 创建样机对应的输出文件夹
var mockupOutputFolder = new Folder(outputFolder.fsName + "/" + mockupName);
if (!mockupOutputFolder.exists) {
mockupOutputFolder.create();
}
// 打开PSD文档
mockupDoc = app.open(mockupFiles[m]);
app.activeDocument = mockupDoc;
// 查找智能对象(2020稳定方式)
var targetLayer = findSmartObject2020(mockupDoc);
if (targetLayer == null) {
errorLog += "样机 " + mockupFiles[m].name + " 中未找到智能对象,跳过。\n";
errorCount += totalImages; // 该样机所有图片都失败
mockupDoc.close(SaveOptions.DONOTSAVECHANGES);
continue;
}
// 记录目标尺寸
var targetBounds = targetLayer.bounds;
var targetWidth = targetBounds[2].value - targetBounds[0].value;
var targetHeight = targetBounds[3].value - targetBounds[1].value;
// 对当前样机,依次处理所有参考图片
for (var i = 0; i < totalImages; i++) {
try {
var imageFile = imageFiles[i];
// 使用2020稳定的智能对象替换方法
replaceSmartObject2020(mockupDoc, targetLayer, imageFile);
// 获取替换后的智能对象
var smartObj = mockupDoc.activeLayer;
// 获取替换后图片的尺寸
var smartBounds = smartObj.bounds;
var smartWidth = smartBounds[2].value - smartBounds[0].value;
var smartHeight = smartBounds[3].value - smartBounds[1].value;
// 计算缩放比例(保持原图比例,填满目标区域)
var scaleX = targetWidth / smartWidth;
var scaleY = targetHeight / smartHeight;
var scale = Math.max(scaleX, scaleY);
// 应用缩放(2020稳定方式)
smartObj.resize(scale * 100, scale * 100, AnchorPosition.MIDDLECENTER);
// 保存输出文件到样机对应的文件夹
var outputFileName = mockupName + "_" +
imageFile.name.replace(/\.[^\.]+$/, "") + "." + exportFormat;
var outputFile = new File(mockupOutputFolder.fsName + "/" + outputFileName);
var saveOptions = new PNGSaveOptions();
saveOptions.compression = 9;
mockupDoc.saveAs(outputFile, saveOptions, true, Extension.LOWERCASE);
successCount++;
} catch (e) {
errorLog += "样机 " + mockupFiles[m].name + " 图片 " + imageFiles[i].name + " 处理失败: " + e.toString() + "\n";
errorCount++;
continue;
}
}
// 当前样机的所有图片处理完成,关闭样机文档
if (mockupDoc) {
mockupDoc.close(SaveOptions.DONOTSAVECHANGES);
mockupDoc = null;
}
} catch (e) {
errorLog += "样机 " + mockupFiles[m].name + " 处理失败: " + e.toString() + "\n";
errorCount++;
if (mockupDoc) {
try { mockupDoc.close(SaveOptions.DONOTSAVECHANGES); } catch (closeErr) {}
mockupDoc = null;
}
continue;
}
}
// 恢复对话框显示设置
app.displayDialogs = DialogModes.ALL;
// 输出结果
showResult(successCount, errorCount, totalMockups, totalImages, errorLog);
}
// 查找智能对象(2020稳定方式)
function findSmartObject2020(doc) {
for (var i = 0; i < doc.layers.length; i++) {
var layer = doc.layers[i];
try {
// 2020中智能对象的判断方式
if (layer.kind === LayerKind.SMARTOBJECT) {
return layer;
}
} catch (e) {
// 继续查找下一个图层
}
}
return null;
}
// 替换智能对象内容(2020稳定方式,使用ActionManager)
function replaceSmartObject2020(doc, targetLayer, imageFile) {
// 激活目标图层
doc.activeLayer = targetLayer;
// 使用ActionManager替换智能对象内容(2020稳定方式)
var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");
var desc = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc.putPath(idnull, new File(imageFile));
var idPgNm = charIDToTypeID("PgNm");
desc.putInteger(idPgNm, 1);
executeAction(idplacedLayerReplaceContents, desc, DialogModes.NO);
}
// 显示结果的辅助函数
function showResult(successCount, errorCount, totalMockups, totalImages, errorLog) {
var resultMsg = "批量套图完成!\n";
resultMsg += "═══════════════════════════\n";
resultMsg += "成功处理: " + successCount + " 张\n";
resultMsg += "错误数: " + errorCount + " 个\n";
resultMsg += "共处理 " + totalMockups + " 个样机\n";
resultMsg += "每个样机替换 " + totalImages + " 张图片\n";
resultMsg += "═══════════════════════════\n";
resultMsg += "脚本作者:Q12310061\n";
resultMsg += "版本:3.1\n";
resultMsg += "═══════════════════════════\n";
if (errorLog.length > 0) {
resultMsg += "\n错误日志:\n";
resultMsg += "───────────────────────\n";
resultMsg += errorLog;
}
alert(resultMsg);
}
// 运行主函数
try {
batchReplaceMockup();
} catch (e) {
alert("脚本运行出错: " + e.toString() + "\n\n请尝试以管理员身份运行Photoshop。");
} |
|