Python で psd ファイルを処理できるライブラリ psd-toolsについて

# Python でPSDファイルを処理できるライブラリ psd-tools

▼公式ドキュメント
https://psd-tools.readthedocs.io/en/latest/

## テスト画像
今回はこちらの画像をサンプルとして使用します。![3070374.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/a118272d-c836-7635-372b-f729d3fad46b.jpeg)
<a href="http://www.freepik.com">Designed by Freepik</a>

▼ダウンロード先
https://www.freepik.com/free-psd/restaurant-gift-voucher-template_5903685.htm#page=3&position=11

▼Photoshop上でみたレイヤー情報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/83ed1c88-e548-95c0-74e1-3ab9f2daddf0.png)

## psd-tools の使い方

#### インストール
```
pip install psd-tools numpy scipy
```

### 使い方

```python

from psd_tools import PSDImage
if __name__ == '__main__':
    file_path = '/Users/[uesr_name]/Downloads/restaurant-gift-voucher-template/3074963.psd'
    psd = PSDImage.open(file_path)
    psd.compose().save('example.png')

    for layer in psd:
        print(layer)
```

▼出力

▼example.png
![example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/e5c36ddc-3b73-6363-a1f6-86556efd9e9b.png)

```

Group('Background' size=1772x886)
Group('Design' size=1426x570)
Group('Images' size=1226x1196)
Group('Text' size=1627x443)
Group('Logo' size=386x107)
```


## すべてのレイヤーにアクセスしたい場合
descendants() メソッドを使うことで、フォルダを含めすべてのレイヤーにアクセス可能

```python
for layer in list(psd.descendants()):
    print(layer)
```

```
Group('Background' size=1772x886)
SolidColorFill('Background' size=1772x886 mask effects)
Group('Design' size=1426x570)
SmartObjectLayer('Brush Stroke' size=1426x413 effects)
ShapeLayer('Rectangle' size=460x80 effects)
Group('Images' size=1226x1196)
SmartObjectLayer('Waffel' size=675x954 effects)
SmartObjectLayer('Food' size=23x27 effects)
SmartObjectLayer('Food' size=23x27 effects)
SmartObjectLayer('Food' size=27x27 effects)
SmartObjectLayer('Tomato Sauce' size=211x208 effects)
SmartObjectLayer('Tomato' size=237x239 effects)
SmartObjectLayer('Orange' size=276x272 effects)
Group('Text' size=1627x443)
TypeLayer('Title' size=506x122)
TypeLayer('20% OFF' size=441x96)
TypeLayer('Voucher ID #56893' size=379x30)
TypeLayer('Web' size=728x27)
TypeLayer('Address')
Group('Logo' size=386x107)
SmartObjectLayer('Place Your Logo Here (Double Click to Edit)' size=386x107)
```


## すべてのレイヤーを PIL.Image 化してレイヤー名で保存

```python

    for layer in list(psd.descendants()):
        print("layer_name: ", layer.name)
        print("is_group(): ", layer.is_group())

        if not layer.is_group():
            pil_img = layer.topil()
            pil_img.save(layer.name + ".png")
```

▼結果
![Waffel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/b70bdf7e-db3d-1f5a-4b83-b26efd27ef18.png)
![Orange.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/11a08354-07fd-96f1-651f-db6c808e2bb9.png)
![Brush Stroke.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/f385606d-5cda-a6f3-75e1-30a4ab6bbace.png)
![Tomato.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/e26fc820-0bea-3041-acea-dd479354b3dd.png)
![Tomato Sauce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/eabe457c-1e81-5f99-3b77-31bffe788ecf.png)
![Title.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/1e4af573-e4c6-f672-411a-b499a2638220.png)
![Background.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/9633c43e-e37c-b401-9fc4-b6461035e3af.png)
![20% OFF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/96493485-076e-38b1-32ef-e13c73e7e188.png)
![Web.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/5c788d84-bfb0-9141-c478-52fd45965a38.png)
![Voucher ID #56893.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/f01c2724-59e6-f81f-cb07-e23fd3d519b3.png)
![Food.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69701/1a16a09a-b33f-8401-a985-f3f0ffd2b3ec.png)