【解説】PSDファイルの仕様（基本構造編）

# PSDファイルとは

PSDファイルとはアドビシステムズが開発した「Adobe Photoshop」というグラフィック編集ツールで利用されるファイル形式です。

画像データをレイヤー形式で複数管理することが出来る便利なファイルなのですが、その内部構造を解説しているサイトがありません。

解説には非常に多くの時間と文章量が必要なために、少しずつ追筆していくことになるかと思いますのでご了承願います。

非常に限定された知識とその技術解説になりますが、応援して頂けると執筆の励みになりますのでよろしくお願いいたします。

仕様書はアドビシステムズが公開していますが、説明が不足しているところや補完が必要なところがありますのでそれらも解説出来たらと思います。

[PSDファイル仕様書](https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/)

解説に使用するPSDファイルのサンプルは近日中に用意する予定です。

解説するPSDデータですが、写真データではなく主に「PSD立ち絵データ」と呼ばれるイラストと、そのアニメーション用のデータが内包されたファイルがメインになります。

ファイル構造を解析するためにはバイナリエディタを使用します。
[バイナリエディタString](https://www.vector.co.jp/soft/win95/util/se079072.html)

PSDファイルは5つのセクションに分かれていてそれぞれ
1. ファイルヘッダセクション
2. カラーモードデータセクション
3. イメージリソースセクション
4. [レイヤーとマスク情報セクション](https://qiita.com/vram/items/8ac2d7bfd63840267109)
5. [イメージデータセクション](3857bf69667e9f8e889a)

となっています。

各セクションの先頭アドレスは管理されていないため、先頭から順に各セクションのサイズを解析することで、それぞれのセクションの先頭アドレスが判明します。

## ファイルヘッダセクション
### ファイル識別子
PSDファイルの先頭4バイトは

| adr | data |text|
|:-:|:-:|:-:|
|   0|38h|8|
|  1|42h|B|
|  2|50h|I|
|  3|53h|S|

または

| adr | data |text|
|:-:|:-:|:-:|
|   0|38h|8|
|  1 |42h|B|
|  2 |36h|6|
|  3 |34h|4|

のようになっています。
この4バイトはファイルがPSD形式であることを示すファイル識別子です。
ここではヘッダが「8BIS」のデータの解説を行います。
「8BIS」ではセクションの長さを表すデータが4バイトであるのに対して
「8B64」では8バイトで管理されています。

### バージョン番号

| adr | data |
|:-:|:-:|
|   4|00h|
|  5|01h|

次の2バイトにはバージョン番号が格納されます。
数値は上位→下位の順に格納されます。

### 予約領域
| adr | data |
|:-:|:-:|
|   6|00h|
|  7|00h|
|   8|00h|
|  9|00h|
|   A|00h|
|  B|00h|

次の6バイト固定長は予約領域でデータは存在しません。

### チャンネル数
| adr | data |
|:-:|:-:|
|   C|00h|
|  D|04h|

次の2バイト固定長のデータはチャンネル数になります。
チャンネル数といってもピンと来ないと思いますが
RGBの色空間表現では赤と緑と青の3色ですので3チャンネルになります。
4チャンネルの場合はRGBに加えて透明度のαチャンネルがあることを示します。


### キャンバスの縦幅、横幅
| adr | data |
|:-:|:-:|
|   E|00h|
|  F|00h|
|   10|00h|
|  11|20h|

| adr | data |
|:-:|:-:|
|   12|00h|
|  13|00h|
|   14|00h|
|  15|20h|

4バイトの固定長で画像の縦幅と横幅を示します。
限界値はPSA形式とPSB形式があり
PSA形式は1～30,000pixel
PSB形式は1～300,000pixel
まで対応します。
この縦幅と横幅は画像データではなくベースとなっている土台のサイズであるため、画像データがこれよりも小さいことや、反対に大きいサイズの画像データが含まれていることがあります。

### データビット数
| adr | data |
|:-:|:-:|
|   16|00h|
|  17|08h|

かなり後半の説明になると思われる画像データのビット数を示します。
イラスト系の場合は8が使われます。
ビット数は 1、8、16、32のいずれかが指定されます。

### 色モード
| adr | data |
|:-:|:-:|
|18|00h|
|19|03h|

色空間の管理方法を示します。
色空間番号と対応する色空間は下記の通りです。

| data |色空間|
|:-:|:-:|
|0|Bitmap|
|1|Grayscale|
|2|Indexed|
|3|RGB|
|4|CMYK|
|7|Multichannel|
|8|Duotone|
|9|Lab|

## カラーモードデータセクション
このセクションでは色に関する様々な情報を示します。

### カラーデータサイズ
| adr | data |
|:-:|:-:|
|1A|00h|
|1B|00h|
|1C|00h|
|1D|00h|

色に関するデータのデータ長を示します。存在しない場合は0になります。

## イメージリソースセクション
このセクションではPSDファイルを編集するエディタが使用する設定値などの情報を示します。
ここでは基本情報とサムネイル情報のみ構造を説明します。

### イメージリソースサイズ
| adr | data |
|:-:|:-:|
|1E|00h|
|1F|00h|
|20|09h|
|21|F6h|

イメージリソースセクションのサイズを示します。イメージリソースセクションを読み飛ばす場合はこのサイズ分を読み飛ばせば次のセクションの先頭アドレスにたどり着きます。

### イメージリソースセクションの識別子
| adr | data |text|
|:-:|:-:|:-:|
|22|38h|8|
|23|42h|B|
|24|49h|I|
|25|4Dh|M|

イメージリソースセクションには複数のリソースが存在します。各リソースの先頭には必ずこの4バイトが存在します。
レイヤーセクションの識別子と同じなので注意が必要です。

### リソースID
| adr | data |
|:-:|:-:|
|26|03h|
|27|EDh|

2バイトで情報の種類を示します。リソースIDは非常に多くの種類が存在しますので詳細は公式の仕様を確認して下さい。


| ID |情報の種類|
|:-:|:-:|
|03EDh|解像度情報|
|0400h|レイヤー情報|
|040Ch|サムネイル情報|

#### 解像度情報
| adr | data |text|
|:-:|:-:|:-:|
|28|0Ah|文字長|
|29|52h|R
|2A|65h|e
|2B|73h|s
|2C|6Fh|o
|2D|6Ch|l
|2E|75h|u
|2F|74h|t
|30|69h|i
|31|6Fh|o
|32|6Eh|n

##### ダミーデータ
| adr | data |
|:-:|:-:|
|33|00h|
|34|00h|
|35|00h|
|36|00h|

0を示します。ダミーかもしれません。

##### データサイズ
| adr | data |
|:-:|:-:|
|37|10h|

解像度データのサイズを示します解像度のデータは16バイト(10h)になります。

##### 水平解像度
| adr | data |
|:-:|:-:|
|38|01h|
|39|5Eh|
|3A|00h|
|3B|00h|

4バイトの固定小数点方式で1インチあたりのピクセル数で示す水平解像度を示します。

##### 水平解像度が示す情報の種類
| adr | data |
|:-:|:-:|
|3C|00h|
|3D|01h|

2バイトで水平解像度が表す情報の種類

| 値 |種類|
|:-:|:-:|
|0001h|水平解像度を1インチあたりのピクセル数で表示|
|0002h|表示1cmあたりのピクセル数で表した水平解像度|

##### 水平解像度が示す単位
| adr | data |
|:-:|:-:|
|3E|00h|
|3F|02h|

2バイトで水平解像度が表す単位を示します。

| 値 |単位|
|:-:|:-:|
|0001h|インチ|
|0002h|cm|
|0003h|ポイント|
|0004h|ピカ|
|0005h|例|

##### 垂直解像度
| adr | data |
|:-:|:-:|
|40|01h|
|41|5Eh|
|42|00h|
|43|00h|

4バイトの固定小数点方式で1インチあたりのピクセル数で示す水平解像度を示します。

##### 垂直解像度が示す情報の種類
| adr | data |
|:-:|:-:|
|44|00h|
|45|01h|

2バイトで垂直解像度が表す情報の種類

| 値 |種類|
|:-:|:-:|
|0001h|垂直解像度を1インチあたりのピクセル数で表示|
|0002h|表示1cmあたりのピクセル数で表した垂直解像度|

##### 垂直解像度が示す単位
| adr | data |
|:-:|:-:|
|46|00h|
|47|02h|

2バイトで垂直解像度が表す単位を示します。

| 値 |単位|
|:-:|:-:|
|   0001h|インチ|
|0002h|cm|
|0003h|ポイント|
|0004h|ピカ|
|0005h|例|

### イメージリソースセクションの識別子
| adr | data |text|
|:-:|:-:|:-:|
|48|38h|8|
|49|42h|B|
|4A|49h|I|
|4B|4Dh|M|

イメージリソースサイズから、まだイメージリソースセクションが続くものと判断します。

### リソースID
| adr | data |
|:-:|:-:|
|4C|04h|
|4D|00h|

2バイトで情報の種類を示します。
0400hはレイヤー情報です。

#### レイヤー情報
| adr | data |text|
|:-:|:-:|:-:|
|4E|0Bh|文字長|
|4F|54h|T|
|50|61h|a|
|51|72h|r|
|52|67h|g|
|53|65h|e|
|54|74h|t|
|55|4Ch|L|
|56|61h|a|
|57|79h|y|
|58|65h|e|
|59|72h|r|

##### データ数
| adr | data |text|
|:-:|:-:|:-:|
|5A|00h||
|5B|00h||
|5C|00h||
|5D|02h||

4バイトでレイヤー情報のデータサイズを示します。

##### データ
| adr | data |
|:-:|:-:|
|5E|00h|
|5F|00h|

レイヤー情報のデータは 0000h 何を示しているのかは未解析

### イメージリソースセクションの識別子
| adr | data |text|
|:-:|:-:|:-:|
|60|38h|8|
|61|42h|B|
|62|49h|I|
|63|4Dh|M|

イメージリソースサイズから、まだイメージリソースセクションが続くものと判断します。

### リソースID
| adr | data |
|:-:|:-:|
|64|04h|
|65|0Ch|

2バイトで情報の種類を示します。
040Chはサムネイル情報です。

#### サムネイル情報
| adr | data |text|
|:-:|:-:|:-:|
|66|09h|文字長|
|67|54h|T| 
|68|68h|h|
|69|75h|u|
|6A|6Dh|m|
|6B|62h|b|
|6C|6Eh|n|
|6D|61h|a|
|6E|69h|i|
|6F|6Ch|l|

##### データ数
| adr | data |
|:-:|:-:|
|70|00h|
|71|00h|
|72|09h|
|73|03h|

4バイトでサムネイル情報のデータサイズを示します。

##### フォーマット
| adr | data |
|:-:|:-:|
|74|00h|
|75|00h|
|76|00h|
|77|01h|

4バイトでサムネイル情報のフォーマットを示します。
| 値 |形式|
|:-:|:-:|
|0000h|BMP|
|0001h|jpeg|

##### 横幅
| adr | data |
|:-:|:-:|
|78|00h|
|79|00h|
|7A|00h|
|7B|70h|

4バイトでサムネイルの横幅を示します。

##### 高さ
| adr | data |
|:-:|:-:|
|7C|00h|
|7D|00h|
|7E|00h|
|7F|70h|

4バイトでサムネイルの高さを示します。

##### 1行の描画に必要なビット数
| adr | data |
|:-:|:-:|
|80|00h|
|81|00h|
|82|01h|
|83|50h|

1行分を描画するのに必要なビット数を示します。
サムネイルの横幅×チャンネル数の値と一致するものと思われます。

##### 高さ×幅×チャンネル
| adr | data |
|:-:|:-:|
|84|00h|
|85|00h|
|86|93h|
|87|00h|

サムネイルの高さと幅とチャンネルを乗算した結果です。
70h x 70h x 3 = 9300h

##### 圧縮後のサイズ
| adr | data |
|:-:|:-:|
|88|00h|
|89|00h|
|8A|09h|
|8B|87h|

##### 1ピクセルあたりのビット数
| adr | data |
|:-:|:-:|
|8C|00h|
|8D|18h|

1ピクセルは24ビットの情報で構成されていることを示す。


##### プレイン数
| adr | data |
|:-:|:-:|
|8E|00h|
|8F|01h|

翻訳に困る部分、直訳でプレイン数


##### 画像データ
jpegデータは FF D8 で始まりFF D9 で終了します。

|Data| 意味 |
|:-:|:-:|
|FFh|   |
|D8h|   |
||jpeg画像データ|
|FFh|   |
|D9h||
|00h||

画像データの最後を示す 00h が1バイト追加される

次にレイヤー情報とマスク情報が続きます。

[記事はこちら](https://qiita.com/vram/items/8ac2d7bfd63840267109)