自分の絵を電子工作で使うには

By ikubaku, Sat 25 December 2021, in category 技術系

art, baremetal, graphics, technical

この記事は KMC Advent Calendar 202124日目の記事です。23日目の記事は準備中です(投稿され次第リンクを追記します)。

背景

最近、安価な液晶ディスプレイモジュールやM5Stackなどの液晶画面を搭載したマイコンボードが手に入りやすくなり、それらを制御する知見も蓄積してきました。それによって電子工作で画面を搭載したものづくりが簡単にできるようになりました。自分のプロジェクトに画面を付けられるようになったということはこれまで7セグやLEDで表示していた情報を文字などにして表示するだけでなく、画像やアニメーションも表示できるということです。せっかく自分で作ったものですから自作のロゴやキャラクターを表示させたくなるかもしれません。また情報を表示するフォントも自作のものを用いるとかっこよくなるかもしれません。

しかし電子工作におけるこのような画像素材の利用はパソコン用のアプリケーションで自作の画像を使う場合とは異なる部分があります。例えばOSや汎用的な画像処理ライブラリがない環境で画像をどのような形式にして取り扱うか、画面はどのような色を表現できるかなどを考慮する必要があります。

この記事ではVGA程度の解像度を持つカラー液晶画面と小型OLEDディスプレイの2つにおいて、PC上で作成した高解像度のイラストをできるだけきれいに表示させる方法について考えようと思います。

解決するべき問題

まずディスプレイモジュールによる制約について考えます。電子工作で使うディスプレイモジュールの性能は様々です。ここでは比較的小型で良く利用されると考えられる小型カラー液晶画面とモノクロ表示のOLEDディスプレイについて考えます。

解像度

小型のディスプレイモジュールは解像度が低い傾向にあります。画素数が多いものでもVGA前後、小さければ100×100ピクセル程度です。したがって多くの場合画像を縮小して表示する必要があります。

色域

モノクロディスプレイの場合色を表現できないことは言うまでもないですが、カラーディスプレイの場合ても色域に注意が必要です。実際市販されている小型ディスプレイモジュールには24bitカラーが表示できない(RGB各チャンネルに8bitのデータが振られていて、かつ実際に画素を256段階に分けて駆動できるもの)ものがあります。このように表現できる色が少ない場合は画像を作成する際の色選びに考慮が必要です。

表現できる色が限られることは、単にある色が使えないという以外の形の問題も引き起こします。例えばアンチエイリアシングのような色の勾配を使った表現ができなくなるおそれがあります。(変換のされ方にもよりますが)色の情報量を小さくすると近い色だった画素がすべて同じ色になってしまうので勾配が消えてしまうことでアンチエイリアシングによる効果がなくなってしまいます。さらにモノクロOLED・液晶ディスプレイでは画素の輝度を制御できないことが多く、この場合は輝度によるグラデーションやアンチエイリアシングが不可能になります。

またディスプレイの制御に用いるコンピュータの性能によっては画像データのサイズに制約ができてしまったり、その場で画像データを変換する余裕がなかったりすることがあります。この場合はディスプレイモジュールの性能が十分であっても画像データの情報量を削減することになるので上記のような問題が発生します。

画像データの形式

電子工作で使うコンピュータはマイクロコントローラなど特殊なものが多いのでPNGやJPEGなどの汎用的な画像データだとそのまま使えない可能性があります。使えない場合は事前にビットマップ形式のデータに変換した上で、定数としてソースコードに埋め込む必要があるかもしれません。

まとめると解像度が小さく、色の種類も少ないような状況でそれっぽい画像を表示できるように画像データを工夫する必要があります。また画像データをどのように組み込んでおくかも考えなければいけません。

既存のノウハウなど

元となる大きな画像やイラストから解像度が小さく使われている色も少ない画像を作成する方法として様々なものが知られています。パソコンに入っている画像ビューアで画像を縮小しても比較的きれいな画像が得られますし、最初から低解像度な絵やイラストをデザインする方法も検索エンジンを使えばたくさんヒットします。

元となる画像を作成する際にも工夫できることがあります。イラストを元にする場合は画像を小さくしてもキャラクターの特徴が残せるようにチャームポイントになる部分を誇張したり、頭身の低いキャラクターとしてデザインしたりすると良いでしょう。最終的にモノクロにする場合は思い切って配色のコントラストを上げるのも良さそうです。

画像データのソースコード中の埋め込みについてもいくつか手があります。単純な方法としては PillowImageMagick などを使って画像をビットマップデータに変換し、数値定数としてソースコードに埋め込んでしまうというものがあるでしょう。また embedded-graphicsを使う場合は tinybmpinclude_bytes! マクロを組み合わせることでプログラムのコンパイル時に自動でこのような処理を行うことができます。さらにWio Terminal+Arduinoによる開発ではSD/MMCから画像データを読み込んで表示させることができます。

とりあえずやってみる

ここでは画像縮小などの既存の方法を使って小型ディスプレイに自作の画像をきれいに表示できるかどうか試してみます。

表示する画像として最近 KMCお絵描きAdvent Calendar 2021 で投稿したちびキャラのイラストを使いました( https://www.pixiv.net/artworks/94884989 )。

ディスプレイとしてはWio Terminal( https://jp.seeedstudio.com/Wio-Terminal-p-4509.html )の液晶ディスプレイとaitendoで販売されている128×64モノクロOLEDディスプレイ( https://www.aitendo.com/product/18940 )を使いました。

カラー液晶に表示する

ここではWio TerminalとArduinoを使ってできるだけ楽な手順でやってみます。

Wio Terminalの液晶ディスプレイの解像度は320×240です。元画像のサイズは8192×8192だったのでまずこれを画像ビューアで240x240に縮小してみます。

image shrinked

一見すると大丈夫そうです。さらに https://wiki.seeedstudio.com/Wio-Terminal-LCD-Loading-Image/#image-format-configuration の手順に従ってWio Terminalで表示可能な形式のビットマップ画像データ(拡張子がbmpだが実はBMP画像ではない)に変換します。16bitカラーとして出力してサンプルの通りに表示させてみたところ以下の画像のようになりました。

wio terminal

主観的な評価ですが線の滑らかさがしっかり表現されていて良さそうに見えます。少し気になるところとしては全体的に青白くなってしまっているように見えることでしょうか。特に背景はほとんど真っ白になってしまっています。これは16bitカラーに変換したときにRGBチャネルがそれぞれ5, 6, 5 [bit] に縮小されて、薄い赤色が出にくくなってしまったかもしれません。

モノクロOLEDディスプレイに表示する

今回使うモノクロOLEDディスプレイは画素に階調がありません。したがって画像の縮小以外にも前処理が必要になります。ここでは元のイラストに2階調処理をかけた後、先にできる不自然な塊を除去する形でイラストをドット絵化しました。また黒目の部分と体色のアクセントになっている色の部分にも塗りを追加しました。調整後のドット絵が次の画像です(おそらく多くの端末で見づらいので拡大しています)。

image shrinked dot

後は画像を1bitBMPに変換しておきます。

ではTinyBMPを使ってBMP画像を読み込みディスプレイに表示させてみます。ペルフェラルの初期化コードなどを省くと、以下のようなコードで実現できます。

// 縦向きにして全体表示したいのでRotate90に設定
let mut display: GraphicsMode<_> = Builder::new().with_rotation(Rotate90).connect_i2c(i2c).into();

display.init().unwrap();
display.flush().unwrap();

// BMP画像のデータを埋め込む
let bmp_data = include_bytes!("../resources/image.bmp");

// BMP画像データをパースして画像データを取り出す
// BMP画像の色の形式とPixelColorの値は同じものにする(例えば16bitカラーならRgb565に指定する)
let bmp = Bmp::<BinaryColor>::from_slice(bmp_data).unwrap();

Image::new(&bmp, Point::new(0, 0)).draw(&mut display).unwrap();

display.flush().unwrap();

実行すると写真のように表示されました。

tinybmp

こちらも概ね良さそうです。

まとめ

思ったよりうまく行ってしまったので特に新たな知見を得ることはできませんでしたが、自分のイラストを電子工作で使う上で必要な作業を一通り確認できたほか、パソコンで描いたものが実際にどのような見た目になるのか感覚がつかめたので個人的には良かったと思います。今後他の画像で問題が起こらないか試してみたり、アニメーションの描画を実装してみたりしようと思います。

宣伝

KMC Advent Calendar 2021の次の記事はhsjoihsさんの記事の予定です。テーマは「電華打字機」です。こちらもぜひご覧ください。

またKMCはこの年末に開催されるコミックマーケット99にブース出展します。出展は2日目、場所は東地区“ツ”ブロック-29aです。お立ち寄りいただけると嬉しいです。