Photoshop 2020 批处理脚本开发思路
项目需求
用户需要一个Photoshop 2020脚本来批量处理图片,具体要求:
- 将所有图片调整为800×800像素的文档尺寸
- 关键要求:图片内容保持原始大小,不进行缩放或拉伸
- 图片在新画布中居中显示
- 转换为PNG格式输出
开发过程与思路演进
第一次尝试:使用 resizeImage() 方法
思路:直接缩放图片到800×800像素
javascript
doc.resizeImage(UnitValue(TARGET_WIDTH, "px"), UnitValue(TARGET_HEIGHT, "px"),
72, ResampleMethod.BICUBIC);
问题:这种方法会缩放图片内容,导致图片变形,不符合用户需求。
第二次尝试:使用 resizeCanvas() 方法
思路:改变画布大小而不缩放图片内容
javascript
doc.resizeCanvas(UnitValue(TARGET_WIDTH, "px"), UnitValue(TARGET_HEIGHT, "px"),
AnchorPosition.MIDDLECENTER);
问题:在某些情况下效果不稳定,可能与图片的原始尺寸和位置有关。
第三次尝试:创建新文档 + 复制粘贴
思路:
- 创建800×800的新文档
- 复制原图内容
- 粘贴到新文档
- 计算居中偏移并移动图层
javascript
// 创建新文档
var newDoc = app.documents.add(TARGET_WIDTH, TARGET_HEIGHT, 72, "temp_doc", NewDocumentMode.RGB);
// 复制粘贴
doc.selection.selectAll();
doc.selection.copy();
newDoc.paste();
// 计算居中位置
var offsetX = (TARGET_WIDTH - currentWidth) / 2;
var offsetY = (TARGET_HEIGHT - currentHeight) / 2;
pastedLayer.translate(offsetX, offsetY);
问题:translate()方法的定位计算有误,导致显示的是放大的局部内容而不是完整图片。
最终解决方案:使用 Place 动作
核心思路:模拟用户手动拖拽图片到新文档的操作
关键技术点
-
使用Photoshop的Place动作
javascriptvar idPlc = charIDToTypeID("Plc "); var desc = new ActionDescriptor(); desc.putPath(charIDToTypeID("null"), file); desc.putBoolean(charIDToTypeID("Lnkd"), false); executeAction(idPlc, desc);
-
精确的居中计算
javascript// 获取图层实际边界 var layerBounds = currentLayer.bounds; var layerWidth = layerBounds[2] - layerBounds[0]; var layerHeight = layerBounds[3] - layerBounds[1]; // 计算画布和图层的中心点 var centerX = TARGET_WIDTH / 2; var centerY = TARGET_HEIGHT / 2; var layerCenterX = layerBounds[0] + layerWidth / 2; var layerCenterY = layerBounds[1] + layerHeight / 2; // 计算需要移动的距离 var deltaX = centerX - layerCenterX; var deltaY = centerY - layerCenterY;
为什么最终方案有效
1. Place动作的优势
- 保持原始尺寸:Place动作导入图片时保持原始像素尺寸
- 模拟手动操作:这正是用户手动拖拽图片时Photoshop内部执行的操作
- 兼容性好:适用于各种图片格式和尺寸
2. 精确的边界计算
- 实际边界 :通过
currentLayer.bounds
获取图层的实际边界坐标 - 中心点计算:分别计算画布中心和图层中心
- 偏移量:计算两个中心点的差值作为移动距离
3. 处理流程
原始图片 → 创建800×800新文档 → Place导入图片 → 计算居中位置 → 移动图层 → 合并图层 → 保存PNG
技术细节
支持的图片格式
javascript
var supportedFormats = /\.(jpg|jpeg|png|gif|tiff|tif|bmp|psd)$/i;
PNG保存选项
javascript
var pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.interlaced = false; // 不使用隔行扫描
pngSaveOptions.compression = 6; // 压缩级别(0-9,6为平衡)
错误处理
- 完善的try-catch机制
- 确保文档正确关闭
- 处理结果统计和反馈
最终效果
✅ 文档尺寸 :精确的800×800像素
✅ 图片内容 :保持原始大小,无缩放变形
✅ 位置 :完美居中显示
✅ 格式 :高质量PNG输出
✅ 批量处理:自动处理文件夹中的所有图片
学到的经验
- 理解用户真实需求:"改变像素尺寸但不缩放内容"这个需求需要仔细分析
- 模拟手动操作:最有效的自动化往往是对手动操作的精确模拟
- 精确的数学计算:居中定位需要准确的坐标计算
- 迭代改进:通过多次尝试和用户反馈不断优化方案
- Photoshop脚本的复杂性:不同方法在不同情况下可能有不同的表现
脚本文件
最终脚本文件:photoshop2020_batch_resize.jsx
使用方法:
- 将需要处理的图片放在
G:/input
文件夹中 - 在Photoshop 2020中运行脚本:文件 → 脚本 → 浏览
- 处理后的PNG文件将保存在
G:/input/output
文件夹中
下面是源码:
jsx
// Photoshop 2020 批处理脚本
// 功能:将所有照片调整为800x800像素文档(图片内容保持原始大小,居中显示)并转换为PNG格式
// 适用版本:Adobe Photoshop 2020
// 设置输入和输出文件夹
var inputFolder = Folder("G:/input/photos");
var outputFolder = Folder("G:/input/output");
// 创建输出文件夹(如果不存在)
if (!outputFolder.exists) {
outputFolder.create();
}
// 支持的图片格式
var supportedFormats = /\.(jpg|jpeg|png|gif|tiff|tif|bmp|psd)$/i;
var files = inputFolder.getFiles(supportedFormats);
// 设置目标尺寸
var TARGET_WIDTH = 800;
var TARGET_HEIGHT = 800;
// 处理计数器
var processedCount = 0;
var skippedCount = 0;
var errorCount = 0;
// 主处理循环
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file instanceof File) {
var doc = null;
try {
// 打开文档
doc = app.open(file);
// 获取原始文件名(不含扩展名)
var originalName = doc.name.replace(/\.[^.]+$/, "");
// 获取文档当前尺寸(转换为像素)
var currentWidth = doc.width.as('px');
var currentHeight = doc.height.as('px');
// 创建一个新的800x800像素文档
var newDoc = app.documents.add(TARGET_WIDTH, TARGET_HEIGHT, 72, "temp_doc", NewDocumentMode.RGB);
// 将原图作为智能对象放置到新文档中
app.activeDocument = newDoc;
var placedLayer = newDoc.artLayers.add();
// 使用place方法导入图片,这样可以保持原始尺寸
var idPlc = charIDToTypeID("Plc ");
var desc = new ActionDescriptor();
desc.putPath(charIDToTypeID("null"), file);
desc.putBoolean(charIDToTypeID("Lnkd"), false);
executeAction(idPlc, desc);
// 获取当前图层(放置的图片)
var currentLayer = newDoc.activeLayer;
// 计算居中位置
var layerBounds = currentLayer.bounds;
var layerWidth = layerBounds[2] - layerBounds[0];
var layerHeight = layerBounds[3] - layerBounds[1];
var centerX = TARGET_WIDTH / 2;
var centerY = TARGET_HEIGHT / 2;
var layerCenterX = layerBounds[0] + layerWidth / 2;
var layerCenterY = layerBounds[1] + layerHeight / 2;
var deltaX = centerX - layerCenterX;
var deltaY = centerY - layerCenterY;
// 移动图层到居中位置
currentLayer.translate(deltaX, deltaY);
// 合并所有图层
newDoc.flatten();
// 关闭原文档
doc.close(SaveOptions.DONOTSAVECHANGES);
// 将新文档设为当前处理文档
doc = newDoc;
// 设置输出文件路径
var outputFile = new File(outputFolder.fsName + "/" + originalName + ".png");
// 配置PNG保存选项
var pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.interlaced = false; // 不使用隔行扫描
pngSaveOptions.compression = 6; // 压缩级别(0-9,6为平衡)
// 保存为PNG格式
doc.saveAs(outputFile, pngSaveOptions, true, Extension.LOWERCASE);
// 关闭文档,不保存更改
doc.close(SaveOptions.DONOTSAVECHANGES);
processedCount++;
} catch (error) {
// 错误处理
errorCount++;
// 确保文档被正确关闭
if (doc !== null) {
try {
doc.close(SaveOptions.DONOTSAVECHANGES);
} catch (closeError) {
// 忽略关闭时的错误
}
}
// 可选:记录错误信息(在实际使用中可以启用)
// alert("处理文件时出错: " + file.name + "\n错误信息: " + error.message);
}
}
}
// 显示处理结果摘要
var summaryMessage = "批处理完成!\n\n" +
"成功处理: " + processedCount + " 个文件\n" +
"跳过处理: " + skippedCount + " 个文件(尺寸不足)\n" +
"处理错误: " + errorCount + " 个文件\n\n" +
"输出文件夹: " + outputFolder.fsName;
alert(summaryMessage);
// 脚本执行完毕
- 保存为jsx文件。
- 运行命令:
Start-Process "F:\PS-2020\PS所在路径\Photoshop.exe" -ArgumentList "-r", "G:\脚本所在路径\photoshop2020_batch_resize.jsx"