介绍

需要将一张 Atlas 中的小图裁剪出来,首先想到的是使用 Photoshop,Photoshop 中有魔术手功能可以快速选中不规则图形,然后导出选中区域到文件。虽然手动操作可以完成,但是小图的数量过多,需要使用脚本进行批处理。

环境

  • Windows 10 22H2
  • Photoshop 2022

脚本

Photoshop 支持 Javascript 脚本进行处理,由于从未使用过 Photoshop 的 Javascript 编程,因此首先尝试询问 ChatGPT 如何导出选中区域为文件。

ChatGPT 给出的东西执行时有异常,由于 Photoshop 并没有一个直观的调试器,因此搜索了 StackOverflow 上现成的方案。

但是导出的图片大小过大,后来发现 selection.bounds 数组的前 4 项分别对应着 xMin, yMin, xMax, yMax,因此需要使用 xMax - xMin 与 yMax - yMin 获取实际图片的大小。

由于需要保存到文件,因此使用了 Math.random * 1000000 来获取随机数字保存,但更好的方案是获得当前时间信息作为文件名。

由于需要实现导出选中区域后删除的效果,取巧使用了选中区域的剪切功能进行删除;另外由于 app.activeDocument 在创建图片后会发生变化,需要在保存完成关闭图片后回到原图执行剪切操作,否则选中区域压根不存在。

绑定快捷键,可以在设置中为此脚本绑定一个快捷键,推荐使用 F1 之类的单个按键,按起来比较简单。

调试

Photoshop 有些情况下脚本执行出错时并没有任何提示,因此可以使用 alert() 方法输出调试信息。

文档

Photoshop 提供 Javascript 文档,可以直接查找到需要的 API 信息。

代码

将文件保存为

ExportSelectionToPNG.jsx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var doc = app.activeDocument;

var pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.compression = 9;

var hasSelection;
var docRef;
try {
    hasSelection = !!app.activeDocument.selection.bounds;
} catch (err) {
    hasSelection = false;
}

if (hasSelection) {
    app.activeDocument.selection.copy(true);

    var w = app.activeDocument.selection.bounds[2] - app.activeDocument.selection.bounds[0];
    var h = app.activeDocument.selection.bounds[3] - app.activeDocument.selection.bounds[1];
    docRef = app.documents.add(w, h);
    docRef.paste();
} else {
    docRef = app.activeDocument;
}

// var file = File.saveDialog("Export as PNG to...");
var randomInt = Math.floor(Math.random() * 1000000);
// alert(doc.path + "/Extracted_" + randomInt + ".png")
var file = new File(doc.path + "/Extracted_" + randomInt + ".png");
if (file && ((file.exists && confirm("Overwrite " + file +"?")) || !file.exists)) {
    docRef.saveAs(file, pngSaveOptions, !hasSelection, Extension.LOWERCASE);
    if (hasSelection) {
    docRef.close(SaveOptions.DONOTSAVECHANGES);
    }
}

try {
    app.activeDocument.selection.cut();
} catch (err) {
}