========================================================================
カメラ制御仕様 (Camera Control Specification)
========================================================================

1. 起動時のカメラ接続フロー (Startup Connection Flow)
------------------------------------------------------------------------
Form1 ロード時に以下の順で接続を試みる．

1. Lucam.Connect() を実行する
    ・成功: Lucam をアクティブカメラとして使用する
    ・失敗: 次へ

2. ImagingSource デバイス一覧を走査する
    ・接続されているデバイス名を順に IScam.Connect() で試行する
    ・最初に成功したカメラをアクティブカメラとして使用する

3. どのカメラも接続できない場合
    ・エラーダイアログを表示してアプリを終了する


2. IScam（ImagingSource カメラ）の制御 (IScam Control)
------------------------------------------------------------------------

2-1. 接続
    ・`[デバイス名].xml` からカメラ設定をロードする．
    ・`config.xml` の `<カメラ名>/ROI` から ROI 設定を読み込む．
    ・`FrameQueueSink` をシンクに設定してライブ開始する．

2-2. プレビュー（フレーム取得コールバック）
    ・`FrameQueueSink` の `Retrieve` コールバックでフレームを受け取る．
    ・受け取った画像を転置（`.T()`）し，ROI を切り出して表示する．
    ・キャリブレーション中は白色票の測定・ゲイン更新も行う（後述）．

2-3. ROI クリップ
    ・ImagingSource カメラは横向きに画像を出力するため，転置して縦向きに変換する．
    ・転置後の画像座標系で ROI（X，Y，W，H）を切り出す．

2-4. 撮影
    ・シンクを `FrameQueueSink` → `FrameSnapSink` に切り替える．
    ・`SnapSingle()` で1フレームずつ取得して `_shots` に蓄積する．
    ・撮影完了後，シンクを `FrameQueueSink` に戻す．
    ・最初の1フレームは捨てる（カメラの安定待ち）．


3. Lucam（Lumenera カメラ）の制御 (Lucam Control)
------------------------------------------------------------------------

3-1. 接続
    ・`LucamNumCameras()` で接続台数を確認する（0台または2台以上はエラー）．
    ・カメラ ID から機種を特定する（`0x49f` → Lw110）．
    ・`LucamRgbPreviewCallback` コールバックを登録する．
    ・`config.xml` の `<Lucam>` からカメラパラメータを設定して，プレビューを開始する．

3-2. プレビュー（フレーム取得コールバック）
    ・`LucamRgbPreviewCallback` でフレームを受け取る．
    ・受け取った画像を転置（`.T()`）して表示する（ROI クリップなし）．
    ・キャリブレーション中は白色票の測定・ゲイン更新も行う（後述）．

3-3. 撮影
    ・`LucamEnableFastFrames()` でスナップ撮影モードに切り替える．
    ・`LucamTakeFastFrame()` でRAW画像を取得し，`LucamConvertFrameToRgb24()` でRGB変換する．
    ・撮影完了後，`LucamDisableFastFrames()` で通常モードに戻す．


4. ホワイトバランス自動調整 (White Balance Calibration)
------------------------------------------------------------------------
チャート検出後（`_calibrating` が `Calib/Frames` にセットされた後），
各フレームで以下の処理を行う．

1. 白色票（`_chartMasks[12]`，24色票の13番）の平均 RGB 値を測定する

2. `Calib/UpdateInterval` フレームごとにゲインを更新する
    ・更新比率: `ratio = (target / current - 1) * UpdateRate + 1`
    ・IScam: `VCDRangeProperty.Value` を直接更新する
    ・Lucam: `_snap.Gain*` を更新し `SetCameraParam()` で反映する

3. `_calibrating` をデクリメントし，0 になったら `CalcTcc()` を呼び出す


5. データ保存フォルダの生成 (Save Folder)
------------------------------------------------------------------------
`SetSaveFolder(note)` が保存先フォルダを以下の書式で生成する．

    [SaveFolder]/[yyyy-MM-dd]/[HH_mm_ss]-[note]/

・`SaveFolder` は `config.xml` の `<File/SaveFolder>` で指定する．
・`note` は「データ名」（撮影時）または「校正」（キャリブ時）．
・フォルダが存在しない場合は自動作成する．
