PS2020,将所有图片不剪切,调整为800×800像素的文档尺寸。

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);

问题:在某些情况下效果不稳定,可能与图片的原始尺寸和位置有关。

第三次尝试:创建新文档 + 复制粘贴

思路

  1. 创建800×800的新文档
  2. 复制原图内容
  3. 粘贴到新文档
  4. 计算居中偏移并移动图层
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 动作

核心思路:模拟用户手动拖拽图片到新文档的操作

关键技术点
  1. 使用Photoshop的Place动作

    javascript 复制代码
    var idPlc = charIDToTypeID("Plc ");
    var desc = new ActionDescriptor();
    desc.putPath(charIDToTypeID("null"), file);
    desc.putBoolean(charIDToTypeID("Lnkd"), false);
    executeAction(idPlc, desc);
  2. 精确的居中计算

    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输出

批量处理:自动处理文件夹中的所有图片

学到的经验

  1. 理解用户真实需求:"改变像素尺寸但不缩放内容"这个需求需要仔细分析
  2. 模拟手动操作:最有效的自动化往往是对手动操作的精确模拟
  3. 精确的数学计算:居中定位需要准确的坐标计算
  4. 迭代改进:通过多次尝试和用户反馈不断优化方案
  5. Photoshop脚本的复杂性:不同方法在不同情况下可能有不同的表现

脚本文件

最终脚本文件:photoshop2020_batch_resize.jsx

使用方法:

  1. 将需要处理的图片放在 G:/input 文件夹中
  2. 在Photoshop 2020中运行脚本:文件 → 脚本 → 浏览
  3. 处理后的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"
相关推荐
sjin1 小时前
React源码 - 大名鼎鼎的Fiber
前端
子兮曰1 小时前
🚀从单体到Monorepo:四川省xxx协会官网架构重生记
前端·next.js·turbopack
白水清风2 小时前
CI/CD学习记录(基于GitLab)
前端·自动化运维·前端工程化
齐杰拉2 小时前
源码精读:拆解 ChatGPT 打字机效果背后的数据流水线
前端·chatgpt
文心快码BaiduComate2 小时前
“一人即团队”——一句话驱动智能体团队
前端·后端·程序员
我是ed2 小时前
# vue3 实现前端生成水印效果
前端
IAtlantiscsdn2 小时前
Redis7底层数据结构解析
前端·数据结构·bootstrap
小枫编程2 小时前
Spring Boot 与前端文件上传跨域问题:Multipart、CORS 与网关配置
前端·spring boot·后端
uhakadotcom3 小时前
入门教程:如何编写一个chrome浏览器插件(以jobleap.cn收藏夹为例)
前端·javascript·面试