あっきぃ日誌

鉄道ブログのような技術系ブログのようななにか

Pimoroni PicoGraphicsでビットマップファイルを使う(とりあえず白黒)

Raspberry Pi Advent Calendar 2022の2日目です。

adventar.org

Pimoroniのディスプレイ系モジュールをPimoroniビルドのMicroPythonで使うときは、PicoGraphicsという共通の描画ライブラリが使えます。

github.com

画像を描画するときはJPEGのみ対応のようですが、最近おもに触っているPico Inky Packは白黒2値で、無圧縮でもビットマップファイルのほうがファイルサイズがコンパクトになるので、ビットマップファイルのデコードに挑戦してみました。久しぶりにデコードするなあと思ったけれど、OSAkkieでビットマップのデコーダーに触れたことはなさそう?でした。あれ?

Pico Inky Packshop.pimoroni.com

Pico Inky パックwww.switch-science.com

(ところではてなブログでShopifiの埋め込みがきれいにできないの、どうにかなってほしいんですけども。。)

参考

Pythonで扱うには、バイト単位でread()して、unpackで解釈していけば良いみたいです。おもったよりかんたんそう。

qiita.com

フォーマットはWikipediaを参考にしました。充実してるな。

ja.wikipedia.org

つくった

qiitaの記事では関数でしたが、クラスで実装してみました。こんな感じで書けるようになっています。

import bitmap
from picographics import PicoGraphics, DISPLAY_XXX

display = PicoGraphics(display=DISPLAY_XXX)

path = "a.bmp"
bmp = bitmap.bitmap(path, display)
bmp.decode(x=0, y=0, reverse=False, transparent=-1)

デコードはひとまず白黒のみ対応です。カラー対応が必要になった時はまたがんばります。ST7789系のLCDを使うときかしら🤔

PicoGraphicsにデータを渡す方法が基本ピクセル単位(頑張っても直線単位)なので、ざっくり以下のような方法でデコードをしており、デコードにかかる時間はJPEGに大敗します。かなしみ。二次元配列をボーン!って投げつけられたりすると良さそうですけど、そうも行かないかあ。

for y in reversed(range(0, self.height)):
    for x in f.read(xの横幅分のビットに相当するバイト数):
        self.display.set_pen(self.pallet[p])
        self.display.pixel(x, y)

# こうできたりしないかなみたいなやつ
# data = []
# for y in reversed(range(0, self.height)):
#     for x in f.read(xの横幅分のビットに相当するバイト数):
#         data.append((x, y, self.pallet[p]))
# self.display.set_pixels(data)

それでもちょいちょい改善はできたので、4秒くらいでデコード完了します。いやそれでも遅いけど。。。

細かいべんり機能

明日のブログで紹介するPico GFX Packでも使えるので、それに合わせて色の反転と透過もサポートしました。反転は、やらないとGFX Packで色が反転してしまうので実装しました。透過は、画像と文字の重ね合わせとかをやるときに便利かなと思ってつけてみました。

描画位置の指定もできます。べんりですね。


コード

Picoスクリプト置き場のリポジトリに置きました。

github.com

まとめ

ファイルはコンパクトにできたけど、デコードが遅いので微妙というオチでした。jpegdecみたいにCで書けたらワンチャンですが、ソコまでの気合はたぶん出ないですね……。