using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using TIS.Imaging;
using System.Windows.Forms;
namespace ISCamRecorder {
internal class ISCamera {
readonly string ICCF_FILE = @"dfk33ux290.iccf"; // 設定ファイル
readonly string CAMERA_FORMAT = "RGB32 (1920x1080)"; // 設定ファイル無い時の解像度
readonly float FRAME_RATE = 40F; // 設定ファイル無い時のFPS
ICImagingControl _Cam; // カメラオブジェクト
string _SerialNumber; // シリアル番号
VCDButtonProperty _Trigger; // トリガー設定
FrameRateCounter _Fps = new FrameRateCounter(10); // フレームレート計測
SinkListener _SinkListener = new SinkListener();
FrameQueueSink _PreviewSink;
FrameQueueSink _RecSink;
IFrameQueueBuffer[] _bufferlist;
public float FrameRate { get { return _Fps.FrameRate; } }
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="cameraControl"></param>
/// <param name="serialNumber"></param>
public ISCamera(ICImagingControl cameraControl, string serialNumber) {
_Cam = cameraControl;
_SerialNumber = serialNumber;
}
/// <summary>
/// カメラ接続とプレビュー開始
/// </summary>
/// <returns></returns>
public bool Connect() {
if (_Cam.DeviceValid) return true;
// 接続
_Cam.Device = _Cam.Devices.FirstOrDefault(
c => c.GetSerialNumber().Equals(_SerialNumber));
if (!_Cam.DeviceValid) return false;
// 撮影条件設定
try {
if (File.Exists(ICCF_FILE)){
_Cam.LoadDeviceState(ICCFImport.Import(ICCF_FILE), false);
Debug.WriteLine($"Camera #{_SerialNumber} loaded config {ICCF_FILE}");
} else {
//Debug.WriteLine($"Can't find config {ICCF_FILE}");
_Cam.VideoFormat = _Cam.VideoFormats.FirstOrDefault(
c => c.Name.Equals(CAMERA_FORMAT));
_Cam.DeviceFrameRate = _Cam.DeviceFrameRates.FirstOrDefault(
c => (c > FRAME_RATE - 0.1F && c < FRAME_RATE + 0.1F));
Debug.WriteLine($"Camera #{_SerialNumber} sets {_Cam.VideoFormat}, {_Cam.DeviceFrameRate:0.0}fps");
}
} catch (ICException iex) {
MessageBox.Show(iex.Message, "Camera Error",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
// 表示設定
_Cam.LiveDisplayDefault = false;
SetDisplaySize();
_Cam.ImageRingBufferSize = 5;
_Trigger = _Cam.VCDPropertyItems.Find<VCDButtonProperty>(
VCDGUIDs.VCDID_TriggerMode, VCDGUIDs.VCDElement_SoftwareTrigger);
_RecSink = new FrameQueueSink(_SinkListener, MediaSubtypes.RGB32);
_PreviewSink = new FrameQueueSink(CaptureFrame, MediaSubtypes.RGB32, 5);
_Cam.Sink = _PreviewSink;
_Cam.LiveStart();
return true;
}
/// <summary>
/// Sink変更
/// </summary>
/// <param name="isRec">true:録画 false:プレビュー</param>
public void ChangeSink(bool isRec) {
_Cam.LiveStop();
if (isRec) _Cam.Sink = _RecSink;
else _Cam.Sink = _PreviewSink;
_Cam.LiveStart();
}
/// <summary>
/// 録画
/// </summary>
public void RecordToMemory() {
Debug.WriteLine($"Cam {_SerialNumber} starts recoding.");
var framesToCapture = 30;
_RecSink.AllocAndQueueBuffers(framesToCapture);
while (true) {
if (framesToCapture <= _RecSink.OutputQueueSize + 1) break;
}
_bufferlist = _RecSink.PopAllOutputQueueBuffers();
Debug.WriteLine($"Cam {_SerialNumber} buffersize {_bufferlist.Length}.");
for (int i = 0; i < _bufferlist.Length; i++) {
//デバイスが生成したフレーム番号が格納されます。
string strFrameNumber = _bufferlist[i].FrameMetadata.DeviceFrameNumber.ToString();
//(有効な場合)デバイスのタイムスタンプが格納されます。
// デバイス固有のタイムソースによるタイムスタンプです。
string strDeviceTimeStamp = _bufferlist[i].FrameMetadata.DeviceTimeStamp.ToString();
//このフレームの最初のパケットをドライバが受信した時刻が格納されます。
string strSampleStartTime = _bufferlist[i].FrameMetadata.DriverFrameFirstPacketTime.ToString(@"hhmmss\.fff");
//ドライバがこのフレームに与えたフレーム番号が格納されます。
string strDriverFrameNumber = _bufferlist[i].FrameMetadata.DriverFrameNumber.ToString();
var fileName = $"Cam{_SerialNumber.Substring(_SerialNumber.Length-2)}_" + strSampleStartTime + ".jpg";
TIS.Imaging.FrameExtensions.SaveAsJpeg(_bufferlist[i], fileName, 80);
}
_bufferlist = null;
GC.Collect();
Debug.WriteLine($"Cam {_SerialNumber} ends recoding.");
}
/// <summary>
/// 表示サイズ設定
/// </summary>
public void SetDisplaySize() {
if (!_Cam.DeviceValid) return;
var vf = _Cam.VideoFormatCurrent;
if (vf.Height * _Cam.Width < vf.Width * _Cam.Height) {
_Cam.LiveDisplayLeft = 0;
_Cam.LiveDisplayWidth = _Cam.Width;
var h = vf.Height * _Cam.Width / vf.Width;
_Cam.LiveDisplayTop = (_Cam.Height - h) / 2;
_Cam.LiveDisplayHeight = h;
} else {
_Cam.LiveDisplayTop = 0;
_Cam.LiveDisplayHeight = _Cam.Width;
var w = vf.Width * _Cam.Height / vf.Height;
_Cam.LiveDisplayLeft = (_Cam.Width - w) / 2;
_Cam.LiveDisplayWidth = w;
}
}
/// <summary>
/// フレーム取得時
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
private FrameQueuedResult CaptureFrame(IFrameQueueBuffer buffer) {
_Fps.Shot();
return FrameQueuedResult.ReQueue;
}
/// <summary>
/// トリガーモード変更
/// </summary>
/// <param name="enable"></param>
public void SetTriggerMode(bool enable) {
_Cam.LiveStop();
_Cam.DeviceTrigger = enable;
_Cam.LiveStart();
}
/// <summary>
/// ソフトウェアトリガー発信
/// </summary>
public void SWTrigger() {
if (_Cam.DeviceValid && _Trigger != null) _Trigger.Push();
}
/// <summary>
/// プロパティ設定(ダイアログ)
/// </summary>
/// <returns></returns>
public string SetProperty() {
if (!_Cam.DeviceValid) return "";
_Cam.ShowPropertyDialog();
return _Cam.SaveDeviceState();
}
/// <summary>
/// プロパティ設定(条件指定)
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public string SetProperty(string config) {
if (!_Cam.DeviceValid) return "";
_Cam.LiveStop();
_Cam.LoadDeviceState(config, false);
_Cam.LiveStart();
return config;
}
/// <summary>
/// カメラ情報文字列
/// </summary>
/// <returns></returns>
public string CameraInfo() {
return $"({_SerialNumber}) {_Fps.FrameRate:0.0}fps";
}
/// <summary>
/// 1秒録画に要するメモリ量
/// </summary>
/// <returns></returns>
public float MemoryFor1SecRecoding() {
if (!_Cam.DeviceValid) return 0;
var vf = _Cam.VideoFormatCurrent;
int frameSize = vf.BitsPerPixel / 8 * vf.Width * vf.Height;
int bcs = 1024 * 1024;
return _Fps.FrameRate * frameSize / bcs;
}
}
}