diff --git a/Configuration/AppSettings.cs b/Configuration/AppSettings.cs index 1f5b3cb..72f3307 100644 --- a/Configuration/AppSettings.cs +++ b/Configuration/AppSettings.cs @@ -1,4 +1,7 @@ +using System; using System.Drawing; +using System.Globalization; +using System.IO; namespace LensAdjustmentTool.Configuration { @@ -31,4 +34,46 @@ public const string DeviceProfileRelativePath = @"Config\DFK33UX178.xml"; public const string ExpectedDeviceNameFragment = "DFK 33UX178"; } + + public sealed class ApertureRoiSettingsStore + { + private const string FileName = "ApertureRoi.txt"; + + private string FilePath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FileName); + + public Rectangle? Load() + { + if (!File.Exists(FilePath)) + return null; + + string text = File.ReadAllText(FilePath).Trim(); + string[] parts = text.Split(','); + if (parts.Length != 4) + return null; + + int x; + int y; + int width; + int height; + if (!int.TryParse(parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out x) || + !int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out y) || + !int.TryParse(parts[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out width) || + !int.TryParse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out height)) + { + return null; + } + + return new Rectangle(x, y, width, height); + } + + public void Save(Rectangle roi) + { + string text = string.Join(",", + roi.X.ToString(CultureInfo.InvariantCulture), + roi.Y.ToString(CultureInfo.InvariantCulture), + roi.Width.ToString(CultureInfo.InvariantCulture), + roi.Height.ToString(CultureInfo.InvariantCulture)); + File.WriteAllText(FilePath, text); + } + } } diff --git a/MainForm.cs b/MainForm.cs index 219b112..e247432 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -17,6 +17,7 @@ private readonly LatestResultMailbox _mailbox; private readonly LensAdjustmentProcessor _processor; private readonly IcImagingCameraService _camera; + private readonly ApertureRoiSettingsStore _apertureRoiSettingsStore; private readonly Timer _uiTimer; private TabControl _tabs; @@ -47,6 +48,7 @@ _logger = new AppLogger(); _mailbox = new LatestResultMailbox(); _processor = new LensAdjustmentProcessor(); + _apertureRoiSettingsStore = new ApertureRoiSettingsStore(); _camera = new IcImagingCameraService(icImagingControl1, _processor, _mailbox, _logger); _uiTimer = new Timer { Interval = AppSettings.UiRefreshIntervalMs }; @@ -406,6 +408,7 @@ SetSplitterDistance(_apertureSplit); //Text = "フォーカス調整 \u2014 Lens Adjustment Tool"; _logger.Info("Application start."); + RestoreApertureRoi(); _processor.SetMode(AdjustmentMode.Focus, resetFocusMaximum: true); _camera.InitializeAndStart(AppDomain.CurrentDomain.BaseDirectory); _cameraInfoLabel.Text = _camera.CameraInfo?.ToString() ?? string.Empty; @@ -455,9 +458,32 @@ var button = (Button)sender; var delta = (Point)button.Tag; Rectangle roi = _processor.MoveApertureCalculationRoi(delta.X, delta.Y); + SaveApertureRoi(roi); _logger.Info($"Aperture ROI moved to ({roi.X}, {roi.Y})."); } + private void RestoreApertureRoi() + { + Rectangle? roi = _apertureRoiSettingsStore.Load(); + if (!roi.HasValue) + return; + + Rectangle applied = _processor.SetApertureCalculationRoi(roi.Value); + _logger.Info($"Aperture ROI restored to ({applied.X}, {applied.Y})."); + } + + private void SaveApertureRoi(Rectangle roi) + { + try + { + _apertureRoiSettingsStore.Save(roi); + } + catch (Exception ex) + { + _logger.Warn("Failed to save aperture ROI." + Environment.NewLine + ex.Message); + } + } + private void UiTimer_Tick(object sender, EventArgs e) { _cameraStatusLabel.Text = "Camera: " + _camera.StatusText; @@ -519,6 +545,7 @@ _logger.Error("Error while stopping camera.", ex); } + SaveApertureRoi(_processor.GetApertureCalculationRoi()); _mailbox.Clear(); ReplacePicture(_focusPicture, null); ReplacePicture(_aperturePicture, null); diff --git a/Processing/LensAdjustmentProcessor.cs b/Processing/LensAdjustmentProcessor.cs index 468d4b4..09a122c 100644 --- a/Processing/LensAdjustmentProcessor.cs +++ b/Processing/LensAdjustmentProcessor.cs @@ -39,24 +39,33 @@ { lock (_apertureRoiSync) { - Rectangle displayRoi = AppSettings.ApertureDisplayRoi; - int x = Math.Max( - displayRoi.X, - Math.Min(_apertureCalculationRoi.X + deltaX, displayRoi.Right - _apertureCalculationRoi.Width)); - int y = Math.Max( - displayRoi.Y, - Math.Min(_apertureCalculationRoi.Y + deltaY, displayRoi.Bottom - _apertureCalculationRoi.Height)); - - _apertureCalculationRoi = new Rectangle( - x, - y, + _apertureCalculationRoi = NormalizeApertureCalculationRoi(new Rectangle( + _apertureCalculationRoi.X + deltaX, + _apertureCalculationRoi.Y + deltaY, _apertureCalculationRoi.Width, - _apertureCalculationRoi.Height); + _apertureCalculationRoi.Height)); return _apertureCalculationRoi; } } + public Rectangle SetApertureCalculationRoi(Rectangle roi) + { + lock (_apertureRoiSync) + { + _apertureCalculationRoi = NormalizeApertureCalculationRoi(roi); + return _apertureCalculationRoi; + } + } + + public Rectangle GetApertureCalculationRoi() + { + lock (_apertureRoiSync) + { + return _apertureCalculationRoi; + } + } + public FrameAnalysisResult Process(IFrameQueueBuffer frame) { if (frame == null) throw new ArgumentNullException(nameof(frame)); @@ -153,12 +162,14 @@ } } - private Rectangle GetApertureCalculationRoi() + private static Rectangle NormalizeApertureCalculationRoi(Rectangle roi) { - lock (_apertureRoiSync) - { - return _apertureCalculationRoi; - } + Rectangle displayRoi = AppSettings.ApertureDisplayRoi; + int width = Math.Min(roi.Width, displayRoi.Width); + int height = Math.Min(roi.Height, displayRoi.Height); + int x = Math.Max(displayRoi.X, Math.Min(roi.X, displayRoi.Right - width)); + int y = Math.Max(displayRoi.Y, Math.Min(roi.Y, displayRoi.Bottom - height)); + return new Rectangle(x, y, width, height); } private static Bitmap Clone24(Bitmap source, Rectangle roi)