用于保存位图的 C# 更快方法

本文关键字:方法 保存 位图 用于 | 更新日期: 2023-09-27 18:33:27

我正在开发一个录音应用程序,每秒能够获得 10 - 15 张屏幕截图。问题是保存所有图像的速度足够快,以便屏幕截图队列不会在 RAM 中积聚并耗尽用户的内存。

目前,我能够通过使用两个线程来做到这一点,这些线程按顺序保存图像,然后收集垃圾。

while (true)
{
    bmp = null;
    Dispatcher.Invoke(new Action(delegate()
    {
        if (images.Count > 0)
        {
            bmp = images[0];
            images.RemoveAt(0);
        }
    }));
    if (bmp != null)
    {
        bmp.Save("frames''" + framesImagesIndex++ + ".png", ImageFormat.Png);
        bmp.Dispose();
        bmp = null;
        GC.Collect();
    }
    Thread.Sleep(10);
}

这样做的问题是它非常占用 CPU,因此我认为它不会在功能较差的系统上工作。这种方法在我的 3.31 GHz 进程上占用 30 个 CPU。

当我将 CPU 设置为将所有

图像写入一个文件并通过锁定位图的位来仅写入字节时,我可以将 CPU 减轻到 17 左右。

byte[] rgbValues;
IntPtr ptr;
System.Drawing.Rectangle rect;
System.Drawing.Imaging.BitmapData bmpData;
System.Drawing.Imaging.PixelFormat pxf;

pxf = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
//using(FileStream fs = new FileStream("frames.data", FileMode.OpenOrCreate, FileAccess.Write))
while (true)
{
    bmp = null;
    Dispatcher.Invoke(new Action(delegate()
    {
        if (images.Count > 0)
        {
            bmp = images[0];
            images.RemoveAt(0);
        }
    }));

    rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
    bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, pxf);
    ptr = bmpData.Scan0;
    rgbValues = new byte[bmpData.Stride * bmp.Height];
    Marshal.Copy(ptr, rgbValues, 0, rgbValues.Length);
    fs.Write(rgbValues, 0, rgbValues.Length);
    bmp.UnlockBits(bmpData);
    bmp.Dispose();
    bmp = null;
    GC.Collect();
}

此方法有助于解决 CPU 问题,但因为它不够快。图像队列会积聚并重载 ram,所以我不知道我还能做些什么来解决这两个问题。

还有其他方法吗?

用于保存位图的 C# 更快方法

首先,使用带有Thread.Sleep(x);while 循环非常占用 CPU,就像GC.Collect()和频繁调用新实例一样。您应该考虑使用线程。

Action action;
public void Main()
{
action = new Action(delegate()
{
    if (images.Count > 0)
    {
        bmp = images[0];
        images.RemoveAt(0);
    }
});
Thread thread = new Thread(SaveBitmap());
thread.Start();
thread.Priority =  ThreadPriority.Highest
}
public void SaveBitmap()
{
    Dispatcher.Invoke(action);
if (bmp != null)
{
    bmp.Save("frames''" + framesImagesIndex++ + ".png", ImageFormat.Png);
    bmp.Dispose();
    bmp = null;
}
}

尝试使用上述方法,或者至少集成一些部分。

由于涉及压缩,另存为 PNG 格式会占用大量 CPU。将图像另存为.bmp,您将获得很大的速度提升,但代价是使用更多磁盘空间。