# 帳票設計書 9-画像PNG

## 概要

本ドキュメントは、ImageクラスのデータをPNG形式でファイルに保存する帳票の設計書である。

### 本帳票の処理概要

本帳票は、Godotエンジン内部のImageクラスデータをPNG（Portable Network Graphics）形式でファイルに保存する機能を提供する。スクリーンショット、動的生成テクスチャ、画像処理結果などをロスレス圧縮された画像ファイルとして出力する。

**業務上の目的・背景**：ゲーム開発において、スクリーンショット撮影、プロシージャルテクスチャの保存、デバッグ用画像出力など、様々な場面で画像をファイルに保存する必要がある。PNGはロスレス圧縮で透過（アルファチャンネル）をサポートしており、品質を損なわない保存に適している。

**帳票の利用シーン**：主に以下のシーンで利用される。1) ゲーム内スクリーンショット撮影、2) エディタでのスクリーンショット保存、3) プロシージャル生成テクスチャの保存、4) 画像処理・加工結果の出力。

**主要な出力内容**：
1. 画像ピクセルデータ（RGB/RGBA）
2. 画像サイズ情報
3. アルファチャンネル（対応フォーマットの場合）
4. PNG標準ヘッダー・チャンク

**帳票の出力タイミング**：Image::save_png()メソッドが呼び出された際、またはImage::save_png_to_buffer()でバッファに出力される。

**帳票の利用者**：ゲーム開発者、エンジン内部処理、ユーザースクリプト

## 帳票種別

画像エクスポート / バイナリデータ出力

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | スクリプトAPI | Image::save_png(path) | GDScript/C#から呼び出し |
| - | エディタ | エディタ内部 | スクリーンショット保存等 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | PNG（Portable Network Graphics） |
| 用紙サイズ | N/A（画像ファイル） |
| 向き | N/A |
| ファイル名 | 呼び出し側で指定 |
| 出力方法 | ファイルパス指定またはバッファ出力 |
| 文字コード | N/A（バイナリ） |

### PNG固有設定

| 項目 | 内容 |
|-----|------|
| 圧縮方式 | DEFLATE（ロスレス） |
| 色深度 | 元画像フォーマットに依存 |
| アルファチャンネル | 対応（RGBAフォーマットの場合） |
| インターレース | なし |

## 帳票レイアウト

### レイアウト概要

PNGファイルは標準PNG仕様に従う。

```
┌─────────────────────────────────────────────────────────────┐
│              PNGシグネチャ（8バイト）                         │
├─────────────────────────────────────────────────────────────┤
│              IHDRチャンク（画像ヘッダー）                      │
├─────────────────────────────────────────────────────────────┤
│              IDATチャンク（画像データ）                        │
│              ...（複数チャンク可）                            │
├─────────────────────────────────────────────────────────────┤
│              IENDチャンク（終端マーカー）                      │
└─────────────────────────────────────────────────────────────┘
```

### ヘッダー部（IHDR）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Width | 画像幅 | Image::get_width() | 32bit整数 |
| 2 | Height | 画像高さ | Image::get_height() | 32bit整数 |
| 3 | Bit depth | ビット深度 | Image::get_format()から算出 | 8/16 |
| 4 | Color type | カラータイプ | Image::get_format()から算出 | 0/2/4/6 |

### 明細部（IDAT）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 圧縮データ | DEFLATE圧縮されたピクセルデータ | Image::get_data() | バイナリ |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 有効な画像 | Imageが空でない（is_empty() == false） | Yes |
| 対応フォーマット | PNGで表現可能なフォーマット | Yes |

### ソート順

N/A（ピクセル順に出力）

### 改ページ条件

N/A（バイナリファイルのため改ページなし）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照せず、Imageオブジェクトからデータを取得する。

| データソース | 用途 | 取得方法 |
|-----------|------|---------|
| Image | 画像データ本体 | get_data() |
| Image | 画像サイズ | get_width(), get_height() |
| Image | フォーマット | get_format() |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| DEFLATE圧縮 | zlib圧縮 | N/A | libpng内部処理 |
| CRCチェックサム | CRC-32 | N/A | チャンクごとに計算 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Image::save_png呼び出し] --> B[save_png_func呼び出し]
    B --> C[ResourceSaverPNG::save_image]
    C --> D[PNGDriverCommon::image_to_png]
    D --> E{エラー?}
    E -->|Yes| F[エラー返却]
    E -->|No| G[FileAccess::open]
    G --> H{オープン成功?}
    H -->|No| F
    H -->|Yes| I[store_buffer]
    I --> J{書き込み成功?}
    J -->|No| K[ERR_CANT_CREATE返却]
    J -->|Yes| L[OK返却]
    F --> M[終了]
    K --> M
    L --> M
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 変換失敗 | PNGDriverCommonでエラー | "Can't convert image to PNG." | ERR_FAIL_COND_V_MSG |
| ファイルオープン失敗 | 書き込み権限なし等 | "Can't save PNG at path: '[path]'." | ERR_FAIL_COND_V_MSG |
| 書き込み失敗 | ディスクエラー等 | なし | ERR_CANT_CREATE返却 |
| 無効なテクスチャ | texture.is_null() | "Can't save invalid texture as PNG." | ERR_FAIL_COND_V_MSG |
| 空のテクスチャ | width == 0 | "Can't save empty texture as PNG." | ERR_FAIL_COND_V_MSG |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 単一画像 |
| 目標出力時間 | 画像サイズに依存（数ms〜数百ms） |
| 同時出力数上限 | スレッド依存 |

## セキュリティ考慮事項

- 出力先パスはユーザー/スクリプトが指定
- ファイルシステム権限に依存
- 大量の画像保存はディスクを消費する可能性

## 備考

- save_png_funcは関数ポインタで、ResourceSaverPNGコンストラクタで設定される
- save_png_to_buffer()を使用するとバッファに出力可能
- PNGDriverCommon::image_to_png()が実際のエンコード処理を行う

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 関数ポインタの設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | image.h | `core/io/image.h` | save_png_func関数ポインタ宣言（200行目） |
| 1-2 | resource_saver_png.cpp | `drivers/png/resource_saver_png.cpp` | コンストラクタでsave_png_func設定（86行目） |

**読解のコツ**: Imageクラスはcore層にあり、PNGエンコード実装はdrivers層にある。関数ポインタで結合されている。

#### Step 2: PNG保存処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | resource_saver_png.cpp | `drivers/png/resource_saver_png.cpp` | save_image()（51-66行目） |

**主要処理フロー**:
1. **52行目**: Vector<uint8_t> bufferを宣言
2. **53行目**: PNGDriverCommon::image_to_png()でPNGデータ生成
3. **55-56行目**: FileAccess::openでファイルを開く
4. **60行目**: store_buffer()でデータ書き込み
5. **61-63行目**: エラーチェックとエラー返却

#### Step 3: バッファ出力を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | resource_saver_png.cpp | `drivers/png/resource_saver_png.cpp` | save_image_to_buffer()（68-73行目） |

**主要処理フロー**:
- **69-70行目**: PNGDriverCommon::image_to_png()でPNGデータ生成
- **71行目**: エラー時は空のVectorを返却
- **72行目**: 成功時はbufferを返却

### プログラム呼び出し階層図

```
Image::save_png(path) [GDScript/C#から呼び出し]
    │
    └─ save_png_func(path, this)
           │ [関数ポインタ経由]
           │
           └─ ResourceSaverPNG::save_image(path, img)
                  │
                  ├─ PNGDriverCommon::image_to_png(img, buffer)
                  │      │
                  │      └─ [libpng/lodepng等でエンコード]
                  │
                  ├─ FileAccess::open(path, WRITE)
                  │
                  └─ file->store_buffer(buffer.ptr(), buffer.size())

Image::save_png_to_buffer() [バッファ出力]
    │
    └─ save_png_buffer_func(this)
           │ [関数ポインタ経由]
           │
           └─ ResourceSaverPNG::save_image_to_buffer(img)
                  │
                  └─ PNGDriverCommon::image_to_png(img, buffer)
                         │
                         └─ return buffer
```

### データフロー図

```
[入力]                        [処理]                         [出力]

Image ────────────────────▶ get_data() ──────────────────▶ ピクセルデータ
      │                                                         │
      ├─ get_width() ─────▶ IHDR生成 ──────────────────────────▶│
      │                                                         │
      ├─ get_height() ────▶                                     │
      │                                                         │
      └─ get_format() ────▶                                     │
                                                                │
                          PNGDriverCommon::image_to_png()
                                │
                                ▼
                          [PNG バイナリ]
                                │
                          FileAccess::store_buffer()
                                │
                                ▼
                          [.png ファイル]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| image.h | `core/io/image.h` | ヘッダー | Imageクラス定義、save_png_func宣言 |
| image.cpp | `core/io/image.cpp` | ソース | Imageクラス実装 |
| resource_saver_png.h | `drivers/png/resource_saver_png.h` | ヘッダー | ResourceSaverPNGクラス定義 |
| resource_saver_png.cpp | `drivers/png/resource_saver_png.cpp` | ソース | save_image()、save_image_to_buffer()実装 |
| png_driver_common.h | `drivers/png/png_driver_common.h` | ヘッダー | PNGDriverCommon定義 |
| png_driver_common.cpp | `drivers/png/png_driver_common.cpp` | ソース | image_to_png()実装 |
| file_access.h | `core/io/file_access.h` | ヘッダー | ファイルI/O基盤クラス |
