zoukankan      html  css  js  c++  java
  • [辛酸历程]在Mac中使用Python获取屏幕截图

    一、起因

    最近想做个小外挂玩玩,技术倒是不难,就是通过图片匹配加上一些判断方法来刷分。但是在最不起眼(却最容易出问题)的准备阶段卡住了。

    为什么卡住了呢,简单说,因为我需要获取截屏的数据,所以就要找一些能截屏的Python库。本来以为很简单,但是实际配置起来却。。。

    PIL,不支持Mac截图

    autopy,mac os安装不上,经过我去官方的issue搜索,发现很多人遇到同样的问题,然后,官方没有给出解决办法,也就是说不能用

    pyscreenshot,安装很费劲,因为依赖其他的Python UI库,好不容易安装好wxpython之后,发现截图是黑屏。。。

    看到这里可能你会问了,为什么不用系统自带的截图工具呢?

    这个其实我也想到了,Mac确实自带截图工具,并且可以命令行运行,使用Python的os.system("xxx")就可以。但是这个方法有一个缺点,就是截图会保存到本地。因为后面要用PIL处理图片,所以整个过程就是:截图--存到本地--PIL从文件读图。大家应该都知道,内存和硬盘的速度是天差地别。。。这个存--取的步骤会增加很多时间。虽然也就是几百毫秒,但是你要知道,一个外挂最起码一秒也要截好记张图,才能及时做出反应。所以这个速度是不能接受的。

    然后呢。。。直接进入主体,我使用了pyobjc。

    二、pyobjc简介

    什么是pyobjc,如果你不愿意百度的话,那我用一句话介绍一下。

    pyobjc就是用Python来写objective-c程序。

    那什么又是objective-c呢?

    objective-c就是专门写ios程序的语言。

    懂了吧,pyobjc其实就是一个桥梁,让我们可以用Python写ios的程序,就像你在Windows下面可以用Windows的各种API一样,这个东西让你可以在mac os x环境下面做任何事。

    三、波澜起伏

    pyobjc装好了,尝试import一个库,没问题。然后就是截图了。

    因为objective-c我不会啊!所以只能Google了。

    好吧,Google了一下(别问我为什么不用百度!)找到一篇用pyobjc截图的教程

    这个教程里面的capture就是截图函数。我们不需要关心。直接看最后。。。好吧,pngcanvas是什么东西?

    按照代码注释里的网址,发现是一个保存图片的小插件。

    把插件代码存到本地以后,运行了一下,可以得到图片了!然后。。。等等,怎么截一个图要十几秒????!!!!

    仔细研究发现,其实截图的时间很短,只有几十毫秒。真正耗时的是把图存到本地。

    然后。。别忘了,我们是要在PIL中使用图,所以思路出来了,把数据转换成PIL的Image。

    怎么转换呢?

    先看看他的代码是怎么转换的吧:

    from pngcanvas import PNGCanvas
            c = PNGCanvas(sp.width, sp.height)
            for x in range(sp.width):
                for y in range(sp.height):
                    c.point(x, y, color = sp.pixel(x, y))
         
            with open("/Users/selfdir/Documents/littlerabbit/text.png", "wb") as f:
                f.write(c.dump())
    

     好吧,虽然不知道PNGCanvas的用法,但是看也能看懂了,他是一个一个像素填充的。

    那么。。。Google一下发现PIL有一个Image.putpixel()方法,直接动手修改:

    for x in range(sp.width):
        for y in range(sp.height):
            img1.putpixel((x,y),sp.pixel(x, y))
    
    img1.save()

    好了,运行一下~~成功!。。。等等,时间还是很长啊,8秒??!!

    好吧。。。仔细分析一下,这样一个一个像素填充肯定是很慢的嘛。。。那么有没有办法直接生成Image呢。

    继续Google。。。发现PIL有个Image.fromstring()函数,可以直接把字符串转换成Image~~赶快使用:

    img1 = Image.fromstring("RGBA", (sp.width, sp.height), xxxx) 
    img1.save(...)

     哈哈成功~~时间也变成一百多毫秒了。然后。。。等等(你到底要等多少次= =)!怎么图片颜色不对劲啊。。。。

    研究发现,是图片的模式不对。capture获取的图片数据是按照BRGA的顺序来储存的,但是PIL是使用RGBA生成图片,自然颜色就不对了。。。

    继续Google!!!

    直接上最终解决代码:

    img1 = Image.fromstring("RGBA", (sp.width, sp.height), xxxx) 
    b, g, r, a= img1.split()
    img1 = Image.merge("RGBA", (r, g, b, a))
    img1.save(...)
    

     先split再merge,实现数据换位。

    终于成功了!!

    然后我们注释掉save语句,再次运行,发现截图+转换一共只需要不到40ms的时间,已经很快了,足够做外挂了~~~

    四、总结

    好吧,啰嗦了半天终于写完了。

    看着很简单,但是其实我是搞了一天才搞定啊。。。。真的是各种麻烦。还好最后搞定了~记录下来希望能帮助到你。

  • 相关阅读:
    将军与妓
    LINUX SHELL
    LINUX FTP
    Java API的常用包
    PYTHON LOGGING模块
    json转xml
    xml转json
    PYTHON DJANGO学习笔记
    PYTHON爬取66影视的电影下载链接,有搜索功能
    JAVA PROPERTIES配置文件使用方法
  • 原文地址:https://www.cnblogs.com/numbbbbb/p/3236595.html
Copyright © 2011-2022 走看看