add:issue #214
This commit is contained in:
@@ -18,6 +18,11 @@ namespace Ink_Canvas.Helpers
|
|||||||
private readonly object _frameLock = new object();
|
private readonly object _frameLock = new object();
|
||||||
private Dispatcher _dispatcher;
|
private Dispatcher _dispatcher;
|
||||||
|
|
||||||
|
// 新增属性
|
||||||
|
private int _rotationAngle = 0; // 0=0度,1=90度,2=180度,3=270度
|
||||||
|
private int _resolutionWidth = 640;
|
||||||
|
private int _resolutionHeight = 480;
|
||||||
|
|
||||||
public event EventHandler<Bitmap> FrameReceived;
|
public event EventHandler<Bitmap> FrameReceived;
|
||||||
public event EventHandler<string> ErrorOccurred;
|
public event EventHandler<string> ErrorOccurred;
|
||||||
|
|
||||||
@@ -25,6 +30,25 @@ namespace Ink_Canvas.Helpers
|
|||||||
public List<FilterInfo> AvailableCameras { get; private set; }
|
public List<FilterInfo> AvailableCameras { get; private set; }
|
||||||
public FilterInfo CurrentCamera { get; private set; }
|
public FilterInfo CurrentCamera { get; private set; }
|
||||||
|
|
||||||
|
// 新增属性
|
||||||
|
public int RotationAngle
|
||||||
|
{
|
||||||
|
get => _rotationAngle;
|
||||||
|
set => _rotationAngle = Math.Max(0, Math.Min(3, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ResolutionWidth
|
||||||
|
{
|
||||||
|
get => _resolutionWidth;
|
||||||
|
set => _resolutionWidth = Math.Max(320, Math.Min(1920, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ResolutionHeight
|
||||||
|
{
|
||||||
|
get => _resolutionHeight;
|
||||||
|
set => _resolutionHeight = Math.Max(240, Math.Min(1080, value));
|
||||||
|
}
|
||||||
|
|
||||||
public CameraService()
|
public CameraService()
|
||||||
{
|
{
|
||||||
_dispatcher = Dispatcher.CurrentDispatcher;
|
_dispatcher = Dispatcher.CurrentDispatcher;
|
||||||
@@ -32,6 +56,16 @@ namespace Ink_Canvas.Helpers
|
|||||||
RefreshCameraList();
|
RefreshCameraList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CameraService(int rotationAngle, int resolutionWidth, int resolutionHeight)
|
||||||
|
{
|
||||||
|
_dispatcher = Dispatcher.CurrentDispatcher;
|
||||||
|
AvailableCameras = new List<FilterInfo>();
|
||||||
|
_rotationAngle = rotationAngle;
|
||||||
|
_resolutionWidth = resolutionWidth;
|
||||||
|
_resolutionHeight = resolutionHeight;
|
||||||
|
RefreshCameraList();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 刷新可用摄像头列表
|
/// 刷新可用摄像头列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -242,14 +276,16 @@ namespace Ink_Canvas.Helpers
|
|||||||
var width = sourceFrame.Width;
|
var width = sourceFrame.Width;
|
||||||
var height = sourceFrame.Height;
|
var height = sourceFrame.Height;
|
||||||
|
|
||||||
if (width > 0 && height > 0)
|
if (width > 0 && height > 0)
|
||||||
{
|
{
|
||||||
_currentFrame = new Bitmap(width, height, PixelFormat.Format24bppRgb);
|
// 应用旋转
|
||||||
using (var graphics = Graphics.FromImage(_currentFrame))
|
Bitmap rotatedFrame = ApplyRotation(sourceFrame);
|
||||||
{
|
|
||||||
graphics.DrawImage(sourceFrame, 0, 0);
|
// 应用分辨率调整
|
||||||
}
|
_currentFrame = ResizeImage(rotatedFrame, _resolutionWidth, _resolutionHeight);
|
||||||
}
|
|
||||||
|
rotatedFrame?.Dispose();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_currentFrame = null;
|
_currentFrame = null;
|
||||||
@@ -300,6 +336,46 @@ namespace Ink_Canvas.Helpers
|
|||||||
return AvailableCameras.Count > 0;
|
return AvailableCameras.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用旋转到图像
|
||||||
|
/// </summary>
|
||||||
|
private Bitmap ApplyRotation(Bitmap source)
|
||||||
|
{
|
||||||
|
if (_rotationAngle == 0)
|
||||||
|
return new Bitmap(source);
|
||||||
|
|
||||||
|
var rotationType = RotateFlipType.RotateNoneFlipNone;
|
||||||
|
switch (_rotationAngle)
|
||||||
|
{
|
||||||
|
case 1: rotationType = RotateFlipType.Rotate90FlipNone; break;
|
||||||
|
case 2: rotationType = RotateFlipType.Rotate180FlipNone; break;
|
||||||
|
case 3: rotationType = RotateFlipType.Rotate270FlipNone; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rotated = new Bitmap(source);
|
||||||
|
rotated.RotateFlip(rotationType);
|
||||||
|
return rotated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调整图像大小
|
||||||
|
/// </summary>
|
||||||
|
private Bitmap ResizeImage(Bitmap source, int width, int height)
|
||||||
|
{
|
||||||
|
if (source.Width == width && source.Height == height)
|
||||||
|
return new Bitmap(source);
|
||||||
|
|
||||||
|
var resized = new Bitmap(width, height, PixelFormat.Format24bppRgb);
|
||||||
|
using (var graphics = Graphics.FromImage(resized))
|
||||||
|
{
|
||||||
|
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
|
||||||
|
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
|
||||||
|
graphics.DrawImage(source, 0, 0, width, height);
|
||||||
|
}
|
||||||
|
return resized;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
StopPreview();
|
StopPreview();
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ namespace Ink_Canvas
|
|||||||
public RandSettings RandSettings { get; set; } = new RandSettings();
|
public RandSettings RandSettings { get; set; } = new RandSettings();
|
||||||
[JsonProperty("modeSettings")]
|
[JsonProperty("modeSettings")]
|
||||||
public ModeSettings ModeSettings { get; set; } = new ModeSettings();
|
public ModeSettings ModeSettings { get; set; } = new ModeSettings();
|
||||||
|
[JsonProperty("camera")]
|
||||||
|
public CameraSettings Camera { get; set; } = new CameraSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Canvas
|
public class Canvas
|
||||||
@@ -682,4 +684,19 @@ namespace Ink_Canvas
|
|||||||
[JsonProperty("isPPTOnlyMode")]
|
[JsonProperty("isPPTOnlyMode")]
|
||||||
public bool IsPPTOnlyMode { get; set; } = false; // 是否为仅PPT模式,默认为false(正常模式)
|
public bool IsPPTOnlyMode { get; set; } = false; // 是否为仅PPT模式,默认为false(正常模式)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CameraSettings
|
||||||
|
{
|
||||||
|
[JsonProperty("rotationAngle")]
|
||||||
|
public int RotationAngle { get; set; } = 0;
|
||||||
|
|
||||||
|
[JsonProperty("resolutionWidth")]
|
||||||
|
public int ResolutionWidth { get; set; } = 1920;
|
||||||
|
|
||||||
|
[JsonProperty("resolutionHeight")]
|
||||||
|
public int ResolutionHeight { get; set; } = 1080;
|
||||||
|
|
||||||
|
[JsonProperty("selectedCameraIndex")]
|
||||||
|
public int SelectedCameraIndex { get; set; } = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,29 +181,65 @@
|
|||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
|
|
||||||
<!-- 摄像头控制面板 -->
|
<!-- 摄像头控制面板 -->
|
||||||
<StackPanel Orientation="Horizontal"
|
<StackPanel Orientation="Vertical"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
Margin="0,0,0,8">
|
Margin="0,0,0,8">
|
||||||
<!-- 摄像头选择下拉框 -->
|
<!-- 第一行:摄像头选择和切换 -->
|
||||||
<ComboBox Name="CameraSelectionComboBox"
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
Width="200"
|
<!-- 摄像头选择下拉框 -->
|
||||||
Margin="4,0"
|
<ComboBox Name="CameraSelectionComboBox"
|
||||||
Background="#2d2d2d"
|
Width="200"
|
||||||
Foreground="White"
|
Margin="4,0"
|
||||||
BorderBrush="#404040"
|
Background="#2d2d2d"
|
||||||
SelectionChanged="CameraSelectionComboBox_SelectionChanged" />
|
Foreground="White"
|
||||||
|
BorderBrush="#404040"
|
||||||
|
SelectionChanged="CameraSelectionComboBox_SelectionChanged" />
|
||||||
|
|
||||||
|
<!-- 切换摄像头按钮 -->
|
||||||
|
<Button Name="SwitchCameraButton"
|
||||||
|
Content="切换摄像头"
|
||||||
|
Margin="4,0"
|
||||||
|
Padding="8,4"
|
||||||
|
Background="#3b82f6"
|
||||||
|
Foreground="White"
|
||||||
|
BorderThickness="0"
|
||||||
|
FontWeight="Medium"
|
||||||
|
Click="SwitchCameraButton_Click" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<!-- 切换摄像头按钮 -->
|
<!-- 第二行:旋转和分辨率控制 -->
|
||||||
<Button Name="SwitchCameraButton"
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,4,0,0">
|
||||||
Content="切换摄像头"
|
<!-- 旋转控制 -->
|
||||||
Margin="4,0"
|
<StackPanel Orientation="Horizontal" Margin="4,0">
|
||||||
Padding="8,4"
|
<TextBlock Text="旋转:" Foreground="White" VerticalAlignment="Center" Margin="0,0,4,0" FontSize="12"/>
|
||||||
Background="#3b82f6"
|
<Button Name="RotateLeftButton" Content="⟲" Width="30" Height="30" Margin="2,0"
|
||||||
Foreground="White"
|
Background="#4b5563" Foreground="White" BorderThickness="0"
|
||||||
BorderThickness="0"
|
Click="RotateLeftButton_Click" FontSize="10" FontWeight="10"/>
|
||||||
FontWeight="Medium"
|
<TextBlock Name="RotationAngleText" Text="0°" Foreground="White" VerticalAlignment="Center"
|
||||||
Click="SwitchCameraButton_Click" />
|
Margin="4,0" FontSize="12" MinWidth="30" TextAlignment="Center"/>
|
||||||
|
<Button Name="RotateRightButton" Content="⟳" Width="30" Height="30" Margin="2,0"
|
||||||
|
Background="#4b5563" Foreground="White" BorderThickness="0"
|
||||||
|
Click="RotateRightButton_Click" FontSize="10" FontWeight="10"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- 分隔线 -->
|
||||||
|
<Rectangle Width="1" Height="20" Fill="#404040" Margin="8,0"/>
|
||||||
|
|
||||||
|
<!-- 分辨率控制 -->
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="4,0">
|
||||||
|
<TextBlock Text="分辨率:" Foreground="White" VerticalAlignment="Center" Margin="0,0,4,0" FontSize="12"/>
|
||||||
|
<ComboBox Name="ResolutionComboBox" Width="120" Margin="2,0"
|
||||||
|
Background="#2d2d2d" Foreground="White" BorderBrush="#404040"
|
||||||
|
SelectionChanged="ResolutionComboBox_SelectionChanged">
|
||||||
|
<ComboBoxItem Content="640x480" Tag="640,480"/>
|
||||||
|
<ComboBoxItem Content="800x600" Tag="800,600"/>
|
||||||
|
<ComboBoxItem Content="1024x768" Tag="1024,768"/>
|
||||||
|
<ComboBoxItem Content="1280x720" Tag="1280,720"/>
|
||||||
|
<ComboBoxItem Content="1920x1080" Tag="1920,1080"/>
|
||||||
|
</ComboBox>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- 摄像头状态指示 -->
|
<!-- 摄像头状态指示 -->
|
||||||
|
|||||||
@@ -104,12 +104,20 @@ namespace Ink_Canvas
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_cameraService = new CameraService();
|
// 从设置中加载摄像头配置
|
||||||
|
var cameraSettings = MainWindow.Settings.Camera;
|
||||||
|
_cameraService = new CameraService(
|
||||||
|
cameraSettings.RotationAngle,
|
||||||
|
cameraSettings.ResolutionWidth,
|
||||||
|
cameraSettings.ResolutionHeight);
|
||||||
_cameraService.FrameReceived += CameraService_FrameReceived;
|
_cameraService.FrameReceived += CameraService_FrameReceived;
|
||||||
_cameraService.ErrorOccurred += CameraService_ErrorOccurred;
|
_cameraService.ErrorOccurred += CameraService_ErrorOccurred;
|
||||||
|
|
||||||
// 初始化摄像头选择下拉框
|
// 初始化摄像头选择下拉框
|
||||||
RefreshCameraComboBox();
|
RefreshCameraComboBox();
|
||||||
|
|
||||||
|
// 初始化旋转和分辨率显示
|
||||||
|
InitializeCameraControls();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -117,6 +125,26 @@ namespace Ink_Canvas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeCameraControls()
|
||||||
|
{
|
||||||
|
if (_cameraService != null)
|
||||||
|
{
|
||||||
|
// 更新旋转角度显示
|
||||||
|
UpdateRotationDisplay();
|
||||||
|
|
||||||
|
// 设置分辨率下拉框
|
||||||
|
var currentResolution = $"{_cameraService.ResolutionWidth}x{_cameraService.ResolutionHeight}";
|
||||||
|
foreach (ComboBoxItem item in ResolutionComboBox.Items)
|
||||||
|
{
|
||||||
|
if (item.Tag?.ToString() == $"{_cameraService.ResolutionWidth},{_cameraService.ResolutionHeight}")
|
||||||
|
{
|
||||||
|
ResolutionComboBox.SelectedItem = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RefreshCameraComboBox()
|
private void RefreshCameraComboBox()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1213,6 +1241,70 @@ namespace Ink_Canvas
|
|||||||
CameraModeButton.Background = new SolidColorBrush(Color.FromRgb(107, 114, 128)); // 灰色
|
CameraModeButton.Background = new SolidColorBrush(Color.FromRgb(107, 114, 128)); // 灰色
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region 摄像头旋转和分辨率控制
|
||||||
|
|
||||||
|
private void RotateLeftButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_cameraService != null)
|
||||||
|
{
|
||||||
|
_cameraService.RotationAngle = (_cameraService.RotationAngle - 1 + 4) % 4;
|
||||||
|
UpdateRotationDisplay();
|
||||||
|
SaveCameraSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RotateRightButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_cameraService != null)
|
||||||
|
{
|
||||||
|
_cameraService.RotationAngle = (_cameraService.RotationAngle + 1) % 4;
|
||||||
|
UpdateRotationDisplay();
|
||||||
|
SaveCameraSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResolutionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_cameraService != null && ResolutionComboBox.SelectedItem is ComboBoxItem selectedItem)
|
||||||
|
{
|
||||||
|
var resolution = selectedItem.Tag?.ToString();
|
||||||
|
if (!string.IsNullOrEmpty(resolution))
|
||||||
|
{
|
||||||
|
var parts = resolution.Split(',');
|
||||||
|
if (parts.Length == 2 &&
|
||||||
|
int.TryParse(parts[0], out int width) &&
|
||||||
|
int.TryParse(parts[1], out int height))
|
||||||
|
{
|
||||||
|
_cameraService.ResolutionWidth = width;
|
||||||
|
_cameraService.ResolutionHeight = height;
|
||||||
|
SaveCameraSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateRotationDisplay()
|
||||||
|
{
|
||||||
|
if (_cameraService != null)
|
||||||
|
{
|
||||||
|
var angle = _cameraService.RotationAngle * 90;
|
||||||
|
RotationAngleText.Text = $"{angle}°";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveCameraSettings()
|
||||||
|
{
|
||||||
|
if (_cameraService != null)
|
||||||
|
{
|
||||||
|
MainWindow.Settings.Camera.RotationAngle = _cameraService.RotationAngle;
|
||||||
|
MainWindow.Settings.Camera.ResolutionWidth = _cameraService.ResolutionWidth;
|
||||||
|
MainWindow.Settings.Camera.ResolutionHeight = _cameraService.ResolutionHeight;
|
||||||
|
MainWindow.SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
protected override void OnClosed(EventArgs e)
|
protected override void OnClosed(EventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
Reference in New Issue
Block a user