【解説】PSDファイルの仕様（レイヤーとマスク情報セクション）

この記事は[PSDファイルの構造（基本構造編）](https://qiita.com/vram/items/2632cb9ed2dec9430f59)からの続きになります。

## レイヤーとマスク情報セクション
PSDファイルの特徴であるレイヤーやマスクのデータを管理するセクションです。

前のセクションであるイメージリソースセクションにてイメージリソースサイズが

| adr | data |
|:-:|:-:|
|1E|00h|
|1F|00h|
|20|09h|
|21|F6h|

このようになっているので
次に読むべきアドレス 22hに対して 09F6hを加算すると A18hとなり、レイヤーとマスク情報セクションは A18hから始まることがわかります。

レイヤーのデータ構造は最背面側のレイヤーから始まり、最後のデータが最も上に来るレイヤーになります。

### データ構造
| byte | info |
|:-:|:-:|
|4|データのサイズ|
|4|セクションのサイズ|
|2|レイヤー数|
| |レイヤー数繰り返し|
|4|上側 Y座標|
|4|左側 X座標|
|4|下側 Y座標|
|4|右側 X座標|
|2|チャンネル数|
| |チャンネル数分繰り返す先頭
|2|チャンネル種別|
|4|チャンネルのサイズ|
| |チャンネル数分繰り返す末端 |
||レイヤー情報に続く|


### データのサイズ
| adr | data |
|:-:|:-:|
|A18|00h|
|A19|00h|
|A1A|14h|
|A1B|04h|

### セクションのサイズ
| adr | data |
|:-:|:-:|
|A1C|00h|
|A1D|00h|
|A1E|13h|
|A1F|FCh|

長さは2回示されていてデータとセクションの違いがあります。
セクションよりも8バイト長くなったのがデータになります。

### レイヤー数
| adr | data |
|:-:|:-:|
|A20|00h|
|A21|03h|

全体のレイヤーの数を示します。

### 上側のY座標
| adr | data |
|:-:|:-:|
|A22|FFh|
|A23|FFh|
|A24|FFh|
|A25|FEh|

レイヤー上側のY座標を示します。 FFFFFFFEhは -2になります。

### 左側のX座標
| adr | data |
|:-:|:-:|
|A26|00h|
|A27|00h|
|A28|00h|
|A29|01h|

レイヤー左側のX座標を示します。 X座標は 1になります。

### 下側のY座標
| adr | data |
|:-:|:-:|
|A2A|00h|
|A2B|00h|
|A2C|00h|
|A2D|21h|

レイヤー下側のY座標を示します。 Y座標は 33になります。

### 右側のX座標
| adr | data |
|:-:|:-:|
|A2E|00h|
|A2F|00h|
|A30|00h|
|A31|1Fh|

レイヤー右側のX座標を示します。 X座標は 31になります。

### チャンネル数
| adr | data |
|:-:|:-:|
|A32|00h|
|A33|04h|

1つのレイヤーは複数のチャンネルを重ね合わせたデータとなります。各チャンネルにはRGBの色を示すものとマスクを示すものがあります。PSDのイラストデータの場合はRGBのほかに透明マスク情報があり、このマスクが示すエリアのみを描画することにより重ね合わせたときの透明部分を再現しています。

#### チャンネルの種別
| adr | data |
|:-:|:-:|
|A34|00h|
|A35|00h|

2バイトでチャンネルの種別を示します。

| 値 |チャンネルの種別|
|:-:|:-:|
|0000h|赤|
|0001h|緑|
|0002h|青|
|FFFFh|透明マスク|
|FFFEh|ユーザーが提供するレイヤーマスク|
|FFFDh|ユーザーマスクとベクトルマスクの両方|

#### チャンネルのサイズ
| adr | data |
|:-:|:-:|
|A36|00h|
|A37|00h|
|A38|02h|
|A39|16h|

続けて4バイトでチャンネルのデータの長さを示します。
チャンネル数の数だけチャンネルの種別とチャンネルの長さのデータが存在します。

## レイヤー情報
チャンネルデータの次はレイヤー情報を示します。非常に複雑な構造の上、識別子が突然現れるので注意が必要です。

### レイヤーの識別子
| adr | data |text|
|:-:|:-:|:-:|
|A4C|38h|8|
|A4D|42h|B|
|A4E|49h|I|
|A4F|4Dh|M|

レイヤーの識別子です、構造の解析処理でこの識別子を見失った場合は処理を見直す必要があります。


### モードキー
| adr | data |text|
|:-:|:-:|:-:|
|A50|6Eh|n|
|A51|6Fh|o|
|A52|72h|r|
|A53|6Dh|m|

レイヤー情報の種別を示します。種類の英語名を4文字に省略したものが使われています。

代表的なモードキーは下記の通り

| モードキー |意味|
|:-:|:-:|
|luni|Unicode レイヤー名称|
|lsct|レイヤーの階層構造|
||ここからは描画系|
|norm|標準描画|
|pass|描画しない？|
|diss|ディゾルブ|
|dark|暗く描画|
|mul |乗算描画|
|idiv|カラーバーン|
|lbrn|リニアバーン|
|dkCl|ダークカラー|
|lite|明るく|
|scrn|スクリーン|
|div|覆い焼きカラー|
|lddg|覆い焼きリニア|
|lgCl|明るい色|
|over|オーバーレイ|
|sLit|ソフトライト|
|hLit|ハードライト|
|vLit| ビビッドライト|
|lLit|リニアライト|
|pLit| ピンライト|
|hMix| ハードミックス|
|diff| 差分|
|smud| 除外|
|fsub| 減算|
|fdiv| 除算|
|hue| 色相|
|sat| 彩度|
|colr| 色|
|lum| 明度|


### 描画系
描画系は描画の演算が異なるだけでデータ構造は同じのためまとめて解説します。
演算には描画前のピクセルと描画しようとしているピクセルで行われ、演算結果が新しいピクセル値になります。

（例）
描画前 old 描画後 new 描画データ data とすると
標準描画では new = data
加算描画では new = old + data
となります。実際はオーバーフローなども考慮します。

描画系のデータ構造
| byte | info |
|:-:|:-:|
|4|8BIM|
|4|normを代表する描画モードキー|
|1|透明度|
|1|クリッピング|
|1|フラグ|
|1|未使用|
|4|データサイズ|
|4|マスクデータサイズ|
||マスクデータサイズが 0ではない時|
|4|上側 Y座標|
|4|左側 X座標|
|4|下側 Y座標|
|4|右側 X座標|
|1|標準色|
|1|フラグ|
|1|マスク|
||マスクデータサイズが 20の時|
|1|ダミーデータ|
||マスクデータサイズが 20ではない時|
|1|フラグその2|
|1|マスクその2|
|4|マスク上側 Y座標|
|4|マスク左側 X座標|
|4|マスク下側 Y座標|
|4|マスク右側 X座標|
||マスクデータサイズが 0ではない時の終端|
|4|合成データサイズ|
||合成データサイズでループ開始|
||ループ1回目はグレイスケール|
||ループ2回目以降は合成として扱う|
|4|データソース場所|
|4|データソースアドレス|
||合成データサイズでループ終端|
|1|レイヤー名サイズ|
|X|レイヤー名(ShiftJIS)|
|※1||

※1レイヤー名の次に来るアドレスは4の倍数になるように0で埋められる

### 透明度
| adr | data |
|:-:|:-:|
|A54|FFh|

レイヤーの透明度を0～255で示します。
0が透明で255が不透明になります。

### クリッピング対象
| adr | data |
|:-:|:-:|
|A55|00h|

クリッピングのベースレイヤーになるのかを示します。
0 クリッピングベースレイヤー
1 非クリッピングベースレイヤー

### フラグ
| adr | data |
|:-:|:-:|
|A56|08h|

各ビットごとに下記の意味があります。
| bit |意味|
|:-:|:-:|
|0|透明度の保護|
|1|ON:非表示|
|2|廃止|
|3|ON:PhotoShop5.0以降のデータ|
|4|bit3がONのときドキュメントの外観に関係のないピクセルデータ|

レイヤーから画像を生成する場合はbit1を確認し、ONであればこのレイヤーを描画しないようにします。

### ダミー
| adr | data |
|:-:|:-:|
|A57|08h|

#### データサイズ
| adr | data |
|:-:|:-:|
|A58|00h|
|A59|00h|
|A5A|00h|
|A5B|1Eh|

レイヤー情報は1つの描画モードキーで始まり、他のモードキーも複数含めます。
次のレイヤー情報は A3Ahに 1Ehを加算した A7Ahから始まります。

#### マスクデータサイズ
| adr | data |
|:-:|:-:|
|A5C|00h|
|A5D|00h|
|A5E|00h|
|A5F|00h|

#### 合成データサイズ
| adr | data |
|:-:|:-:|
|A60|00h|
|A61|00h|
|A62|00h|
|A63|00h|

#### レイヤーデータサイズ
| adr | data |
|:-:|:-:|
|A64|01h|

#### レイヤー名
| adr | data |text|
|:-:|:-:|:-:|
|A65|42h|B|

#### レイヤー名のダミー
| adr | data |text|
|:-:|:-:|:-:|
|A66|00h||
|A67|00h||

A66hが4で割り切れないので4が割り切れるアドレスが次のアドレスになるようにダミーデータで埋めます。
その結果次のアドレスは 4で割り切れる A68hになります。

### レイヤーの識別子
| adr | data |text|
|:-:|:-:|:-:|
|A68|38h|8|
|A69|42h|B|
|A6A|49h|I|
|A6B|4Dh|M|

レイヤーの識別子です、構造の解析処理でこの識別子を見失った場合は処理を見直す必要があります。

### モードキー
| adr | data |text|
|:-:|:-:|:-:|
|A6C|6Ch|l|
|A6D|75h|u|
|A6E|6Eh|n|
|A6F|69h|i|

レイヤー情報の種別を示します。luniはレイヤー名を示すUNICODE文字列を指します。

#### UNICODEデータサイズ
| adr | data |
|:-:|:-:|
|A70|00h|
|A71|00h|
|A72|00h|
|A73|06h|

UNICODEのデータサイズを示します。
A74h に 6hを加算した A7Ahが次のレイヤー情報のアドレスになります。

#### UNICODE文字長
| adr | data |
|:-:|:-:|
|A74|00h|
|A75|00h|
|A76|00h|
|A77|06h|

文字列データはデータのサイズと文字の長さが異なります。
データを処理する場合はデータサイズを、文字列を成形する場合は文字長を使用します。

#### UNICODE レイヤー名
| adr | data |text|
|:-:|:-:|:-:|
|A78|00h||
|A79|42h|B|

UNICODEで示されるレイヤー名です。
この情報が無い場合はnormのレイヤー名を採用します。
両方存在し、アプリがUNICODEに対応している場合はUNICODEのレイヤー名を採用します。

次に処理するアドレス A7Ahはレイヤーのデータサイズから計算した次のレイヤーのアドレスになるため、このレイヤーの処理はここで終了し次のレイヤーのデータの処理に移行します。
次のレイヤーのデータはレイヤー構造のここから始まる部分になります。

| byte | info |
|:-:|:-:|
|4|上側 Y座標|
|4|左側 X座標|
|4|下側 Y座標|
|4|右側 X座標|
|2|チャンネル数|

### レイヤー階層情報
モードキー lsct の場合のデータ構造は以下の通り
| byte | info |
|:-:|:-:|
|4|レイヤーのサイズ|
|4|階層構造データ|

| 階層構造 |意味|
|:-:|:-:|
|0|通常のレイヤー|
|1|階層構造を開くレイヤー|
|2|階層構造を開くレイヤー|
|3|階層構造を閉じるレイヤー|

レイヤー情報は背面から順になるため、レイヤーが階層構造である場合には1や2よりも先に3が存在します。

レイヤー情報の次には[イメージデータセクション](3857bf69667e9f8e889a)があります。