# 開発進捗ログ

<!--
本ファイルは追記型のフル進捗ログ．

- 最新エントリは下に追記する（時系列順．古いものが上，新しいものが下）
- CLAUDE.md の「開発進捗」セクションは最新 1 行のみ（上書き運用）
- 詳細・失敗パターン・設計判断はすべて本ファイルに残す
- 書式・運用ルールは docs/01_GUIDE/GUIDE_05_エージェント運用ルール.md
  「進捗記録の運用ルール（CLAUDE.md / PROGRESS.md）」を参照
-->

## Step 1〜5: 撮影・保存・一覧・削除の実装

- 状況: 初期バージョンのアプリ（撮影画面 + 一覧画面）が動作する状態に到達
- 動機: TIAS（積分球を用いた大型装置）のスマホ版として研究メンバー向け撮影アプリを立ち上げる．PC 側で解析するため，スマホ側は撮影・保存に特化（PLAN_01 要件定義書参照）

## 撮影→保存の高速化

- 状況: YUV→PNG 変換を Android ネイティブに移行．非圧縮 PNG + 回転統合により 15 秒 → 約 2 秒に短縮
- 動機: Dart の image パッケージで PNG エンコードが遅く撮影フローが詰まっていた
- 設計判断: 非圧縮 PNG（Deflater.NO_COMPRESSION）を選択．圧縮率より速度優先．研究用途で 1 ショット数 MB は許容
- 失敗パターン: 当初 Dart の isolate で並列化を検討したが，Plane バイトの copy オーバーヘッドで思ったほど速くならなかった

## カメラ診断機能の追加（インフラのみ・UI 非表示）

- 状況: `DiagnosticsProvider` / `RawCaptureService.getCameraDiagnostics` / `FileService.saveDiagnosticsJson` を追加．UI ボタンは出さず将来再利用に備えて温存
- 動機: 定量モード撮影を実装する前提として，実機 AQUOS sense3 の Camera2 能力（HW Level・MANUAL_SENSOR/POST_PROCESSING の有無・RAW 出力可否・LSC マップ取得可否）を一度きっちり確認したかった
- 結果: AQUOS sense3 フロントカメラは **HW Level 3 + RAW + MANUAL_SENSOR + MANUAL_POST_PROCESSING** 対応．診断結果 JSON は `docs/06_TEST/camera_diagnostics_20260531_161734.json` に保存
- 失敗パターン: `LENS_INFO_SHADING_MAP_SIZE` は hidden API でビルドエラー．`STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES` で代替判定 + 実キャプチャ後に CaptureResult から取得する設計に変更

## 定量モード撮影機能（DNG 経路）完成

- 状況: シャッターで `MiniTIAS_QM_YYYYMMDD_HHmmss.dng`（10-bit BGGR Bayer 3264×2448，約 16MB）と `.meta.json`（settings/actual/sensorCharacteristics/lscMap）を `Pictures/MiniTIAS/` に保存．既存 PNG 経路は `captureFullResolutionPng` として温存
- 動機: SmTIAS-LightSim 側でのシミュ vs 実機の定量比較で残差 2.1× が解消しない問題．原因は MiniTIAS 通常モードが AE/AWB/NR/EDGE/TONEMAP 全自動で撮影ごとに値が揺らいでいたこと（TECH_01 参照）
- 設計判断: Camera2 マニュアル制御で `CONTROL_MODE=OFF` + AE/AWB/AF/NR/EDGE OFF + TONEMAP 線形 + 露光 1/60s 固定 + ISO 40 固定．`SHADING_MODE` は HIGH_QUALITY を採用（LSC マップ実値を取りたいため．OFF だと単位マップしか返らない）．フォーマットは DNG (RAW_SENSOR) を採用（8bit PNG では舌の色再現には情報量不足）
- 失敗パターン: ① MTP コピー直後の DNG が PC で 0 バイトに見える→「MethodChannel 16MB 転送が失敗」と誤診断．実際は MTP コピー遅延で，30 秒待てば全データあった．② `SHADING_MODE = OFF` 初回採用で LSC マップが全 1.0（Android 仕様）→ HIGH_QUALITY に変更で実値取得
- 後段: 露光時間・ISO のキャリブ機能（白板撮影で AE 一回走らせて値を固定する半自動モード），撮影連射再現性検証 V1（CoV < 1%），他機種展開時の `getCameraDiagnostics` 再実行

## テンプレート同期

- 状況: programming-template から進捗記録の二段構成（CLAUDE.md 1 行 + PROGRESS.md 追記ログ）と関連スラッシュコマンド・ガイド更新を取り込み
- 動機: テンプレート側で進捗記録ルールが更新された．CLAUDE.md が毎ターン読み込まれることを考えると履歴を切り離す設計は合理的
- 設計判断: `.gitignore` はテンプレート版（ミニマル）を採用せず Flutter 用エントリを温存．`CLAUDE.md` も全体上書きせず進捗欄だけ二段構成に書き換え．既存進捗エントリは本ファイルへ移植

## DNG プレビュー JPEG 機能を追加

- 状況: 撮影 1 回で `.preview.jpg`（1632×1224，100〜300KB）を `.dng` と並べて保存．一覧画面で表示・拡大できる．削除時は dng / meta.json と連動
- 動機: DNG は Flutter `Image.file` でデコードできずアプリ内で撮影結果を確認できなかった．研究者が「ちゃんと撮れたか」を端末上で判断できるようにする
- 設計判断: 別ファイル方式（案 B）を採用．案 A（DNG 内サムネ）は Dart で TIFF パーサが必要で実装重い．案 C（マルチストリーム + JPEG）は ISP のフルパイプライン処理が混じり研究データの位置付けが曖昧になる．案 B は Kotlin で Bayer→2×2 demosaic→ガンマ 2.2 で JPEG 化するだけのシンプル実装で，DNG 本体は無変更で済む
- 失敗パターン: なし（実機で意図通り動作）
- 既知の課題: プレビューが緑がかる．原因はおそらく WB 未適用（COLOR_CORRECTION_GAINS=identity）と BGGR の G チャネルが 2 サンプル平均で他より重み付けされる効果の組み合わせ．プレビュー画質の話なので DNG 解析には影響しない
- 後段: 緑かぶり改善（グレーワールド WB or AsShotNeutral 反映）．露光時間キャリブ機能．連射再現性検証 V1

## プレビュー JPEG をライブビュー（自動 ISP）スナップショットに切替

- 状況: プレビュー JPEG の生成元を「Kotlin Bayer demosaic」から「`capturePreviewSnapshot` のライブプレビュー YUV→JPEG」に切替．Kotlin プラグインから約 200 行削除．Dart で `FileService.savePreviewJpeg` を追加し，`takePicture(previewBytes:)` でシャッター瞬間のスナップショットを保存
- 動機: 自前で Bayer→グレーワールド AWB→自動レベル→sRGB トーンカーブと再現したが，旧 PNG（フル ISP）の見た目に届かなかった．Camera2 ISP がフル稼働するライブプレビューと同じ絵を使えば一発で一致する．かつコードが大幅にシンプルになる
- 設計判断: ライブプレビューの絵を「研究データには使わない確認用」と割り切る．DNG は引き続きマニュアル制御の RAW．Preview のソースが自動 ISP かマニュアルかは独立に決められる．既存の `capturePreviewSnapshot` は保存中オーバーレイで既に使われていたので新規 API 追加なし
- 失敗パターン: ① 自前 demosaic + ガンマ 2.2 → 緑かぶり ② グレーワールド AWB → 緑かぶり解消だが暗い・フラット ③ 自動レベル + sRGB トーンカーブ → さらに改善も自動 ISP に届かない → ライブビュースナップショットを直接使う方針に転換．結果コード ~200 行削減 + ライブビュー完全一致
- 後段: 解像度がプレビュー由来（おそらく 1280×720）になるが研究用途では十分．画素統計 meta 追加，hot pixel マップ，連射機能 V1 検証

## SmTIAS-LightSim 側との合意（TECH_03/04）

- 状況: 実装報告 TECH_03 を SmTIAS-LightSim 側に送付 → 回答 TECH_04 受領．`docs/05_TECH/` に両方配置．
- 主要決定:
  - SHADING_MODE: **HIGH_QUALITY 維持**．Mitsuba orthographic 出力は「完璧に LSC 補正できた場合の理想値」相当のため HQ DNG と直接比較が物理整合．LSC マップは検証用に温存
  - 作業分け: **フェーズ A（1 ショット対応検証）→ フェーズ B（連射 V1）** の二段階．連射 UI はフェーズ B に降格
  - 露光・ISO 目安: 白板 mean = 400〜600（10-bit 黒レベル除去後），p99 < 836
  - 転送: adb pull 推奨．MTP は禁止しないが大容量 DNG で不整合リスク

## フェーズ A 対応（画素統計・Hot pixel map 追加，露光 1/120s 確定）

- 状況: meta.json に `image_statistics`（mean/max/p99/saturated_pixel_ratio per channel + thresholds）と `hot_pixel_map`（mode/count/coordinates）を追加．`STATISTICS_HOT_PIXEL_MAP_MODE = true` を CaptureRequest に追加．露光時間 1/60s → 1/120s に確定
- 動機: TECH_04 フェーズ A 要請．飽和判定の即時化と外れ値マスクのため
- 設計判断: 既存 `buildMetadataMap` のシグネチャ拡張（既定値 null で後方互換）．Bayer 2×2 BGGR 走査の中で 1 パスで mean/max/ヒストグラム/飽和率/低露光率を同時計算．p99 はチャネルごとに 256bin ヒストグラム → 累積で 99% 探索．Hot pixel map は `STATISTICS_HOT_PIXEL_MAP_MODE` が Android 仕様で Boolean 型（`*_ON` 定数は存在しない）．画素統計失敗時は `image_statistics: null` で続行（撮影成功は保証）
- 失敗パターン: 露光時間調整で 3 ステップ要した — ① 1/60s（初期値）→ 飽和率 21.7%（mean G 887）．完全に過露光 ② 1/250s → 飽和率 0% だが mean G 207（黒レベル除去後）と暗すぎ ③ 1/120s → mean G 461（黒レベル除去後）で TECH_04 目標 400〜600 中央．飽和率 0%．**線形領域に完全に収まる確定値**
- アタッチメント + LED ON 環境での測定値（基準値として記録）: mean R/G/B (raw) = 349/525/325，p99 G = 879，飽和率 0%，underexposed 0.002%
- 後段: フェーズ A サンプルを SmTIAS-LightSim 側 `reference_measurement/quantitative/` に adb pull 転送 → 1 ショット シミュ vs 実機の突合．残差が縮めばフェーズ B（連射 V1）へ
