PythonでRaspberry Piのスクリーンショットを撮る

Pocket

はじめに

フレームバッファ(/dev/fb0) + python3でスクリーンショットを撮ります。

準備

Piilow(画像処理ライブラリ)をインストールする

pip install Pillow

フレームバッファの情報を取得する

fbset
↓結果
mode "1920x1080"
 geometry 1920 1080 1920 1080 32
 timings 0 0 0 0 0 0 0
 rgba 8/16,8/8,8/0,8/24

上記から読み取れるもの

  • 幅1920
  • 高さ1080
  • 32bit → 1pixelの色は32bit(4byte)
  • rgba

rgba 8/16,8/8,8/0,8/24 となっていますが、これは
r → 8/16:32bitの左16bit目から8bit
g → 8/8:32bitの左8bit目から8bit
b → 8/0:32bitの左0bit目から8bit
a → 8/24:32bitの左24bit目から8bit
となっていますので、32bitの中身はbgraの順にデータが並んでいることになります。
/dev/fb0 には bgraの順番で32bit(4byte)のデータが1920×1080個並んでいることになります。

コード

from PIL import Image  #1
file = open('/dev/fb0','rb')  #2
rawdata = file.read()
file.close()
Imagesize = (1920,1080)
tmpImg = Image.frombytes('RGBA', Imagesize, rawdata)  #3
r, g, b, a = tmpImg.split()  #4
img = Image.merge("RGB", (b, g, r))  #5
img.save(img.png)  #6
  • #1 開発が停止したPILのフォークがPillowで、互換性があるようにPILからimportするのかな?最初 from Pillow としてしばらく悩んでました
  • #2 /dev/fb0をバイナリで読み込む
  • #3 rawdata(中身/dev/fb0)をRGBAモードで読み込む(BGRAモードはない)
  • #4 イメージをrgbaのチャンネルごとに分割する
  • #5 BGRAをRGBAで読み込んでいるため、bとrが入れ替わっているのでここで入れ替える。(“RGBA”, (b, g, r, a))じゃないの?と思うかもしれませんが、正しいイメージにならないことがあったのでaを省いた。原因はしらべていません。
  • #6 拡張子をjpgにしても適当に変換して保存してくれる。ちなみにa.saveとするとaチャンネルの画像が保存できる

最後に

端末ウィンドウをぐりぐりマウスで移動させながらスクリーンショットを撮ると端末ウィンドウの表示が歪んでしまいました。
これは/dev/fb0を読込んでいる途中で/dev/fb0が更新されるためだと思われます。
なのでアクションゲームなどのスクリーンショット撮影には向かないと思います。
今回はとある検査機器のUI(ラズパイで制御、アニメーションとかは無い)のスクリーンショットを撮りたかっただけなので特に問題ありませんでした。

Pocket

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください