C#+OpenCV进阶(四)_录屏

/// <summary>
/// 录屏线程
/// </summary>
private static CancellationTokenSource cts;

/// <summary>
/// 录屏保存er
/// </summary>
private static VideoWriter _videoWriter;

/// <summary>
/// 录屏-开始
/// </summary>
/// <param name="index">屏幕序号;0=第一个屏幕</param>
/// <param name="parameter">录制参数</param>
/// <param name="videoParameter">录制文件保存参数</param>
/// <param name="doCaptureScreen">处理方法</param>
/// <exception cref="Exception"></exception>
public static void CaptureScreen_Start(int index, ScreenParameter parameter, VideoParameter videoParameter, DelDoCaptureScreen? doCaptureScreen)
{
    // 获取屏幕
    Screen[] screens = Screen.AllScreens;
    if (screens == null || screens.Length < 1)
    {
        throw new Exception("未检测到任何屏幕!");
    }
    if (index > screens.Length - 1)
    {
        throw new Exception($"未检测到屏幕【{index}】!");
    }
    Screen screen = screens[index];

    // 设置录制参数
    if (parameter == null || (parameter.SourceX == 0 && parameter.SourceY == 0 && parameter.DestinationX == 0 && parameter.DestinationY == 0 && parameter.BlockRegionSize == default))
    {
        parameter = new ScreenParameter();

        parameter.SourceX = screen.Bounds.X;
        parameter.SourceY = screen.Bounds.Y;
        parameter.DestinationX = 0;
        parameter.DestinationY = 0;
        parameter.BlockRegionSize = screen.Bounds.Size;
    }
    else
    {
        parameter.SourceX = parameter.SourceX < screen.Bounds.X ? screen.Bounds.X : parameter.SourceX;
        parameter.SourceY = parameter.SourceY < screen.Bounds.Y ? screen.Bounds.Y : parameter.SourceY;

        parameter.DestinationX = parameter.DestinationX < screen.Bounds.X ? screen.Bounds.X : parameter.DestinationX;
        parameter.DestinationX = parameter.DestinationX > screen.Bounds.Width ? screen.Bounds.Width : parameter.DestinationX;
        parameter.DestinationY = parameter.DestinationY < screen.Bounds.Y ? screen.Bounds.Y : parameter.DestinationY;
        parameter.DestinationY = parameter.DestinationY > screen.Bounds.Height ? screen.Bounds.Height : parameter.DestinationY;

        int width = screen.Bounds.Width;
        int height = screen.Bounds.Height;
        width = parameter.BlockRegionSize.Width > width ? width : parameter.BlockRegionSize.Width;
        height = parameter.BlockRegionSize.Height > height ? height : parameter.BlockRegionSize.Height;
        parameter.BlockRegionSize = new System.Drawing.Size(width, height);
    }

    // 设置录屏文件参数
    if (videoParameter == null)
    {
        throw new Exception("请先设置好‘录制文件保存参数’【videoParameter】!");
    }
    if (string.IsNullOrEmpty(videoParameter.FileName))
    {
        throw new Exception("请先设置好‘录制文件的保存路径’!");
    }

    if (videoParameter.FrameSize == default)
    {
        videoParameter.FrameSize = new OpenCvSharp.Size(parameter.BlockRegionSize.Width, parameter.BlockRegionSize.Height);
    }

    _videoWriter = new VideoWriter(videoParameter.FileName, videoParameter.ApiPreference, videoParameter.Fourcc,
        videoParameter.Fps, videoParameter.FrameSize, videoParameter.IsColor);

    // 录制
    Bitmap bitmap = new Bitmap(parameter.BlockRegionSize.Width, parameter.BlockRegionSize.Height);
    Graphics g = Graphics.FromImage(bitmap);

    cts = new CancellationTokenSource();
    Task.Run(() =>
    {
        while (!cts.Token.IsCancellationRequested)
        {
            g.CopyFromScreen(parameter.SourceX, parameter.SourceY, parameter.DestinationX, parameter.DestinationY, screen.Bounds.Size);

            Mat mat = bitmap.ToMat();
            // 托管方法
            doCaptureScreen?.Invoke(mat);

            // 保存
            _videoWriter.Write(mat);
        }
    });
}

/// <summary>
/// 录屏-结束
/// </summary>
public static void CaptureScreen_Stop(DelDoCaptureScreenClosed? doCaptureScreenClosed)
{
    if (cts != null)
    {
        cts.Cancel();

        Thread.Sleep(1000);
        _videoWriter?.Release();  // 关闭写入
        _videoWriter?.Dispose();

        // 托管方法
        doCaptureScreenClosed?.Invoke();
    }
}

/// <summary>
/// 录屏参数
/// </summary>
public class ScreenParameter
{
    /// <summary>
    /// 截屏位置X
    /// </summary>
    public int SourceX { get; set; } = 0;

    /// <summary>
    /// 截屏位置Y
    /// </summary>
    public int SourceY { get; set; } = 0;

    /// <summary>
    /// 截屏目标位置X
    /// </summary>
    public int DestinationX { get; set; } = 0;

    /// <summary>
    /// 截屏目标位置Y
    /// </summary>
    public int DestinationY { get; set; } = 0;

    /// <summary>
    /// 截屏大小
    /// </summary>
    public System.Drawing.Size BlockRegionSize { get; set; } = default;
}

/// <summary>
/// 录屏保存文件参数
/// </summary>
public class VideoParameter()
{
    /// <summary>
    /// 视频文件保存路径
    /// </summary>
    public string FileName { set; get; } = string.Empty;
    /// <summary>
    /// API后端
    /// </summary>
    public VideoCaptureAPIs ApiPreference { set; get; } = VideoCaptureAPIs.ANY;
    /// <summary>
    /// 编码格式
    /// </summary>
    public FourCC Fourcc { set; get; } = FourCC.H264;
    /// <summary>
    /// 帧数
    /// </summary>
    public double Fps { set; get; } = 30;
    /// <summary>
    /// 视频分辨率
    /// 默认不需要指定
    /// </summary>
    public OpenCvSharp.Size FrameSize { set; get; } = default;
    /// <summary>
    /// 是否是彩色图
    /// </summary>
    public bool IsColor { set; get; } = true;
}
posted @ 2024-07-11 11:40  ꧁执笔小白꧂  阅读(80)  评论(0编辑  收藏  举报