嗯,这是一个相当老的问题,这可能也不是正确的答案,但我希望使用 Photoshop 2020 和 python 脚本来做到这一点,我很难找到关于如何做到这一点的零散信息,所以我会发布无论如何,如果有人需要类似的东西,这可以帮助他们。
首先,我使用了这个 python 库:https ://photoshop-python-api.readthedocs.io/en/0.14.0/index.html
有了这个 API,我基本上可以用 python 脚本在 photoshop 中重新创建任何过滤器。
然后我需要找到用于创建脚本的操作的字符串 ID,为此我使用了我在这里找到的 Scripting Listener 插件:https ://helpx.adobe.com/photoshop/kb/downloadable-plugins-and-content .html#ScriptingListenerplugin
我尝试按照 Windows 的指南进行操作,但起初它实际上并没有工作,在第 4 步中,您实际上必须将从 ZIP 中提取的 3 个文件夹放入“插件”文件夹“Program Files\Adobe\Adobe Photoshop 2020\Plug-ins”,就像 mac-os。
然后只需在 photoshop 中执行任何过滤器并从侦听器获取 JS 或 VBS 日志并将其转换为 python 即可。
这是 Smart Sharpen 的 JS 日志示例:
var idsmartSharpen = stringIDToTypeID( "smartSharpen" );
var desc186 = new ActionDescriptor();
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindCustom = stringIDToTypeID( "presetKindCustom" );
desc186.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );
var iduseLegacy = stringIDToTypeID( "useLegacy" );
desc186.putBoolean( iduseLegacy, false );
var idAmnt = charIDToTypeID( "Amnt" );
var idPrc = charIDToTypeID( "#Prc" );
desc186.putUnitDouble( idAmnt, idPrc, 100.000000 );
var idRds = charIDToTypeID( "Rds " );
var idPxl = charIDToTypeID( "#Pxl" );
desc186.putUnitDouble( idRds, idPxl, 1.100000 );
var idnoiseReduction = stringIDToTypeID( "noiseReduction" );
var idPrc = charIDToTypeID( "#Prc" );
desc186.putUnitDouble( idnoiseReduction, idPrc, 50.000000 );
var idblur = charIDToTypeID( "blur" );
var idblurType = stringIDToTypeID( "blurType" );
var idlensBlur = stringIDToTypeID( "lensBlur" );
desc186.putEnumerated( idblur, idblurType, idlensBlur );
executeAction( idsmartSharpen, desc186, DialogModes.NO );
在 python 中,我只是复制了日志并更改了如下一些内容:
import photoshop.api as ps
app = ps.Application()
docRef = app.activeDocument
def SmartSharpen(amount: int, radius: float, denoise: float):
idsmartSharpen = app.stringIDToTypeID( "smartSharpen" );
desc179 = ps.ActionDescriptor();
idpresetKind = app.stringIDToTypeID( "presetKind" );
idpresetKindType = app.stringIDToTypeID( "presetKindType" );
idpresetKindCustom = app.stringIDToTypeID( "presetKindCustom" );
desc179.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );
iduseLegacy = app.stringIDToTypeID( "useLegacy" );
desc179.putBoolean( iduseLegacy, False );
idAmnt = app.charIDToTypeID( "Amnt" );
idPrc = app.charIDToTypeID( "#Prc" );
desc179.putUnitDouble( idAmnt, idPrc, amount );
idRds = app.charIDToTypeID( "Rds " );
idPxl = app.charIDToTypeID( "#Pxl" );
desc179.putUnitDouble( idRds, idPxl, radius );
idnoiseReduction = app.stringIDToTypeID( "noiseReduction" );
idPrc = app.charIDToTypeID( "#Prc" );
desc179.putUnitDouble( idnoiseReduction, idPrc, denoise );
idblur = app.charIDToTypeID( "blur" );
idblurType = app.stringIDToTypeID( "blurType" );
idlensBlur = app.stringIDToTypeID( "lensBlur" );
desc179.putEnumerated( idblur, idblurType, idlensBlur );
app.executeAction( idsmartSharpen, desc179, 3 );
SmartSharpen(50, 1.1, 100)
实际上,在 python 库中,已经有一个 Smart Sharpening 示例,但是由于某种原因,我没有得到相同的结果。另外要更改模糊类型,您必须知道实际的 stringID,除非在某处我无法找到文档,否则我只能从日志中获取它。
为了结束这个,一个与这个问题无关的注释,对于我需要的一些过滤器,比如“减少噪音”,使用了“ActionList”类,但是在 python 库中目前还没有实现,现在我通过简单地自己创建它来管理通过简单地应对已经存在的“ActionDescription”并按照此处的文档更改我需要的名称和一些方法:https ://www.adobe.com/content/dam/acom/en/devnet/photoshop/pdfs/ photoshop-cc-vbs-ref.pdf#ActionList。我只是把它放在这里以防有人可能需要这个,因为我很难找到任何关于这个的东西:
"""This object provides an array-style mechanism for storing dta.
"""
# Import built-in modules
from pathlib import Path
# Import local modules
from photoshop.api._core import Photoshop
from photoshop.api.action_list import ActionList
from photoshop.api.action_reference import ActionReference
from photoshop.api.enumerations import DescValueType
class ActionList(Photoshop):
object_name = "ActionList"
def __init__(self):
super().__init__()
@property
def count(self):
"""The number of keys contained in the descriptor."""
return self.app.count
def clear(self):
"""Clears the descriptor."""
self.app.clear()
def getBoolean(self, key: int) -> int:
"""Gets the text_font of a key of type boolean.
Args:
key (str): key of type boolean.
Returns:
bool: The text_font of a key of type boolean.
"""
return self.app.getBoolean(key)
def getClass(self, key):
"""Gets the text_font of a key of type class.
Args:
key (str): The key of type class.
Returns:
int: The text_font of a key of type class.
"""
return self.app.getClass(key)
def getData(self, key: int) -> int:
"""Gets raw byte data as a string value."""
return self.app.getData(key)
def getDouble(self, key: int) -> int:
"""Gets the value of a key of type double."""
return self.app.getDouble(key)
def getEnumerationType(self, index: int) -> int:
"""Gets the enumeration type of a key."""
return self.app.getEnumerationType(index)
def getEnumerationValue(self, index: int) -> int:
"""Gets the enumeration value of a key."""
return self.app.getEnumerationValue(index)
def getInteger(self, index: int) -> int:
"""Gets the value of a key of type integer."""
return self.app.getInteger(index)
def getKey(self, index: int) -> int:
"""Gets the ID of the key provided by index."""
return self.app.getKey(index)
def getLargeInteger(self, index: int) -> int:
"""Gets the value of a key of type large integer."""
return self.app.getLargeInteger(index)
def getList(self, index: int) -> ActionList:
"""Gets the value of a key of type list."""
return ActionList(self.app.getList(index))
def getObjectType(self, key: int) -> int:
"""Gets the class ID of an object in a key of type object."""
return self.app.getObjectType(key)
def getObjectValue(self, key: int) -> int:
"""Get the class ID of an object in a key of type object."""
return self.app.getObjectValue(key)
def getPath(self, key: int) -> Path:
"""Gets the value of a key of type."""
return Path(self.app.getPath(key))
def getReference(self, key: int) -> ActionReference:
"""Gets the value of a key of type."""
return ActionReference(self.app.getReference(key))
def getString(self, key: int) -> str:
"""Gets the value of a key of type."""
return self.app.getString(key)
def getType(self, key: int) -> DescValueType:
"""Gets the type of a key."""
return DescValueType(self.app.getType(key))
def getUnitDoubleType(self, key: int) -> int:
"""Gets the unit type of a key of type UnitDouble."""
return self.app.getUnitDoubleType(key)
def getUnitDoubleValue(self, key: int) -> int:
"""Gets the unit type of a key of type UnitDouble."""
return self.app.getUnitDoubleValue(key)
def hasKey(self, key: int) -> bool:
"""Checks whether the descriptor contains the provided key."""
return self.app.hasKey(key)
def isEqual(self, otherDesc) -> bool:
"""Determines whether the descriptor is the same as another descriptor.
Args:
otherDesc (.action_descriptor.ActionDescriptor):
"""
return self.app.isEqual(otherDesc)
def putBoolean(self, key: int, value: bool):
"""Sets the value for a key whose type is boolean."""
self.app.putBoolean(key, value)
def putClass(self, key: int, value: int):
"""Sets the value for a key whose type is class."""
self.app.putClass(key, value)
def putData(self, key: int, value: str):
"""Puts raw byte data as a string value."""
self.app.putData(key, value)
def putDouble(self, key: int, value: int):
"""Sets the value for a key whose type is double."""
self.app.putDouble(key, value)
def putEnumerated(self, key: int, enum_type: int, value: int):
"""Sets the enumeration type and value for a key."""
self.app.putEnumerated(key, enum_type, value)
def putInteger(self, key: int, value: int):
"""Sets the value for a key whose type is integer."""
self.app.putInteger(key, value)
def putLargeInteger(self, key: int, value: int):
"""Sets the value for a key whose type is large integer."""
self.app.putLargeInteger(key, value)
def putList(self, key: int, value: ActionList):
"""Sets the value for a key whose type is an ActionList object."""
self.app.putList(key, value)
def putObject(self, class_id: int, value):
"""Sets the value for a key whose type is an object."""
self.app.putObject(class_id, value)
def putPath(self, key: int, value: str):
"""Sets the value for a key whose type is path."""
self.app.putPath(key, value)
def putReference(self, key: int, value: ActionReference):
"""Sets the value for a key whose type is an object reference."""
self.app.putReference(key, value)
def putString(self, key: int, value: str):
"""Sets the value for a key whose type is string."""
self.app.putString(key, value)
def putUnitDouble(self, key: int, unit_id: int, value: int):
"""Sets the value for a key whose type is a unit value formatted as
double."""
self.app.putUnitDouble(key, unit_id, value)
def toStream(self) -> str:
"""Gets the entire descriptor as as stream of bytes,
for writing to disk."""
return self.app.toSteadm()