通过代码捕获IDL图形用户界面屏幕截图
原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/screen-capturing-idl-guis-from-code
10422 为本文评分:
5.0
通过代码捕获IDL图形用户界面屏幕截图
Jim Pendleton 2015年10月29日 星期四
用户长期以来一直期望能够在IDL环境中以编程方式捕获IDL部件(widget)的屏幕截图。
遗憾的是,这一功能短期内似乎无法实现,因此我一直在互联网上搜寻可能的变通方案。
Linux系统
在Linux系统上,长期以来可以直接通过SPAWN调用ImageMagick的"import"命令行应用程序。
如果imagemagick套件已包含在系统路径中,您可以捕获整个显示屏幕,或捕获指定名称的单个窗口。
屏幕截图会保存到临时文件,随后可将其读入IDL。以下示例假设imagemagick的"import"可执行文件位于shell路径中。
IDL> spawn, 'import -window root screenshot.jpg', output, error
IDL> im = read_jpeg('screenshot.jpg')
IDL> i = image(im)
IDL> file_delete, 'screenshot.jpg'
ImageMagick已存在很长时间。您可以根据系统管理员允许的程度来决定对其的信任度。
对于Linux用户而言,这是一个可行的解决方案,且无需修改IDL内部代码来支持此功能。
Windows系统
在Windows系统上,如果同时运行Cygwin X服务器,ImageMagick似乎也能实现此功能。
但既然有更简单的解决方案,谁还愿意处理那些复杂配置呢?
我最近在github上发现了Vasil Arnaudov提供的嵌入式C#简单DOS批处理脚本,为Windows用户提供了等效功能,无需安装来源可疑、意图不明或受版权限制的"免费软件"。
您可以阅读源代码并自行决定是否信任。
唯一的要求是已安装.NET框架——对于任何比XP更新的Windows版本来说,这几乎是必然已安装的。
在本示例中,我先将Vasil Arnaudov的"screenCapture.bat"复制到Windows桌面再执行。
IDL> spawn, 'c:\users\me\desktop\screenCapture.bat test.png', output, error
IDL> im = read_png('test.png')
IDL> i = image(im[0:2, *, *])
IDL> file_delete, 'test.png'
由于选择捕获PNG格式,我还获取了透明度通道,因此第一个维度是4个元素(RGBA)而非3个(RGB)。
您可以选择其他格式如JPEG或BMP进行捕获。可通过查阅源代码了解支持的文件格式选项。
假设我只想捕获单个部件的内容。
IDL> tlb = widget_base(/column, xoffset=100, yoffset=200, title='my widget')
IDL> l = widget_label(tlb, value='我们将捕获此部件的内容')
IDL> widget_control, tlb, /realize
在捕获全屏之前,可随意将部件移动到屏幕上的新位置。
IDL> spawn, 'c:\users\me\desktop\screenCapture.bat test.jpg', output, error
IDL> read_jpeg, 'test.jpg', im
IDL> i2 = image(im)
IDL> file_delete, 'test.jpg'
理论上,screenCapture.bat可接受窗口名称作为可选参数,仅捕获该窗口。但在IDL测试中,我发现焦点常常(并非总是)会返回到主IDL工作台,导致捕获的是该窗口而非目标部件。
那么,如何从全屏截图中提取仅包含我们部件的内容呢?
请注意,我们的屏幕截图图像原点在左下角,但屏幕偏移量是从左上角开始测量的。利用WIDGET_INFO返回的几何信息结构,定位并提取部件的位图。
IDL> g = widget_info(tlb, /geometry)
IDL> s = get_screen_size()
IDL> ox = g.xoffset
IDL> oy = s[1] - g.yoffset
IDL> w = im[*, ox:ox + g.scr_xsize, (oy - g.scr_ysize):oy]
IDL> i = image(w)
如果您使用多显示器,并希望捕获主显示器之外的其他显示器图像,可能需要修改提供的C#代码——这留给读者作为练习。
当然,这个逻辑可以轻松封装成函数,接受部件ID作为输入,返回图像数组作为输出。这也留给读者作为练习。