[python庫]psd文件操作庫--psd_tools

psd-tools

psd-tools是處理Photoshop的psd文件的python庫。

源碼地址:https://github.com/psd-tools/psd-tools
文檔地址:https://psd-tools.readthedocs.io/en/latest/

一、安裝:

pip install psd-tools   
#這個包裏需求了 Pillow(用於將圖像導出到PNG,處理它們),所以安裝時會自動安裝,不需要額外安裝

爲了從32位PSD文件中提取圖像,PIL/Pillow必須使用LITTLECMS或LITTLECMS2支持來構建(apt-get install liblcms2-2或brew install little-cms2)

爲了用完整的圖層圖像合成功能,也可以安裝NumPy/SciPy:

pip install numpy scipy

以下情況Numpy是必要的:

  • 使用正常模式以外的混合模式;
  • 使用漸變填充。

二、使用

0/ 示例

from psd_tools import PSDImage

psd = PSDImage.open('example.psd')
psd.compose().save('example.png')

for layer in psd:
    print(layer)

1.操作一個PSD文件

#可在源碼的psd_image.py中看到PSDImage類

1/ 打開一個文件

from psd_tools import PSDImage
psd = PSDImage.open('my_image.psd')
#返回一個PSDImage類型的對象

#psd_tools中的大多數數據結構都支持在IPython環境中進行漂亮的打印。

#  In [1]: PSDImage.open('example.psd')
#  Out[1]:
#  PSDImage(mode=RGB size=101x55 depth=8 channels=3)
#    [0] PixelLayer('Background' size=101x55)
#    [1] PixelLayer('Layer 1' size=85x46)

##############################################################
2/ psd的屬性(可在源碼的psd_image.py中看到PSDImage類)
有些無意義的屬性也定義了,爲了和layer一樣可以,如:visible直接返回Ture。

這裏列出一些有意義,一般會用到的屬性:
psd.width #寬
psd.height #高
psd.size #(width, height) tuple
psd.offset #(left, top) tuple
psd.left #0
psd.right #self.width
psd.top #0
psd.bottom #self.height
psd.viewbox #(left, top, right, bottom) `tuple`

psd.bbox #能包圍住所有可見的層的最小的方框(x,y,z,w)
psd.color_mode #顏色模式,如RGB,GRAYSCALE
psd.channels #顏色通道數量
psd.depth #像素深度位數
psd.version #文件版本 psd是1,psb是2.
psd.has_preview #Returns if the document has real merged data. When True, `topil()`returns pre-composed data.
psd.has_thumbnail #是否有縮略圖
psd.thumbnail #返回	PIL.Image格式的縮略圖

這裏列出一些無意義的爲了可以和layer一樣操作的屬性:
psd.is_visible() #True
psd.visible #True
psd.parent #None
psd.name   #'Root'
psd.kind #'psdimage'

print(str(psd.is_group()))#是否是組 psd文件直接傳進去也是組
psd文件的層可以遍歷:
for layer in psd:
print(layer)
if layer.is_group():
    for child in layer:
        print(child)

child = psd[0][0]
#迭代順序是從背景到前景,與1.7.x之前的版本相反。使用reverse (list(psd))從前臺到後臺進行迭代。

##############################################################
3/ 保存psd文件:
psd.save('output.psd')

4/ 用psd文件獲取PIL Image.
psd.topil(channel=None, **kwargs)
#channel:0爲R,1爲G,2爲B,-1爲A,根據constants.py中ChannelID類。

5/ 合併psd文件.
psd.compose(force = False,bbox=None,**kwargs)

6/ 用PIL Image生成一個PSDImage對象
from psd_tools import PSDImage
psd = PSDImage.frompilfrompil(image,compression=<Compression.PACK_BITS: 1>)

2.操作一個PSD圖層

#可在源碼的layers.py中看到Layer類

##############################################################
1/Layer的屬性(可在源碼的layers.py中看到Layer類)

layer.name #層的名字(可寫)
layer.kind #層的類別(字符串)

#(group(圖層組), pixel(普通圖層), shape, type(文本圖層), smartobject,or psdimage(psd本身))
#shape繪製矢量形狀,形狀信息存儲在vector_mask和origination屬性中。其他圖層也可以有形狀信息作爲蒙版:
#smartobject爲非破壞性編輯嵌入或鏈接外部文件。文件內容可以通過smart_object屬性訪問。

layer.layer_id #Layer ID.
layer.visible #層本身是否勾選可見(可寫)
layer.is_visible() #層是否可見,受父物體影響。(父物體不可見,這個層就算勾選了可見這個也是False)

layer.opacity #透明度 [0,255](可寫)
layer.parent #Parent of this layer.
layer.is_group #是否是個組
layer.blend_mode #混合模式(可寫),返回Constants.py中的BlendMode
layer.has_mask #是否有mask
layer.left #左座標(可寫)
layer.top  #頂座標(可寫)
layer.right #右座標
layer.bottom #底座標
layer.width #層的寬
layer.height #層的高
layer.offset #(left, top) tuple. (可寫)
layer.size #(width, height) tuple.
layer.bbox #(left, top, right, bottom) tuple.
layer.has_pixels() #是否有像素
layer.has_mask() #是否有蒙板
layer.has_vector_mask() #是否有矢量蒙板
layer.mask #層相關的蒙版 return: :py:class:`~psd_tools.api.mask.Mask` or `None`
layer.vector_mask #層相關的矢量蒙版 return: :py:class:`~psd_tools.api.shape.VectorMask` or `None`
layer.has_origination() #是否有實時形狀屬性
layer.origination #實時形狀屬性
layer.has_stroke() #是否有比劃
layer.stroke #比劃
layer.has_clip_layers() #是否有裁剪
layer.clip_layers #裁剪,Clip layers associated with this layer.
layer.has_effects() #是否有效果處理
layer.effects #效果處理 return: :py:class:`~psd_tools.api.effects.Effects`
layer.tagged_blocks #Layer tagged blocks that is a dict-like container of settings.

##############################################################
2/ 獲得圖層的pil圖,Get PIL Image of the layer.(返回PIL.Image對象或沒像素時返回`None`)
layer.topil(channel=None, **kwargs)

e.g.
from psd_tools.constants import ChannelID
image = layer.topil()
red = layer.topil(ChannelID.CHANNEL_0)
alpha = layer.topil(ChannelID.TRANSPARENCY_MASK)

##############################################################
3/ 合併圖層和其蒙版(mask, vector mask, and clipping layers)(返回PIL.Image對象或沒像素時返回`None`)
layer.compose(bbox=None, **kwargs)

不合並,單獨獲取:
image = layer.topil()
mask = layer.mask.topil()
from psd_tools import compose
clip_image = compose(layer.clip_layers)

三、操作案例

1、導出一個psd文件的所有圖層(用文件本身的大小,而不是圖層的大小)

思路:

遍歷所有圖層,每次導出一個目前圖層
把除目標圖層外的圖層(is_group()要爲False,圖層組不隱藏)隱藏,設置visible爲False,目標圖層的visible設置爲True
然後調用:

merged_image = psd.compose(True) 
merged_image.save(exportName)
#依據實驗,這裏參數force要爲True,否則不是目前設置好的圖層顯隱看出來的圖。

#看源碼可知,force爲False時,使用的圖是topil()返回的PIL Image,貌似不會受臨時修改的圖層顯隱影響;(不太確定這個圖生成的時機,但好像只會生成一次)
#force爲True使用的圖爲compose所有圖層產生的PIL Image,所以會根據所有圖層現在的顯隱去生成新圖。

導出文件。

2.導出一個psd文件的所有圖層(用圖層本身的大小)

思路:

這個比較簡單,就直接調用

#不帶蒙版
layer_image = layer.topil()
layer_image.save('layer.png')

或者

#帶蒙版
layer.compose()
layer_image.save('layer.png')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章