[辛酸歷程]在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的時間,已經很快了,足夠做外掛了~~~

四、總結

好吧,啰嗦了半天終於寫完了。

看着很簡單,但是其實我是搞了一天才搞定啊。。。。真的是各種麻煩。還好最后搞定了~記錄下來希望能幫助到你。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM