ByteScope

Image to C Array

行きと帰りの両方。絵をファームウェアがコンパイルできる配列に、配列を目で見られる絵に。

画像はブラウザから出ません。全ピクセルの変換がこのタブの中で完結します。

元画像

PNG / JPG / SVG / GIF / WebP をここにドロップ

クリックして選ぶこともできます。デコードはページ内で、アップロードはしません。

一辺 4096 px まで。パネルは元の絵よりずっと小さいのが普通で、ここでどこまで縮めるかが、1ビットに背負わせるディテールの量を決めます。

ピクセル形式

ディザ
ピクセルの並び
ビット順
バイト順

出力プレビュー

元画像を縮めたものではありません。詰め終わった配列を読み戻した絵なので、ディザの網目もビット順も行の詰め物も、実際に出力されるとおりです。

C ソース

まだ何もありません。
まだ何もありません。

配列から画像に戻す

C 配列を貼るか生のダンプをドロップして、絵が斜めにずれなくなるまで幅を動かしてください。素性の分からないフレームバッファを特定する定番の手ですが、自分の作った配列が正しいことを一番早く確かめる方法でもあります。

16/32ビットのトークンのバイト順

1バイトより広いトークンにだけ効きます。TFT_eSPI の配列が並べる uint16_t の値がこれです。

または .bin のダンプをドロップ

フラッシュの一区画でも、SD カードのセクタでも、ピクセルが入っていれば何でも。

幅が違うフレームバッファは斜めの縞にずれます。縞がまっすぐになるまで動かせば、そこが本当の幅です。

ピクセルの並び
ビット順
バイト順

まだ読み込んでいません。

このツールについて

ディスプレイが本当に欲しがっている配列

ディスプレイのドライバは PNG を受け取りません。受け取るのは、そのコントローラが読む並びちょうどに置かれたバイト列で、その並び方はどれも誰かが決めるしかない項目です。1ピクセル1ビットか16ビットか。いちばん左のピクセルはビット7か、ビット0か。行を順に並べるのか、高さ8ピクセルのページに切るのか。赤は上位5ビットか下位5ビットか。ここに画像を落として形式を選べば、それに合わせてバイトが詰まります。mono、gray2、gray4、gray8、LVGL が使う alpha1 から alpha8 までのマスク、rgb565、rgb888、argb8888。設定の横に出るプレビューは元画像を縮めたものではなく、詰め終わった配列を読み戻したものなので、見えているものがそのままパネルに出ます。

1ピクセル1ビットを何に使うか

128x64 の OLED は 8,192 ピクセル、1つあたり1ビット。つまり絵の出来は、白と黒の境目をどこに置くかだけで決まります。線画やアイコンなら素直なしきい値が正解で、スライダーがその境目を動かします。写真なら誤差をばらまくほうがよく、Floyd–Steinberg は隣のピクセルへ拡散して新聞印刷のようなざらつきを、Bayer 4x4 の規則的な行列は小さいパネルで読みやすい網目を作ります。明るさとコントラストは境目より前、invert は後に効き、どれもドラッグしている最中にプレビューが描き直されます。アイコンが1ビットに耐えるかどうかは、出るサイズで見るしか判断のしようがないからです。

フレームバッファを画像に戻す

逆方向は誰も作っていない機能で、しかも手元にある本当の疑問——この配列で合っているのか——に答えるのはこちらです。C 配列を貼るか(0x のバイト、十進、\x エスケープ、裸の16進の塊、波かっこやコメントや #define 行があってもなくても構いません)、フラッシュから抜いた生の .bin を落とすと、画像として描かれます。あとは幅のスライダーを動かすだけ。幅が違うフレームバッファは斜めの縞にずれ、幅が合った瞬間に絵がぴたりと立ち上がります。素性の分からないダンプを特定する定番の手ですが、自分の出力の点検にもそのまま使えます。アイコンを変換し、その配列を貼り戻して、出てきた絵が自分のアイコンに見えるなら、ビット順も行の詰め物も合っています。読めなかったトークンは飲み込まれず位置つきで報告されるので、貼り付けた配列のタイプミス1つで失うのは値1つ、残り全部ではありません。

テンプレートとバイト順、そして必ず引っかかるやつ

同じバイト列でも、何にコンパイルさせるかで包み方が変わります。素の static const uint8_t 配列、_WIDTH と _HEIGHT のマクロが付いた Adafruit GFX の PROGMEM 配列、#define で寸法を書く u8g2 の XBM、LVGL v8 の lv_img_dsc_t と v9 の lv_image_dsc_t、TFT_eSPI の pushImage() に渡す uint16_t 配列、そして framebuf のコンストラクタを隣に書いた MicroPython の bytes リテラル。引っかかるのは TFT_eSPI です。16ビットのピクセルを上位バイトから読むので、このテンプレートのときだけ RGB565 をビッグエンディアンで詰める必要があり、他のテンプレートはすべてリトルです。ここではテンプレートを選べばバイト順がそれに従います。きれいにコンパイルできて色だけ違う配列は、誰も見つけたくないたぐいのバグだからです。全部このタブの Web Worker で動きます。アップロードなし、アカウントなし、まだ発表していない製品のアートワークは手元から出ません。

よくある質問

SSD1306 の OLED にはどの設定ですか?

形式は mono、ピクセルの並びはページ、ビット順は LSB からです。SSD1306 や SH1106 はメモリを高さ8ピクセルの縦ページとして持ち、1列1バイト、ページの一番上のピクセルがビット0に入ります。ページ並び+LSB からはまさにそれを作ります。素直に行ごとに並べた配列を送ると、画像が8本のスライスに刻まれたように見えるのはこれが理由です。コントローラに直接書くのではなく u8g2 の XBM 用ヘルパに渡すなら、行ごと+MSB からにしてください。

TFT_eSPI に出すと色がおかしくなります。

ほぼバイト順です。pushImage() は16ビットのバッファを上位バイトから読むので、下位バイトを先に詰めた RGB565 は、純粋な赤 0xf800 が 0x00f8、暗い青灰色に変わります。配列はコンパイルでき、サイズも合っていて、色だけが違う。ここで TFT_eSPI のテンプレートを選べばビッグエンディアンで詰め、そのことも表示します。よそから持ってきた配列の色が崩れているなら、逆変換ビューアに読み込ませてバイト順を切り替えてみてください。どちらで書かれたものかは絵がすぐ教えてくれます。

LVGL のバイナリ画像ファイルは作れますか?

作れませんし、作れるふりもしません。ここが出すのは C のソースです。ピクセル配列と、名前付きフィールドを持つ lv_img_dsc_t(v8)または lv_image_dsc_t(v9)の構造体リテラル——プロジェクトに入れてコンパイルするあれです。独自ヘッダを持つ .bin 形式は別物で、当てずっぽうで作るくらいならここでは実装しない、という判断をしています。カラーフォーマットの欄も任せません。あなたのビルドが期待するトークンを渡せばそのまま書き出し、空なら UNKNOWN と TODO が並びます。定数をでっち上げることはありません。

フラッシュのダンプはあるのに、画像の幅が分かりません。

.bin を逆変換ビューアに落とし、ピクセル形式を当てて、幅スキャンを1から上げていってください。正しい幅以外では各行が一定量ずれ、まっすぐな辺が斜めになるので表示が歪みます。幅が本当のストライドに一致した瞬間、すべてが一度に揃います。あとはピクセルの手前にあるヘッダぶんだけオフセットをずらします。データが足りなくてもここではエラーになりません。裏にバイトがないピクセルは透明で描かれて数えられるので、途中までのダンプでも拒まれずにスキャンできます。

画像はどこかにアップロードされますか?

されません。ファイルはあなたのブラウザ自身がデコードし、ピクセルの量子化とパックはこのタブの Web Worker で行い、タブを閉じれば全部消えます。アップロードの工程も、アカウントも、サーバ側の処理もありません。これは他のツールよりもここで効いてきます。未発表の製品のアイコン一式は、まさに「オンライン変換サイトに貼るな」と言われる種類のファイルだからです。