首頁 > 軟體

Python通過psd-tools解析PSD檔案

2022-06-16 18:01:40

前言:

最近碰到業務需要根據PSD檔案實現PSD檔案解析圖層功能,搜到了Python的一個解析PSD的庫。這個庫就是psd-toolspsd-tools是一個Python軟體包,用於處理Adobe Photoshop PSD檔案。以下就是psd-tools的基本介紹。

特點

支援:

  • 讀取和寫入初級的PSD/PSB檔案結構
  • 以NumPy和PIL格式匯出原始圖層影象

有限的支援:

  • 基於畫素的基本圖層的構造
  • 填充層效果的構造
  • 向量面具
  • 編輯一些圖層屬性,如圖層名稱
  • 除溶解外的混合模式
  • 繪製貝塞爾曲線

不支援:

  • 編輯圖層結構,如新增或刪除一個圖層
  • 調整層的構造
  • 許多層效果的構造
  • 字型渲染

安裝

使用pip來安裝該軟體包。

pip install psd-tools 

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

pip install numpy scipy

使用

簡單的例子:

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)

1. 命令列

該軟體包提供命令列工具來處理PSD檔案。

psd-tools export <input_file> <output_file> [options]
psd-tools show <input_file> [options]
psd-tools debug <input_file> [options]
psd-tools -h | --help
psd-tools --version

例子:

psd-tools show example.psd  # 顯示檔案內容
psd-tools export example.psd example.png  # 匯出為PNG
psd-tools export example.psd[0] example-0.png  # 將圖層匯出為PNG

2. 操作PSD檔案

psd_tools.api 包提供了使用者友好的API來處理PSD檔案。

開啟一個影象:

from psd_tools import PSDImage
psd = PSDImage.open('my_image.psd')

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)

內部層可以通過迭代器或索引進行存取:

for layer in psd:
    print(layer)
    if layer.is_group():
        for child in layer:
            print(child)

child = psd[0][0]

開啟的PSD檔案可以儲存:

psd.save('output.psd')

3. 操作使用層

在Photoshop中,有各種層的種類。

最基本的圖層型別是PixelLayer:

print(layer.name)
layer.kind == 'pixel'

有些圖層屬性是可編輯的,如圖層名稱:

layer.name = 'Updated layer 1'

組裡有內部層:

for layer in group:
    print(layer)
first_layer = group[0]

TypeLayer 是一個帶有文字的層:

print(layer.text)

ShapeLayer 繪製一個向量形狀,形狀資訊儲存在vector_mask和origination屬性中。其他層也可以有形狀資訊作為遮罩:

print(layer.vector_mask)
for shape in layer.origination:
    print(shape)

SmartObjectLayer 嵌入或連結一個外部檔案,用於非破壞性編輯。檔案內容可以通過smart_object屬性存取:

import io
if layer.smart_object.filetype in ('jpg', 'png'):
    image = Image.open(io.BytesIO(layer.smart_object.data))

SolidColorFillPatternFill, 和 GradientFill 是填充圖層,如果沒有相關的遮罩,它們會繪製整個區域。 AdjustmentLayer 的子類表示應用於組成影象的層調整。參見 Adjustment layers.

4. 將資料匯出到 PIL

將整個檔案匯出為 PIL.Image:

image = psd.composite()
image.save('exported.png')

匯出單一圖層,包括遮罩和剪裁層:

image = layer.composite()

分別匯出圖層和蒙版,不需要合成:

image = layer.topil()
mask = layer.mask.topil()

要合成特定的圖層,如除文字外的圖層,請使用layer_filter選項:

image = psd.composite(
    layer_filter=lambda layer: layer.is_visible() and layer.kind != 'type')

請注意:大多數圖層效果和調整層不被支援。合成的結果可能看起來與Photoshop不同。

4. 將資料匯出到NumPy

PSDImage或圖層可以通過 numpy() 方法匯出為NumPy陣列:

image = psd.numpy()
layer_image = layer.numpy()

更多操作

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)

到此這篇關於Python通過psd-tools解析PSD檔案的文章就介紹到這了,更多相關Python PSD 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com