組み込みLinuxでスクリーンショットを撮影する
組み込みでスクリーンショット
はじめに
組み込みLinuxはデスクトップ環境が無いので
スクリーンショットを取るアプリも無い。
でも操作画面(LCD)はあるからドキュメントを作るのにスクリーンショットが欲しい!
という上司からの要望があった。
半日でスクリーンショット撮影するツールを作らされたのでここにメモっておく。
こちらのサイトを参考にさせていただきました。
非常に助かりました。ありがとうございます。
ラズパイでフレームバッファ(/dev/fb0)を使用して、直接ディスプレイ画像を入出力する - Qiita
Bitmapファイルフォーマット
内容
結論までの経緯とやったことを書いておく。
フレームバッファとは
Linuxはフレームバッファにデータを書き込むとカーネルがいい感じに勝手に描画してくれる。
つまりディスプレイの情報はフレームバッファに入っている。
カーネルが書き込んだフレームバッファをどう処理しているのかはわからない(そのうち理解したい)。
手元のUbuntuマシンでは/dev/fb0
があった。
フレームバッファの情報は以下のコマンドで確認できるらしい。
$ cat /sys/class/graphics/fb0/bits_per_pixel 32 $ cat /sys/class/graphics/fb0/virtual_size 1920,1080
フレームバッファを取得して見てみる
以下のコマンドでフレームバッファを取得する。
$ cat /dev/fb0 > temp.raw
IrfanViewでrawファイルを開く。
ソフトを起動して、ドラッグ&ドロップでrawファイルをぶち込むとrawファイルを開く設定ができる。
今回は以下の設定でrawファイルを正常に表示できた。
- Image width:1920
- Image heigh:1080
- BitsPerPixel:32 BPP[4 byte per pixel]
- Options for 24 and 32 BPP:Color order BGR(32bit BGRA)
rawファイルは扱いにくい
rawファイルでスクリーンショットを撮影することはできた。
でもrawファイルは一般的な画像ビューアで表示できないし、ドキュメントに貼り付けることもできない。
...と参ってたら、チームのすごい人から
「昔、bitmapでスクリーンショット撮るツールあった気がする。ツール見つけられないけど確かbitmapヘッダをくっつけてただけだった気がする。」
と、神の導きを頂いたので、とりあえずbitmapヘッダを作ってみることにした。
bitmapヘッダを作る
bitmapのヘッダは、ファイルヘッダ(14byte)と情報ヘッダ(40byte)の54byteでできているらしい。
とりあえず空のバイナリファイルを作る。
dd if=/dev/zero of=bmp_head.bin bs=54 count=1
vscodeの拡張機能「vscode-hexdump」でヘッダにデータを入れていく。
ファイルタイプ以外はすべてリトルエンディアンでデータを入れる。
以下は実際に入れたデータ
種類 | オフセット | サイズ | 値 | メモ |
ファイルタイプ | 0 | 2byte | 0x42、0x4D | 固定値 |
ファイルサイズ(byte) | 2 | 4byte | 0x00 1F A4 36 | ヘッダサイズ(54byte)+1920*1080 |
予約領域1 | 6 | 2byte | 0x00 | 固定値 |
予約領域2 | 8 | 2byte | 0x00 | 固定値 |
ヘッダサイズ | 10 | 4byte | 0x00 00 00 36 | 固定値 |
情報ヘッダサイズ | 14 | 4byte | 0x00 00 00 28 | 固定値 |
画像の横幅(ピクセル) | 18 | 4byte | 0x00 00 07 80 | 1920 |
画像の縦幅(ピクセル) | 22 | 4byte | 0x FF FF FB C8 | -1080(縦幅の2の補数) |
プレーン数 | 26 | 2byte | 0x00 01 | 固定値(プレーンとは?) |
1画素の色数 | 28 | 2byte | 0x00 20 | bits_per_pixelの値 |
圧縮形式 | 30 | 4byte | 0x00 00 00 00 | rawファイルなので0固定 |
画像サイズ | 34 | 4byte | 0x00 1F A4 00 | 1920*1080 |
水平解像度(ppm) | 38 | 4byte | 0x00 00 00 00 | 固定値 |
垂直解像度(ppm) | 42 | 4byte | 0x00 00 00 00 | 固定値 |
色数 | 46 | 4byte | 0x00 00 00 00 | 固定値 |
重要色数 | 50 | 4byte | 0x00 00 00 00 | 固定値 |
rawファイルにbitmapヘッダをくっつける
必死こいてポチポチ計算してヘッダファイル作ったらあとは、rawファイルにくっつけるだけ。
cat bmp_head.bin temp.raw > test.bmp
何故かできた
これで何故かbitmapファイルでスクリーンショットが作れてしまった。