我正在尝试获取连接到 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: '内存不足,无法继续执行程序。'例如,如果我尝试获取视频的屏幕截图。
以下是更多详细信息:
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, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
在 SSDS.Main.Core.WindowsMethods.GetImage(Display display) in WindowsMethods.cs:line 204
在 WindowsMethods.cs 中的 SSDS.Main.Core.WindowsMethods.d__26.MoveNext():line 364
抛出异常: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 像素宽度?
还是其他地方的问题?
答案 0 :(得分:0)
将 GetImage() 方法更改为此。可能是因为Desktop
也给了一个消息。
public static byte[] GetImage()
{
// Define bitmap
double screenLeft = SystemParameters.VirtualScreenLeft;
double screenTop = SystemParameters.VirtualScreenTop;
double screenWidth = SystemParameters.VirtualScreenWidth;
double screenHeight = SystemParameters.VirtualScreenHeight;
using (Bitmap sc = new Bitmap((int)screenWidth, (int)screenHeight, 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((int)screenLeft, (int)screenTop, 0,
0, sc.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;
}
}
}