状況: 初期バージョンのアプリ(撮影画面 + 一覧画面)が動作する状態に到達
動機: TIAS(積分球を用いた大型装置)のスマホ版として研究メンバー向け撮影アプリを立ち上げる.PC 側で解析するため,スマホ側は撮影・保存に特化(PLAN_01 要件定義書参照)
状況: YUV→PNG 変換を Android ネイティブに移行.非圧縮 PNG + 回転統合により 15 秒 → 約 2 秒に短縮
動機: Dart の image パッケージで PNG エンコードが遅く撮影フローが詰まっていた
設計判断: 非圧縮 PNG(Deflater.NO_COMPRESSION)を選択.圧縮率より速度優先.研究用途で 1 ショット数 MB は許容
失敗パターン: 当初 Dart の isolate で並列化を検討したが,Plane バイトの copy オーバーヘッドで思ったほど速くならなかった
状況: 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 から取得する設計に変更
状況: シャッターで 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× が解消しない問題.原因は SmTIAS-Capture 通常モードが 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 も全体上書きせず進捗欄だけ二段構成に書き換え.既存進捗エントリは本ファイルへ移植
状況: 撮影 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 の生成元を「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 検証
状況: 実装報告 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 で不整合リスク
状況: 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)へ
状況: v1.0.0(撮影・保存・一覧)以降に積み上げた機能群(ネイティブ高速化・カメラ診断・DNG 定量モード・プレビュー JPEG・画素統計/Hot pixel map)を一区切りとし v1.1.0 を採番(pubspec 1.0.0+1 → 1.1.0+2).併せてリリース整理を実施
動機: 開発が一区切りついたため,ドキュメントの陳腐化解消・コード品質改善・正式名称への統一を行い,新バージョンとして保存する
ドキュメント: README/CLAUDE.md/ENV/PLAN を定量モード現状に更新.SPEC_01 を3分割(画面 / カメラ撮影 / アーキテクチャ・非機能).05_TECH の往復書簡 TECH_01/03/04 を1本(設計の経緯と合意)に統合し TECH_02(引き継ぎ手順)は役目終了で削除.参考画像 DSC_0066.JPG を local_reference/(gitignore)へ退避
リファクタリング: Dart は PreviewFrame 型導入・build のオーバーレイ抽出(テスト 79 件維持).Kotlin は肥大化した RawCapturePlugin.kt を 1184→856 行に縮小し,純粋処理を 4 object(PngEncoder/YuvJpegConverter/ImageStatistics/CaptureMetadata)へ抽出
テスト: ImageStatistics の数理ロジック(mean/max/p99/飽和率)を実機不要の JUnit で検証(./gradlew test).GUIDE_07 に方針追記
リネーム: 正式名称 SmTIAS に合わせ MiniTIAS → SmTIAS-Capture (GitHub リポジトリ名・ローカルフォルダ・Dart パッケージ smtias_capture・Android com.example.smtias_capture・全プラットフォーム製品名・ドキュメント表記)
設計判断: SmTIAS-LightSim とのデータ契約(保存接頭辞 MiniTIAS_QM_・保存先 Pictures/MiniTIAS/)は突合互換のため意図的に維持
検証: dart analyze 0 件 / dart format 差分なし / flutter test 79 件 / flutter build apk --debug 成功 / gradle 単体テスト通過