【问题标题】:Xamarin Mac, convert CGImage to .NET System.Drawing.ImageXamarin Mac,将 CGImage 转换为 .NET System.Drawing.Image
【发布时间】:2019-04-11 06:02:50
【问题描述】:

我正在使用 Xamarin/MONO 编写一个 MacOS 应用程序,我想从屏幕上截取一张图像,并将其与 .NET 中的其他图像库一起使用

我发现我可以像这样使用本机系统库

[DllImport(Constants.CoreGraphicsLibrary)]
static extern IntPtr CGWindowListCreateImage(CGRect screenBounds, CGWindowListOption windowOption, uint windowID, CGWindowImageOption imageOption);

但是,一旦我拥有了 CGImage intptr,它对我来说并不是什么好事,因为我想做一些我已经为其他平台实现的 System.Drawing 东西。有没有办法可以使用 IntPtr 并以某种方式获得 System.Drawing 图像?或者也许将 CGImage intptr 保存到磁盘并使用 System.Drawing 加载它?

【问题讨论】:

标签: c# macos xamarin xamarin.mac


【解决方案1】:

您可以使用CGImageDestination 在文件、NSMutableData 或 CG 使用者中创建 CGImage 的 png/jpeg 表示。

如果您的 C# 库可以处理字节序列/数组,那么您可以使用生成的 NSMutableData(通过 GetBytes)将 PNG/JPEG 格式的字节复制到一个缓冲区供您在内存中切片和切块...

var cgImagePtr = CGWindowListCreateImage(new CGRect(0, 0, 100, 100), CGWindowListOption.All, 0, CGWindowImageOption.Default);
using (var url = new NSUrl("file", "localhost", "/Users/Sushi/Desktop/someFileName.png"))
using (var cgImage = new CGImage(cgImagePtr))
using (var destination = CGImageDestination.Create(url, "public.png", 1)) 
{
    destination.AddImage(cgImage);
    destination.Close();
}
cgImagePtr = null;

注意:不要使用UTType 作为您的typeIdentifier,您的CGImageDestination 将始终为空,请使用“public.png”、“public.jpeg”等...(这些是区分大小写的)

【讨论】:

  • "如果您的 C# 库可以作用于字节序列/数组,那么您可以使用生成的 NSMutableData(通过 GetBytes)复制 PNG/JPEG 格式的文件,而不是将文件保存到磁盘字节到缓冲区,供您在内存中切片和切块......”这正是我想要采取的方法,我只是不确定如何继续。如果我可以从 IntPtr CGWindowListCreateImage 返回到 C# ByteArray,我将能够从那里获取它。问题是我的项目是双平台的,我不能直接使用 NSFoundation 类或任何 MonoMac 的东西。
  • Problem is my project is dual platform and I can't use NSFoundation classes or any MonoMac stuff directly 如果您不使用 Xamarin.Mac(?) 并且只是通过 Interop(?) 使用纯 Mono,则必须在内存中编组/固定 IntPtr 并解码/转换内存结构CGImage,不是很有趣(或富有成效)的东西。您还可以通过消息传递到 ObjectiveC 运行时并手动调用 ObjC 方法(这一切都是通过消息传递完成的,而不是直接方法/指针调用),丑陋但可行,您可以查看 Xamarin.iOS/Xamarin.Mac 代码基于看看这是如何完成的。
  • @Richhofen 您可以添加至少一个基于Xamarin.Mac 的库,并在 macOS 平台上使用依赖注入来加载它。我个人会使用 Xamarin.Mac 作为 shell 应用程序/容器,并在其中引用您的跨平台库。
  • @Richthhofen 作为替代方案,您可以退出进程并调用自定义 AppleScript 来截取屏幕截图,然后将其加载到您的跨平台应用程序中,但我不知道您的实际应用程序是什么要求是,只是你正在做一个屏幕快照。
  • @Richthofen 作为测试然后,创建一个 Xamarin.Mac 应用程序并将代码包含在我的答案中的 NSButton.Activated EventHandler 中,作为对您的问题的快速测试(注意:您可能需要玩标志;CGWindowListOption & CGWindowImageOption 以满足您的需求)。如果你这样做了,你可以直接使用 Xamarin 帮助程序CGImage.ScreenImage 将屏幕捕获到 CGImage(而不是使用对 CGWindowListCreateImage 的 Interop 调用)。
猜你喜欢
  • 2011-04-14
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 1970-01-01
  • 2015-11-02
  • 2012-02-14
相关资源
最近更新 更多