【发布时间】:2021-02-11 16:16:21
【问题描述】:
我正在尝试获取连接到 PC 的显示器的屏幕截图,并将结果作为字节 [] 返回
Display 类是 WindowsDisplayAPI。
/// <summary>
/// Returns the screenshot to be displayed
/// </summary>
/// <param name="display"></param>
/// <returns></returns>
public static byte[] GetImage(Display display)
{
// Define bitmap
using (Bitmap sc = new Bitmap(display.GetScreen().Bounds.Width, display.GetScreen().Bounds.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
if (sc == null)
return null;
// Define graphics object
using (Graphics memoryGraphics = Graphics.FromImage(sc))
{
if (memoryGraphics == null)
return null;
memoryGraphics.CopyFromScreen(display.GetScreen().Bounds.X, display.GetScreen().Bounds.Y, 0,
0, display.GetScreen().Bounds.Size, CopyPixelOperation.SourceCopy);
BitmapSource tmp = CreateBitmapSourceFromGdiBitmap(sc);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
byte[] bit = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
encoder.Frames.Add(BitmapFrame.Create(tmp));
encoder.Save(stream);
bit = stream.ToArray();
stream.Dispose();
stream.Close();
}
GC.Collect();
return bit;
}
}
}
与辅助方法一起
/// <summary>
/// Helper for GetImage
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
private static BitmapSource CreateBitmapSourceFromGdiBitmap(Bitmap bitmap)
{
#region
// Transform the image for CaptureScreen method
if (bitmap == null)
throw new ArgumentNullException("bitmap");
var rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);
var bitmapData = bitmap.LockBits(
rect,
ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
try
{
var size = (rect.Width * rect.Height) * 4;
return BitmapSource.Create(
bitmap.Width,
bitmap.Height,
bitmap.HorizontalResolution,
bitmap.VerticalResolution,
System.Windows.Media.PixelFormats.Bgra32,
null,
bitmapData.Scan0,
size,
bitmapData.Stride);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
#endregion
}
我不相信我有内存泄漏,尽管不确定。如果我采用普通的静态屏幕,该方法工作正常,但抛出 System.OutOfMemoryException: 'Insufficient memory to continue the execution of the program.'例如,如果我尝试获取视频的屏幕截图。
这里有更多细节:
2021-02-11 16:32:52,395 错误 SSDS.Main.Core.WindowsMethods - System.ArgumentException:参数无效。
在 System.Drawing.Graphics.GetHdc()
在 System.Drawing.Graphics.CopyFromScreen(Int32 sourceX, Int32 sourceY, Int32 destinationX, Int32 destinationY, 大小 blockRegionSize, CopyPixelOperation copyPixelOperation)
在 WindowsMethods.cs 中的 SSDS.Main.Core.WindowsMethods.GetImage(显示显示):第 204 行
在 WindowsMethods.cs:line 364 中的 SSDS.Main.Core.WindowsMethods.d__26.MoveNext()
抛出异常:System.Drawing.dll 中的“System.ArgumentException”
这是第 204 行:
memoryGraphics.CopyFromScreen(display.GetScreen().Bounds.X, display.GetScreen().Bounds.Y, 0, 0, display.GetScreen().Bounds.Size, CopyPixelOperation.SourceCopy);
如果我以 x64 格式发送应用程序,它可以正常工作,但是我看到内存使用量攀升至略低于 2GB,而在任何 cpu 设置下它都保持在 900MB 以下。所以我猜测创建的图像不必要的大,我怎么能减少到让我们说 300 像素宽度?
还是其他地方有问题?
【问题讨论】:
-
您是否将其构建为 32 位 x86 应用程序?另外,我对您要解决的问题有点困惑。您提到了两个不同的例外;
OutOfMemoryException和ArgumentException。你想解决哪一个问题? -
我要解决的异常是主题的一部分,因此引发了第二个异常。如果我使用 64 位,一切正常,这更多的是尝试为所有环境获得正确的修复,而不仅仅是快速修复..
-
memoryGraphics.CopyFromScreen行是抛出OutOfMemoryException的那一行吗? -
是的,这是正确的
-
Display的类型是什么?我正在试验您的代码,我认为问题可能是 Win32 API 调用问题。
标签: c# wpf graphics bitmap screenshot