ししかわ商店

2018/12/18

M5Stack Avatarでビットマップ画像の顔パーツを表示する

M5Stack
placeholdercover image

この記事はM5Stack Advent Calendarの12日目の記事です。

M5Stack Avatarとは


私が開発しているM5Stack用のライブラリです。液晶にかわいい顔を表示することができます。

https://github.com/meganetaaan/m5stack-avatar

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f32303434372f34346233616164322d623531642d646264352d633630612d3336336538363831626362632e676966.gif

今までのアバターは円や矩形などの図形の組み合わせでしかパーツを作れませんでしたが、 この記事ではビットマップ画像をアバターの顔パーツとして描画する方法を紹介します。

XBM(XBitMap)は画像をC言語の配列として表現したファイル形式です。 ソースコードに埋め込んで利用できます。 バイナリイメージ(各ピクセルが白黒どちらか)専用です。

XBM形式への変換は次のようなWebアプリを使うのが最も手軽です。

https://www.online-utility.org/image/convert/to/XBM

または、開発環境にImageMagickをインストールしていれば、コマンド一発で変換できます。

1
$ convert input.png output.xbm

ここでは例として次の画像を変換してみましょう。

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f32303434372f31623239316136392d343930332d316561372d626536312d3939633566633962613238322e706e67.png

http://www.iconarchive.com/show/mono-general-4-icons-by-custom-icon-design/eye-icon.html

ImageMagickで変換しますが、このとき同時にアバターのパーツとして表示させたい大きさにリサイズします。 40x40ピクセルの場合は次のようになります。

1
$ convert eye.png -resize 40x40 eye_small.xbm

変換後のファイルは次のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#define eye_small_width 40
#define eye_small_height 40
static char eye_small_bits[] = {
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0x07, 0x00, 
  0xE0, 0xFF, 0xFF, 0x01, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xFE, 
  0x1F, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x00, 
  0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 
  0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 
  0x01, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x01, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 
  0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x00, 
  0xFE, 0xFF, 0x01, 0x00, 0x80, 0xFF, 0xFF, 0x07, 0x00, 0xE0, 0xFF, 0xFF, 
  0x3F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, };

画像の1ピクセルが1ビットに対応しており、8ビット=1バイト毎に16進数表記されているのがわかるかと思います。

前述のXBM画像をM5Stackのプログラムとして書き込むために、ファイルを少し修正する必要があります。

  • ファイルをリネームして拡張子を.hにします
1
$mv eye_small.xbm eye_small.h
1
2
3
4
5
#include <pgmspace.h>

#define eye_small_width 40
#define eye_small_height 40
PROGMEM const unsigned char eye_small[] = {/* 配列の中身はおなじため省略 */};

PROGMEMはデータを端末のフラッシュメモリ上に配置するためのキーワードです。 これでeye_small.hをインクルードすると画像が使えるようになります。

M5Stackの顔の各パーツはTFT_eSpriteクラスのメソッドを介して描画を行います。 XBM画像の描画はdrawXBitMapメソッドでできます。

前述の画像を描画するコードをライブラリのサンプルとして公開しました。 サンプルから画像描画部分だけ抜き出すと次のようなイメージです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

class BMPEye : public Drawable
{
  void draw(TFT_eSPI *spi, BoundingRect rect, DrawContext *ctx)
  {
    uint16_t color = ctx->getColorPalette()->get(COLOR_PRIMARY);
    uint16_t cx = rect.getCenterX();
    uint16_t cy = rect.getCenterY();
    spi->drawXBitmap(
        cx - eye_small_width / 2,
        cy - eye_small_height / 2,
        eye_small, eye_small_width, eye_small_height, color);
  }
};

以上でアバターの顔パーツとして画像が描画できるようになります。 この機能を使えばかなり表現力が増すかと思います。ぜひあなただけのカスタムアバターを作ってみてください!