# 画面設計書 76-WriteableBitmap

## 概要

本ドキュメントは、RenderDemoアプリケーションにおけるWriteableBitmap（書き込み可能ビットマップ）ページの画面設計を定義するものです。このページは、Avaloniaフレームワークが提供するピクセル操作可能なビットマップ機能と、アルファフォーマット（Premultiplied/Unpremultiplied）の違いを視覚的にデモンストレーションします。

### 本画面の処理概要

**業務上の目的・背景**：動的な画像生成やピクセル単位の処理が必要なアプリケーション（画像エディタ、グラフ描画、ゲーム等）では、WriteableBitmapを使用してピクセルデータを直接操作することが求められます。特に、アルファチャンネルの扱い方（Premultiplied Alpha vs Unpremultiplied Alpha）は描画結果に大きな影響を与えるため、本画面は両形式の違いを視覚的に比較し、開発者が正しい実装を学習できるようにすることを目的としています。

**画面へのアクセス方法**：RenderDemoアプリケーションを起動後、左側のHamburgerMenuから「WriteableBitmap」タブを選択することでアクセスできます。

**主要な操作・処理内容**：
1. 画面がロジカルツリーにアタッチされた時点で2つの256x256ピクセルWriteableBitmapを作成（Unpremul/Premul）
2. 各フレームで緑色のピクセルをアルファ値を変化させながら両ビットマップに書き込み
3. 左側にUnpremultiplied Alpha、中央にPremultiplied Alpha、右側に参照用のSolidColorBrushを表示
4. 背景は赤色で、アルファブレンディングの効果を視覚的に確認可能

**画面遷移**：
- 遷移元：RenderDemo MainWindow（HamburgerMenuより選択）
- 遷移先：なし（デモページのため画面遷移機能は持たない）

**権限による表示制御**：本画面はデモ用途のため、権限による表示制御は実装されていません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 80 | Image | 主機能 | WriteableBitmapのデモ。ピクセル操作可能なビットマップ |

## 画面種別

デモ / ピクセル操作・アルファフォーマット比較表示

## URL/ルーティング

本アプリケーションはデスクトップアプリケーションのため、URLルーティングは使用しません。
HamburgerMenuのタブ選択により画面切り替えが行われます。

## 入出力項目

本画面はデモ表示専用のため、ユーザー入力項目はありません。

| 項目名 | 入力/出力 | 型 | 説明 |
|--------|----------|-----|------|
| なし | - | - | 表示専用画面 |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Unpremultiplied Bitmap | WriteableBitmap | 256x256ピクセル、AlphaFormat.Unpremul、緑色のアルファアニメーション |
| Premultiplied Bitmap | WriteableBitmap | 256x256ピクセル、AlphaFormat.Premul、緑色のアルファアニメーション |
| 参照用矩形 | Rectangle | SolidColorBrush(Lime)、アルファアニメーション、比較用 |
| 背景 | Rectangle | 赤色、256x3=768ピクセル幅、アルファブレンディング効果の確認用 |

## イベント仕様

### 1-ロジカルツリーアタッチ時

コントロールがロジカルツリーにアタッチされた際にWriteableBitmapを初期化します。

**処理フロー**:
1. OnAttachedToLogicalTreeが呼ばれる
2. _unpremulBitmap = new WriteableBitmap(256x256, 96dpi, Bgra8888, Unpremul)を作成
3. _premulBitmap = new WriteableBitmap(256x256, 96dpi, Bgra8888, Premul)を作成
4. base.OnAttachedToLogicalTreeを呼び出し

### 2-ロジカルツリーデタッチ時

コントロールがロジカルツリーからデタッチされた際にリソースを解放します。

**処理フロー**:
1. OnDetachedFromLogicalTreeが呼ばれる
2. base.OnDetachedFromLogicalTreeを呼び出し
3. _unpremulBitmapをDispose、nullに設定
4. _premulBitmapをDispose、nullに設定

### 3-フレーム描画時

各フレームでピクセル書き込みと画面描画を実行します。

**処理フロー**:
1. Render(DrawingContext)が呼ばれる
2. アルファ値を計算（経過時間に基づき0-255をループ）
3. FillPixels関数で両ビットマップにピクセルデータを書き込み
4. FillRectangle(Red)で背景を描画
5. DrawImageで両ビットマップを描画（X=0, X=256）
6. FillRectangle(Lime, alpha)で参照用矩形を描画（X=512）
7. Dispatcher.UIThread.Postで次フレーム描画を要求

## データベース更新仕様

本画面はデモ表示専用のため、データベース操作は行いません。

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | データベース操作なし |

## メッセージ仕様

本画面はデモ表示専用のため、メッセージ表示機能はありません。

| メッセージID | 種別 | 内容 | 表示条件 |
|-------------|------|------|---------|
| なし | - | - | - |

## 例外処理

| 例外 | 対処 |
|------|------|
| ビットマップがnull | Renderメソッドで早期リターン |
| レンダリングエラー | Avaloniaフレームワークの標準エラーハンドリングに委譲 |

## 備考

- **Premultiplied Alpha**: RGBチャンネルの値がアルファ値で事前に乗算されている形式。GPUレンダリングで標準的に使用される
- **Unpremultiplied Alpha**: RGBチャンネルの値がそのまま保持されている形式。画像編集ソフトウェアで一般的
- ピクセルフォーマットはBgra8888（Blue-Green-Red-Alpha、各8ビット）
- Marshal.Copyを使用してマネージド配列からネイティブメモリにコピー
- Color.ToUInt32()でカラー値をピクセルデータに変換
- 3つの表示が同じ見た目になれば、アルファフォーマットの処理が正しいことを意味する

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

WriteableBitmapとアルファフォーマットの関係を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WriteableBitmapPage.cs | `samples/RenderDemo/Pages/WriteableBitmapPage.cs` | 2つのWriteableBitmap（Unpremul/Premul）の定義を確認 |

**読解のコツ**: AlphaFormatはAvaloniaのPixelFormat指定と組み合わせて使用します。Premulの場合、RGB値はアルファ値で乗算して設定する必要があります。

#### Step 2: エントリーポイントを理解する

コントロールの初期化とライフサイクルを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | WriteableBitmapPage.cs | `samples/RenderDemo/Pages/WriteableBitmapPage.cs` | OnAttachedToLogicalTree/OnDetachedFromLogicalTreeでのリソース管理を確認 |

**主要処理フロー**:
1. **行20-26**: OnAttachedToLogicalTreeで2つのWriteableBitmapを作成
2. **行28-37**: OnDetachedFromLogicalTreeでDispose処理

#### Step 3: ピクセル書き込み処理を理解する

FillPixels関数のアルファ処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | WriteableBitmapPage.cs | `samples/RenderDemo/Pages/WriteableBitmapPage.cs` | FillPixels関数内のPremul/Unpremul分岐処理を確認 |

**主要処理フロー**:
- **行44-71**: FillPixelsローカル関数の定義
- **行46**: bitmap.Lock()でフレームバッファをロック
- **行54-62**: Premulの場合、R/G/B値をアルファで乗算
- **行69**: Marshal.Copyでピクセルデータをコピー

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

```
MainWindow
    |
    +-- HamburgerMenu (controls:HamburgerMenu)
           |
           +-- TabItem[Header="WriteableBitmap"]
                  |
                  +-- WriteableBitmapPage (Control)
                         |
                         +-- OnAttachedToLogicalTree
                         |      |
                         |      +-- new WriteableBitmap(..., AlphaFormat.Unpremul)
                         |      +-- new WriteableBitmap(..., AlphaFormat.Premul)
                         |
                         +-- Render(DrawingContext)
                         |      |
                         |      +-- FillPixels(_unpremulBitmap, alpha, false)
                         |      |      |
                         |      |      +-- bitmap.Lock()
                         |      |      +-- Marshal.Copy(data, fb.Address)
                         |      |
                         |      +-- FillPixels(_premulBitmap, alpha, true)
                         |      |      |
                         |      |      +-- R/G/B *= alpha/255
                         |      |
                         |      +-- context.FillRectangle(Red, 背景)
                         |      +-- context.DrawImage(_unpremulBitmap)
                         |      +-- context.DrawImage(_premulBitmap)
                         |      +-- context.FillRectangle(Lime, alpha)
                         |      +-- Dispatcher.Post(InvalidateVisual)
                         |
                         +-- OnDetachedFromLogicalTree
                                |
                                +-- _unpremulBitmap?.Dispose()
                                +-- _premulBitmap?.Dispose()
```

### データフロー図

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

Stopwatch           --> alpha計算           --> byte (0-255)
(経過時間)              (% 256)

Color(A,0,255,0)    --> FillPixels         --> ピクセルデータ
+ アルファ値            (Premul/Unpremul)

WriteableBitmap     --> Lock() + Marshal   --> フレームバッファ更新
(256x256)               .Copy()

フレームバッファ     --> DrawImage          --> 画面表示
                                               (3領域比較)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WriteableBitmapPage.cs | `samples/RenderDemo/Pages/WriteableBitmapPage.cs` | C# | ピクセル操作可能ビットマップを実装したControl |
| MainWindow.xaml | `samples/RenderDemo/MainWindow.xaml` | XAML | ホスト画面（HamburgerMenuでページを管理） |
