捕获位图时引发内存溢出异常

3

问题

我目前正在尝试创建一个应用程序,该应用程序将在用户复制计算机上的问题时创建gif /视频(尚未决定)。这显然意味着我需要通过定时器定期创建屏幕截图。

问题在于,25秒后(总是25秒),我会收到一个错误消息,提示系统内存不足。

Exception thrown: 'System.OutOfMemoryException' in System.Drawing.dll

Additional information: Out of memory.

我的代码

下面是计时器Tick事件中的代码:

Private DebugVid As New List(Of IntPtr)

Private Sub tmrDebug_Tick(sender As Object, e As EventArgs) Handles tmrDebug.Tick

    Dim CurrentScreen As Screen = Screen.PrimaryScreen
    For Each SCR As Screen In Screen.AllScreens
        If SCR.Bounds.Contains(MousePosition) Then
            CurrentScreen = SCR
        End If
    Next

    Using ScreenGrab As New Bitmap(CurrentScreen.Bounds.Width, CurrentScreen.Bounds.Height)
        Using g As Graphics = Graphics.FromImage(ScreenGrab)
            g.CopyFromScreen(New Point(CurrentScreen.Bounds.X, CurrentScreen.Bounds.Y), New Point(0, 0), ScreenGrab.Size)
            g.DrawImage(My.Resources.MyCursor, New Point(MousePosition.X - CurrentScreen.Bounds.X, MousePosition.Y))
        End Using
        DebugVid.Add(ScreenGrab.GetHbitmap())
    End Using

    GC.Collect()
End Sub

第一部分定义了光标所在的屏幕,以便知道要创建哪个屏幕的位图。
第二部分创建了位图,将屏幕截图应用于它,绘制了鼠标位置处的光标,最后将整数指针存储在列表中。
一旦用户点击停止录制按钮,它就会转换为gif(目前是这样)。
代码中引发异常的部分是以下行:
DebugVid.Add(ScreenGrab.GetHbitmap())

非常感谢您的帮助。


2
25秒,每秒有多少帧?图像尺寸是多少?做一下数学运算,你可能就会明白为什么内存不足了。最好将文件保存在某个地方,并用它们构建GIF,只是不要将它们保留在内存中。顺便问一下,你为什么需要HBITMAP? - Adriano Repetti
这是我第一次尝试这样的事情,所以我从网上收集了一些碎片,因此使用了HBITMAP。我知道存储图像是一个繁重的任务,所以如果有任何替代方法,我非常欢迎。计时器每秒运行两次,图像大小为我的屏幕分辨率,目前为1680x1050。 - Weebie
1个回答

4

这可能会产生大量未受管理的GDI句柄和位图数据需要保存在内存中。25秒后,可用的句柄数量或者可用的进程内存可能会被耗尽,因此您可能需要考虑在记录帧时将每个帧保存到磁盘上。当录制完成后,再将单个图像处理成gif格式。

根据MSDN的说明,进程可用的GDI句柄数量范围从256到65536不等,具体取决于操作系统和配置。您所拍摄的每个屏幕截图都至少使用了一个句柄,并且由您的应用程序和.net框架使用了更多的句柄。


我刚刚尝试了你的建议,将屏幕截图的Base 64字符串版本保存在文本文件中而不是存储在内存中。大约一分半钟后,文件就达到了8GB,所以这并不是一个可行的方法。有更好的存储方式吗? - Weebie
2
Base 64编码实际上会使您的文件变大。我建议将每个帧保存为“png”格式。这应该可以在不损失质量的情况下显着压缩文件。此外,磁盘上有8GB,这肯定解释了为什么您会耗尽内存。 - Bradley Uffner
大约1分钟内可以传输100MB,我认为这是最好的结果了,非常感谢。我只需要记得在创建GIF时删除PNG文件即可! - Weebie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接