使用 C# 位图更有效地将图像保存到磁盘

问题描述

我正在使用 C# 程序每秒保存大约 10 个大小为 660x330 的屏幕截图。

此 C# 程序用作游戏 GTA V 的 .dll 脚本。

Bitmap catchBmp = new Bitmap(300,660,System.Drawing.Imaging.PixelFormat.Format32bppRgb);
Graphics g = Graphics.FromImage(catchBmp);
g.copyFromScreen(new Point(Screen.AllScreens[0].Bounds.Width / 3 + 170,Screen.AllScreens[0].Bounds.Height / 6 + 60),new Point(0,0),new Size(300,660));
string tmp = Path.Combine(path,modNum.ToString(),location);
if (!Directory.Exists(tmp))
{
    Directory.CreateDirectory(tmp);
}
string tmp_filename = tmp + "\\" + location + "_" + weather + "_" + time + "_" + anim + "_" + view_angle + "_" + modNum + "_" + picNum.ToString() + ".jpg";
catchBmp.Save(tmp_filename);
UI.ShowSubtitle(tmp_filename);
Wait(100);
catchBmp.dispose();
g.dispose();      

上面的代码是循环运行的,每秒运行10次左右。

脚本运行大约 6 个小时后,我的硬盘驱动器似乎达到了最大使用率,脚本崩溃了。

有没有办法防止这种情况发生?我想一次运行这个脚本几天。

使用线程保存图像会有帮助吗?或者在将队列保存到磁盘的同时实现队列?

解决方法

这似乎是磁盘跟不上的简单问题。

一种选择是使用更高效的存储格式,即保存为视频文件,可以利用帧之间的差异进行更好的压缩。参见例如 video-writing in aforge。虽然这应该会减少写入数据的大小,但会增加系统的 CPU 负载。

另一种选择是通过降低分辨率或adjusting the compression parameters来降低图像文件的质量。您还可以切换图像格式。 Jpeg 是一个旧标准,往往会以低比特率生成低质量的图像,像 jpeg xr 这样更现代的格式可能效果更好。

第三种选择是简单地获得更快的磁盘,和/或确保程序对磁盘具有独占访问权。

使用队列或线程可能不会有太大帮助,因为代码不会阻塞其他任何东西,而且它只会尽可能快地运行。但是我建议在位图之前处理图形,并在处理之后移动等待。