PhotoShop脚本之Action Descriptor
最近研究PS工具,发现部分API不能直接获取到的图层信息,如描边色值、渐变色值等是可以通过PhotoShop的内置对象——Action Descriptor获取的。
1、PhotoShop脚本简介
PhotoShop脚本主要是基于JavaScript语言,以及PhotoShop的语言ExtendScript。这里不做赘述。
想要学习ExtendScript的小伙伴可以看看此官方文档:
https://wwwimages2.adobe.com/content/dam/acom/en/devnet/photoshop/pdfs/photoshop-cc-javascript-ref-2015.pdf
2、语言
PhotoShop支持几种脚本语言,Mac平台有AppleScript,Windows平台有VBScript,以及两个平台都支持的JavaScript。在这里我用的就是JavaScript语言,文件后缀是.jsx。
3、工具
PhotoShop脚本可以用任何文本编辑来写,这里推荐使用Adobe的IDE,叫Adobe ExtendScript Tookit,其支持断点调试,还可以通过Data Browser窗口查看对象的属性和方法。
4、语法
PhotoShop获取信息的一种方式是使用ExtendScript在文本对象模型DOM(Document Object Model)中访问和修改PSD源文件中对象的属性,直观而方便,但不能实现所有的PS操作。
PhotoShop获取信息的另一种方式是通过使用动作代理(ActionManager)的方式,可以实现比DOM更多的操作,但貌似不支持AppleScript。
动作代理主要类有ActionDescriptor,ActionReference,ActionList。
ActionDescriptor相当于一个存储属性和值的字典,
ActionList是一个存储相同属性的值的数组,
ActionReference存储一个action的引用
5、使用Action Descriptor
使用ActionManager看起来比使用ExtendScript要复杂许多,但好在Adobe有个监听Action的插件,下载地址:
Windows:http://download.adobe.com/pub/adobe/photoshop/win/13.x/Win_Scripting_Plug-In.zip
Mac:https://link.csdn.net/?target=http%3A%2F%2Fdownload.adobe.com%2Fpub%2Fadobe%2Fphotoshop%2Fmac%2F13.x%2FScripting_Plug_In_Release.dmg
下载解压后将ScriptListener.8li拷贝到Adobe Photoshop/Plug-ins/目录下即可。
重开PS,操作将会被记录在桌面的ScriptingListenerJS.log和ScriptingListenerVB.log中
切记不用时把该插件移除,需要时再复制到Plug-ins目录下,以免撑爆磁盘以及影响PS操作性能。
6、示例
这里举一个例子,获取文本图层的Outline色值
首先,下载安装好Adobe监听Action的插件,然后打开PS,新建一个空白文档,并新建一个文本层,输入文本:测试,选中文本图层
然后打开桌面的ScriptingListenerJS.log文本文档,把里面的内容删除并保存。
在PS中双击文本图层为其添加描边效果,然后打开ScriptingListenerJS.log
然后看到其操作代码:
通过查阅官方文档可以得知其对应的事件名,文档链接:https://wwwimages2.adobe.com/content/dam/acom/en/devnet/photoshop/pdfs/photoshop_scriptref_js.pdf
然后通过使用ExtendScript中的方法app. charIDToTypeID(charID)以及app.typeIDToStringID(id),可以得到对应Action的名字分别为(顺序由上到下)color,red,grain,blue,frameFX和layerEffects
然后获取选中图层的ActionDescriptor,使用前记得把文本图层设置为选中状态:
function getActiveLayerDescriptor()
{
var ref = new ActionReference();
ref.putEnumerated(char2Type("Lyr "), char2Type("Ordn"), char2Type("Trgt"));
return executeActionGet(ref);
}
然后判断是否存在刚才所说的节点,其中顺序需要反过来,由下到上
先在当前图层的ActionDescriptor查找名为layerEffects的子节点,若存在则判断在layerEffects的ActionDescriptor中是否存在frameFX节点,以此类推,直到找到color节点下的三个Double类型的变量,用ActionDescriptor.getDouble方法,分别获取red,grain,blue的值
7、完整代码:
function getID(str)
{
return app.stringIDToTypeID( str );
}
function getActiveLayerDescriptor()
{
var ref = new ActionReference();
ref.putEnumerated(char2Type("Lyr "), char2Type("Ordn"), char2Type("Trgt"));
return executeActionGet(ref);
}
function descToColorList( colorDesc )
{
return rgbTxt = [roundColor(colorDesc.getDouble(1382293536)),
roundColor(colorDesc.getDouble(1198681632)),
roundColor(colorDesc.getDouble(1114382368))];
}
function changeToHex(rgbTxt)
{
var value = "";
for(var i = 0, len = rgbTxt.length; i < len; i++)
{
var string = rgbTxt[i].toString(16);
if(string.length < 2)
{
string = "0" + string;
}
value += string;
}
return value;
}
function roundColor(x)
{
x = Math.round(x);
return (x > 255) ? 255 : x;
}
var currentDesc = getActiveLayerDescriptor();
var layerEffectsID = getID( "layerEffects" );
if(currentDesc.hasKey(layerEffectsID))
{
var layerEffectsDesc = currentDesc.getObjectValue(layerEffectsID);
var frameFXID = getID("frameFX");
if(layerEffectsDesc.hasKey(frameFXID)){
var frameFXDesc = layerEffectsDesc.getObjectValue(frameFXID);
var colorID = getID("color");
if(frameFXDesc.hasKey(colorID) && frameFXDesc.getBoolean(getID("enabled")))
{
var colorDesc = frameFXDesc.getObjectValue(colorID);
var rgbTxt = descToColorList(colorDesc);
var rgbHexTxt = changeToHex(rgbTxt);
alert(rgbHexTxt);
}
}
}