Open Upfunny opened 2 years ago
@Upfunny 这个之前没尝试过,我到时候帮你测试一下
@Upfunny 这个之前没尝试过,我到时候帮你测试一下
感谢~! 另外想到一个曲线救国的方式 把psd打开 需要的保留 不需要的全删 存储为psd 再新建一个psd 将这个删减后的psd导入 但会有一个问题 psd导入后,是smart object,如何转换为图层?
单凭ps api可能有点想不到,但是我们可以借助另一个模块:psd-tools 这是psd-tools的Getting started使用例:(将图层保存为图片)
from psd_tools import PSDImage
psd = PSDImage.open('example.psd')
psd.composite().save('example.png')
for layer in psd:
print(layer)
layer_image = layer.composite()
layer_image.save('%s.png' % layer.name)
然后,这是ps api的Import Image As Layer(将图片导入为图层)用例:
"""Import a image as a artLayer."""
# Import local modules
from photoshop import Session
with Session(action="new_document") as ps:
desc = ps.ActionDescriptor
desc.putPath(ps.app.charIDToTypeID("null"), "your/image/path")
event_id = ps.app.charIDToTypeID("Plc ") # `Plc` need one space in here.
ps.app.executeAction(ps.app.charIDToTypeID("Plc "), desc)
我们只要拼接上面两段代码即可:将要复制的psd存为临时文件(用tempfiles
模块),从这个psd中读出图层并存为临时文件,在ps中切换到目标psd,然后将前述临时图片导入。
顺便捉个虫:https://loonghao.github.io/photoshop-python-api/examples/#operation-layer-set 标题应为Operate Layer Set 第一行应为"""An example to show you how to operate layerSet."""
单凭ps api可能有点想不到,但是我们可以借助另一个模块:psd-tools 这是psd-tools的Getting started使用例:(将图层保存为图片)
from psd_tools import PSDImage psd = PSDImage.open('example.psd') psd.composite().save('example.png') for layer in psd: print(layer) layer_image = layer.composite() layer_image.save('%s.png' % layer.name)
然后,这是ps api的Import Image As Layer(将图片导入为图层)用例:
"""Import a image as a artLayer.""" # Import local modules from photoshop import Session with Session(action="new_document") as ps: desc = ps.ActionDescriptor desc.putPath(ps.app.charIDToTypeID("null"), "your/image/path") event_id = ps.app.charIDToTypeID("Plc ") # `Plc` need one space in here. ps.app.executeAction(ps.app.charIDToTypeID("Plc "), desc)
我们只要拼接上面两段代码即可:将要复制的psd存为临时文件(用
tempfiles
模块),从这个psd中读出图层并存为临时文件,在ps中切换到目标psd,然后将前述临时图片导入。
实际上不使用psd-tools 使用photoshop-python-api 也是可以实现的 筛选下图层名 不需要的隐藏掉 输出png就可以 但是我的需求中还需要对合成的psd进行二次编辑,所以直接保存为png肯定是不行的,目前是保存为psd,再在新的psd中导入之前导出的元素psd,缺点是导入后为智能对象,需要点击一下右键转为图层。目前在考虑是否结合PS里的动作进行处理
单凭ps api可能有点想不到,但是我们可以借助另一个模块:psd-tools 这是psd-tools的Getting started使用例:(将图层保存为图片)
from psd_tools import PSDImage psd = PSDImage.open('example.psd') psd.composite().save('example.png') for layer in psd: print(layer) layer_image = layer.composite() layer_image.save('%s.png' % layer.name)
然后,这是ps api的Import Image As Layer(将图片导入为图层)用例:
"""Import a image as a artLayer.""" # Import local modules from photoshop import Session with Session(action="new_document") as ps: desc = ps.ActionDescriptor desc.putPath(ps.app.charIDToTypeID("null"), "your/image/path") event_id = ps.app.charIDToTypeID("Plc ") # `Plc` need one space in here. ps.app.executeAction(ps.app.charIDToTypeID("Plc "), desc)
我们只要拼接上面两段代码即可:将要复制的psd存为临时文件(用
tempfiles
模块),从这个psd中读出图层并存为临时文件,在ps中切换到目标psd,然后将前述临时图片导入。实际上不使用psd-tools 使用photoshop-python-api 也是可以实现的 筛选下图层名 不需要的隐藏掉 输出png就可以 但是我的需求中还需要对合成的psd进行二次编辑,所以直接保存为png肯定是不行的,目前是保存为psd,再在新的psd中导入之前导出的元素psd,缺点是导入后为智能对象,需要点击一下右键转为图层。目前在考虑是否结合PS里的动作进行处理
请您仔细读,psd-tools可以分别存每一个图层。把一个psd中的一个图层存为png再导入另一个psd,和直接复制一个psd中的一个图层到另一个psd,这两个操作是等效的。
for layer in psd:
print(layer)
layer_image = layer.composite()
layer_image.save('%s.png' % layer.name)
psd-tools示例中的这段代码已经明显的不能再明显了
补充一下,对于一个文字图层,直接读取它的所有属性然后在另一个psd中创建一个一样的即可。
单凭ps api可能有点想不到,但是我们可以借助另一个模块:psd-tools 这是psd-tools的Getting started使用例:(将图层保存为图片)
from psd_tools import PSDImage psd = PSDImage.open('example.psd') psd.composite().save('example.png') for layer in psd: print(layer) layer_image = layer.composite() layer_image.save('%s.png' % layer.name)
然后,这是ps api的Import Image As Layer(将图片导入为图层)用例:
"""Import a image as a artLayer.""" # Import local modules from photoshop import Session with Session(action="new_document") as ps: desc = ps.ActionDescriptor desc.putPath(ps.app.charIDToTypeID("null"), "your/image/path") event_id = ps.app.charIDToTypeID("Plc ") # `Plc` need one space in here. ps.app.executeAction(ps.app.charIDToTypeID("Plc "), desc)
我们只要拼接上面两段代码即可:将要复制的psd存为临时文件(用
tempfiles
模块),从这个psd中读出图层并存为临时文件,在ps中切换到目标psd,然后将前述临时图片导入。实际上不使用psd-tools 使用photoshop-python-api 也是可以实现的 筛选下图层名 不需要的隐藏掉 输出png就可以 但是我的需求中还需要对合成的psd进行二次编辑,所以直接保存为png肯定是不行的,目前是保存为psd,再在新的psd中导入之前导出的元素psd,缺点是导入后为智能对象,需要点击一下右键转为图层。目前在考虑是否结合PS里的动作进行处理
请您仔细读,psd-tools可以分别存每一个图层。把一个psd中的一个图层存为png再导入另一个psd,和直接复制一个psd中的一个图层到另一个psd,这两个操作是等效的。
图层类型很多 文字图层 形状图层 智能对象等等,每个图层也可能包含各种效果,单纯的导入PNG和复制图层可不是等效
图层类型很多 文字图层 形状图层 智能对象等等,每个图层也可能包含各种效果,单纯的导入PNG和复制图层可不是等效
兵来将挡,水来土掩呗。ps api是可以读取图层属性的,像文字图层,形状图层这样的图层只要读取所有信息并在目标psd中创建一个一样的即可。
那我请教一下 望不吝赐教 一个文字图层 多行文字 部分文字字号不同,颜色不同,可能加粗倾斜下划线 如何使用api读取信息并新建一个一模一样的
你第一条回复的“目前在考虑是否结合PS里的动作进行处理”其实是个不错的思路。 我试了一下,录制了一个全选并复制的动作和一个粘贴的动作,尝试用这两个动作复制图层,可惜的是,复制的文字图层已经被自动转换成了图片,无法编辑。
那我请教一下 望不吝赐教 一个文字图层 多行文字 部分文字字号不同,颜色不同,可能加粗倾斜下划线 如何使用api读取信息并新建一个一模一样的
读文档:https://loonghao.github.io/photoshop-python-api/reference/photoshop/api/text_item/ 我其实不太明白为啥作者不写一份中文文档,明明他写英语都有语法错误(见上方捉虫)
那我请教一下 望不吝赐教 一个文字图层 多行文字 部分文字字号不同,颜色不同,可能加粗倾斜下划线 如何使用api读取信息并新建一个一模一样的
读文档:https://loonghao.github.io/photoshop-python-api/reference/photoshop/api/text_item/ 我其实不太明白为啥作者不写一份中文文档,明明他写英语都有语法错误(见上方捉虫)
英文更普适 语法无所谓 看的大差不差就行了 不必吹毛求疵 PS的api 有一些信息是获取不到的比如修改我说的这种复杂一些的文字图层,我是没有找到方法能读出更细的信息 基于图层的调整字号 调整文本是没问题 但调整第5-10个字的字号 或者文本 这种就不行了
那我请教一下 望不吝赐教 一个文字图层 多行文字 部分文字字号不同,颜色不同,可能加粗倾斜下划线 如何使用api读取信息并新建一个一模一样的
读文档:https://loonghao.github.io/photoshop-python-api/reference/photoshop/api/text_item/ 我其实不太明白为啥作者不写一份中文文档,明明他写英语都有语法错误(见上方捉虫)
英文更普适 语法无所谓 看的大差不差就行了 不必吹毛求疵 PS的api 有一些信息是获取不到的比如修改我说的这种复杂一些的文字图层,我是没有找到方法能读出更细的信息 基于图层的调整字号 调整文本是没问题 但调整第5-10个字的字号 或者文本 这种就不行了
这点你说的挺对,ps api确实没这种功能。 但是我发现ps的动作可以实现这种精确度的操作。 因此我有了这种思路:我可以先生成一个单一字体的文本,然后生成一个临时动作,再执行这个动作即可。 我试试能不能实现
@Upfunny 这个之前没尝试过,我到时候帮你测试一下
感谢~! 另外想到一个曲线救国的方式 把psd打开 需要的保留 不需要的全删 存储为psd 再新建一个psd 将这个删减后的psd导入 但会有一个问题 psd导入后,是smart object,如何转换为图层?
下面代码会把当前活动层的智能对象转换成普通层
# example 1
with Session() as ps:
js = """
var idplacedLayerConvertToLayers = stringIDToTypeID( "placedLayerConvertToLayers" );
executeAction( idplacedLayerConvertToLayers, undefined, DialogModes.NO );
"""
ps.app.doJavaScript(js)
# example 2
with Session() as ps:
descriptor = ps.ActionDescriptor
idplacedLayerConvertToLayers = ps.app.stringIDToTypeID("placedLayerConvertToLayers")
ps.app.executeAction(idplacedLayerConvertToLayers, descriptor)
结合动作做了一下解读,缺很多属性,有时间(指下周)再补
import photoshop.api as ps
from psaction import *
psapp = ps.Application()
xyt = psActionDescriptor(psapp, [ \ #作用未知
('putDouble', (psstr('xx'), 1.000000)), \
('putDouble', (psstr('xy'), 0.000000)), \
('putDouble', (psstr('yx'), 0.000000)), \
('putDouble', (psstr('yy'), 1.000000)), \
('putDouble', (psstr('tx'), 0.000000)), \
('putDouble', (psstr('ty'), 0.000000)), \
])
basexy = psActionDescriptor(psapp, [ \ #基底的xy坐标
('putDouble', (pschr('Hrzn'), 0.000000)), \
('putDouble', (pschr('Vrtc'), 0.000000)), \
])
blockstyle1 = psActionDescriptor(psapp, [ \
('putBoolean', (psstr('styleSheetHasParent'), True)), \
('putString', (psstr('fontPostScriptName'), """STKaiti""")), \ #字体PostScript名称
('putString', (pschr('FntN'), """STKaiti""")), \ #字体名称
('putString', (pschr('FntS'), """Regular""")), \ #字体样式
('putInteger', (pschr('Scrp'), 25)), \ #脚本,大部分字体的尺寸
('putInteger', (pschr('FntT'), 1)), \ #字体技术
('putUnitDouble', (pschr('Sz'), pschr('#Pnt'), 25.000000)), \ #本区域的字体尺寸
('putBoolean', (psstr('syntheticBold'), True)), \ #仿粗体
('putBoolean', (psstr('autoLeading'), False)), \ #自动行距
('putUnitDouble', (pschr('Ldng'), pschr('#Pnt'), 32.000000)), \ #行距
])
blockparastyle1 = psActionDescriptor(psapp, [ \
('putBoolean', (psstr('styleSheetHasParent'), True)), \
])
textShape = psActionDescriptor(psapp, [ \
('putEnumerated', (pschr('TEXT'), pschr('TEXT'), pschr('Pnt'))), \ #文本形状类型:点
('putEnumerated', (pschr('Ornt'), pschr('Ornt'), pschr('Hrzn'))), \ #文本方向:水平
('putObject', (pschr('Trnf'), pschr('Trnf'), xyt)), \ #调用上方xyt
('putInteger', (psstr('rowCount'), 1)), \ #列数
('putInteger', (psstr('columnCount'), 1)), \ #行数
('putBoolean', (psstr('rowMajorOrder'), True)), \ #是否带“使用行主顺序”
('putUnitDouble', (psstr('rowGutter'), pschr('#Pnt'), 0.000000)), \ #行装订线点数
('putUnitDouble', (psstr('columnGutter'), pschr('#Pnt'), 0.000000 )), \ #列装订线点数
('putUnitDouble', (pschr('Spcn'), pschr('#Pnt'), 0.000000 )), \ #列间距
('putEnumerated', (psstr('frameBaselineAlignment'), psstr('frameBaselineAlignment'), psstr('alignByAscent'))), \ #首行对齐:字母上缘
('putUnitDouble', (psstr('firstBaselineMinimum'), pschr('#Pnt'), 0.000000)), \ #首行最小高度点数
('putObject', (psstr('base'), pschr('Pnt'), basexy)), \ #关联基底配置
])
blockstyle1_range = psActionDescriptor(psapp, [ \
('putInteger', (pschr('From'), 0)), \ #从0起
('putInteger', (pschr('T'), 48)), \ #到48
('putObject', (pschr('TxtS'), pschr('TxtS'), blockstyle1)), \
])
blockparastyle1_range = psActionDescriptor(psapp, [ \
('putInteger', (pschr('From'), 0)), \
('putInteger', (pschr('T'), 48)), \
('putObject', (psstr('paragraphStyle'), psstr('paragraphStyle'), blockparastyle1)), \
])
warp = psActionDescriptor(psapp, [ \
('putEnumerated', (psstr('warpStyle'), psstr('warpStyle'), psstr('warpNone'))), \ #变形样式:无
('putDouble', (psstr('warpValue'), 0.000000)), \ #弯曲度
('putDouble', (psstr('warpPerspective'), 0.000000)), \ #垂直扭曲度
('putDouble', (psstr('warpPerspectiveOther'), 0.000000)), \ #水平扭曲度
('putEnumerated', (psstr('warpRotate'), pschr('Ornt'), pschr('Hrzn'))), \ #轴:水平
])
textShape_list = psActionList(psapp, [ \
('putObject', (psstr('textShape'), textShape)), \ #关联文本形状配置
])
blockstyle_list = psActionList(psapp, [ \
('putObject', (pschr('Txtt'), blockstyle1_range)), \ #关联样式范围配置
])
blockparastyle_list = psActionList(psapp, [ \
('putObject', (psstr('paragraphStyleRange'), blockparastyle1_range)), \ #关联段落样式范围配置
])
kerningrange_list = psActionList(psapp) #关联字距微调范围配置,遗憾的是本例无此配置
imgproperty = psActionDescriptor(psapp, [ \
('putString', (pschr('Txt'), """aaaaaaaaaaaaaaaakaaaa\raaaaaaaaaaaaaaaaaaasfgsdfg""")), \ #文本内容
('putObject', (psstr('warp'), psstr('warp'), warp)), \ #关联变形配置
('putEnumerated', (psstr('textGridding'), psstr('textGridding'), pschr('None'))), \ #文本网格:无
('putEnumerated', (pschr('Ornt'), pschr('Ornt'), pschr('Hrzn'))), \ #取向:水平
('putEnumerated', (pschr('AntA'), pschr('Annt'), pschr('AnSt'))), \ #消除锯齿:浑厚
('putList', (psstr('textShape'), textShape_list)), \ #关联文本形状列表
('putList', (pschr('Txtt'), blockstyle_list)), \ #关联样式范围列表
('putList', (psstr('paragraphStyleRange'), blockparastyle_list)), \ #关联段落样式范围列表
('putList', (psstr('kerningRange'), kerningrange_list)), \ #关联字距微调范围列表
])
imgaction = psActionDescriptorTop(psapp, [ \
('putEnumerated',(pschr('TxLr'), pschr('Ordn'), pschr('Trgt'))), \
])
imgaction.add_commands([ \
('putObject', (pschr('T'), pschr('TxLr'), imgproperty)), \
])
imgaction.execute(pschr('setd'))
注:此段代码无法运行,原因是单行写多行似乎不能在中间注释,测试的话复制上面没注释的即可
另外,经测试,可以删去部分代码,只设置部分属性,如:
import photoshop.api as ps from psaction import * psapp = ps.Application() blockstyle1 = psActionDescriptor(psapp, [ \ ('putBoolean', (psstr('styleSheetHasParent'), True)), \ ('putString', (psstr('fontPostScriptName'), """STKaiti""")), \ ('putString', (pschr('FntN'), """STKaiti""")), \ ('putString', (pschr('FntS'), """Regular""")), \ ('putInteger', (pschr('Scrp'), 25)), \ ('putInteger', (pschr('FntT'), 1)), \ ('putUnitDouble', (pschr('Sz'), pschr('#Pnt'), 25.000000)), \ ('putBoolean', (psstr('syntheticBold'), True)), \ ('putBoolean', (psstr('autoLeading'), False)), \ ('putUnitDouble', (pschr('Ldng'), pschr('#Pnt'), 32.000000)), \ ]) blockparastyle1 = psActionDescriptor(psapp, [ \ ('putBoolean', (psstr('styleSheetHasParent'), True)), \ ]) blockstyle1_range = psActionDescriptor(psapp, [ \ ('putInteger', (pschr('From'), 0)), \ ('putInteger', (pschr('T'), 48)), \ ('putObject', (pschr('TxtS'), pschr('TxtS'), blockstyle1)), \ ]) blockparastyle1_range = psActionDescriptor(psapp, [ \ ('putInteger', (pschr('From'), 0)), \ ('putInteger', (pschr('T'), 48)), \ ('putObject', (psstr('paragraphStyle'), psstr('paragraphStyle'), blockparastyle1)), \ ]) blockstyle_list = psActionList(psapp, [ \ ('putObject', (pschr('Txtt'), blockstyle1_range)), \ ]) blockparastyle_list = psActionList(psapp, [ \ ('putObject', (psstr('paragraphStyleRange'), blockparastyle1_range)), \ ]) kerningrange_list = psActionList(psapp) imgproperty = psActionDescriptor(psapp, [ \ ('putString', (pschr('Txt'), """aaaaaaaaaaaaaaaakaaaa\raaaaaaaaaaaaaa\raaaaasfgsdfg""")), \ ('putEnumerated', (pschr('Ornt'), pschr('Ornt'), pschr('Hrzn'))), \ ('putList', (pschr('Txtt'), blockstyle_list)), \ ('putList', (psstr('paragraphStyleRange'), blockparastyle_list)), \ ('putList', (psstr('kerningRange'), kerningrange_list)), \ ]) imgaction = psActionDescriptorTop(psapp, [ ('putEnumerated',(pschr('TxLr'), pschr('Ordn'), pschr('Trgt'))) ]) imgaction.add_commands([ ('putObject', (pschr('T'), pschr('TxLr'), imgproperty)) ]) imgaction.execute(pschr('setd'))
感觉胜利近在眼前了 上述动作只能设置文本的高级属性,并不能读取,但是看psd-tools的文档好像可以读取这些属性
话说怎么录制jsx? 我录制出来的动作是atn
话说怎么录制jsx? 我录制出来的动作是atn
安装ScriptingListener插件:https://helpx.adobe.com/photoshop/kb/downloadable-plugins-and-content.html#id_68969 注意:不用时请将它移出插件目录,以免录制的操作挤爆硬盘
通过这几天对ActionManager的研究,我发现了解决此问题的通用方案:
此段代码可以实现一个文字图层的全复制,将当前文档选中的图层复制到下一个文档选中的图层上(需要都是文字图层)
#参考:https://loonghao.github.io/photoshop-python-api/examples/#copy-and-paste
#导入模块,设置app
import photoshop.api as ps
import photoshop.api.action_manager as am
app = ps.Application()
def switch_doc(n): #ActionManager实现,向前/后切换n个文档,正数向后,负数向前
next_desc = ps.ActionDescriptor.load({'null': ['!ref', ReferenceKey('document', am.Offset+n)])
app.executeAction(am.str2id('select'), next_desc)
startRulerUnits = app.preferences.rulerUnits
app.preferences.rulerUnits = ps.Units.Inches
#这个reference会选择当前文字图层
curlyr_ref = ps.ActionReference.load(['!ref', ReferenceKey('textLayer', am.Enumerated('ordinal', 'targetEnum')))
curlyr_desc = app.executeActionGet(curlyr_ref)
curlyr_data = curlyr_desc.uget('textKey')
switch_doc(1) #切换到后一个文档
desc = ps.ActionDescriptor()
desc.uput('target', curlyr_ref)
desc.uput('to', curlyr_data)
app.executeAction(am.str2id('set'), desc)
if startRulerUnits != app.preferences.rulerUnits:
app.preferences.rulerUnits = startRulerUnits
完全复制,大小样式全部保留的那种
@Upfunny
Hi~ 发现你base 深圳 很高兴可以使用中文沟通 有个问题想请教一下~ 我几个psd 想从这几个psd中,分别复制 图层 或者 组 到一个新的psd内 想请教一下 怎么跨psd复制图层或组