Xamarin Mac,将 CGImage 转换为 .NET System.Drawing.Image

Posted

技术标签:

【中文标题】Xamarin Mac,将 CGImage 转换为 .NET System.Drawing.Image【英文标题】:Xamarin Mac, convert CGImage to .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 加载它?

【问题讨论】:

***.com/questions/11132410/… 【参考方案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 调用)。

以上是关于Xamarin Mac,将 CGImage 转换为 .NET System.Drawing.Image的主要内容,如果未能解决你的问题,请参考以下文章

将 UIImage 转换为 CGImage 会导致图像旋转

将UIImage转换为CVPixelBufferRef

[NSNull CGImage]:选择资产并将其转换为 JPEG 时出现无法识别的选择器异常

有啥方法可以在不将 CIImage 转换为 UIImage 或 CGImage 的情况下将 CIImage 转换为 NSData?

UIImage 在将其转换为 CIImage,然后转换为 CGImage 并返回 UIImage 时失去其方向

生成的 CGImage 总是模糊的