なでしこさんでドットマトリクスLED風表示
今週ももう日曜日⋯⋯
夜はクソ寝倒してしまった⋯⋯
日中は意識を保つことに成功したものの、愚かにも先延ばしにしまくっていた確定申告関係の作業で埋まり、時間が無くなった⋯⋯
仕方ない、今日もなでしこで適当なプログラムを書いてstreakを繋ぐか⋯⋯
今回やったこと
なでしこで、ドットマトリクスLED風に「大石泉すき」の文字を流して表示する。
プログラム
ドットマトリクスLED風表示 (なでしこ3貯蔵庫)
今回の流す文字には、8×8ドット日本語フォント「美咲フォント」 (美咲ゴシック) を用いた。
このフォントは、「8×8ドット」を謳っているが、ほとんどの文字を1行・1列あけて7×7ドットで表現している。
そのため、今回のように1行だけで用いると、1行無駄になってしまって残念な仕上がりになってしまった。
美咲フォントが解決する問題として言及されている恵梨沙フォントは8×8ドット一杯に作られているらしい (美咲フォントのページより) が、残念ながらこちらは自由には使えないようである。
この使い方により適した別のフォントを探すか、8×8ドットではなく5×7ドットのドットマトリクスLEDを使うことにすれば、改善できるかもしれない。
実装のポイント
画像と表示幅の設定
画像URLは「data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAICAYAAAC/K3xHAAAApUlEQVQ4T81T0RKAMAjK///o2rroyEPZ3tpTbSqgGOc4x3Mi4qDf+3beVUfF5rucqzA6/BIcnJ2AleJKJISsNKDLtwJGwDuBHMzd3OlcFQui3ZQ6HCUmVibgOuTeYcVJfMemzo53XScAgAycv2chkOPvap8Usaq+tRAEKKKc3AHk3B278XQcWWkh7ED2OzrJS8wFeElz9ytSTpiq70R9LOSC//h+AcfTrOkYDa7yAAAAAElFTkSuQmCC」。
列数は16。LEDの点灯パターンとして用いる画像のURLと、表示するLEDの列数 (横に何個並べるか) を設定する。
今回は、データURLを用い、美咲フォントピッカーで作成した画像を埋め込んだ。
この画像は、黒が点灯、白が消灯を表す。
今回の仕様では、表示する行数 (縦に何個並べるか) は、画像の高さをそのまま用い、明示はしない。
一方、表示する列数は、スクロールしながら一部を表示するため、画像からすぐには求まらないので、明示する。
画像データを読み取る関数の用意
●(IMGの)画像データ取得とは
定数の画像幅はIMG$width。
定数の画像高はIMG$height。
定数のキャンバスは「canvas」のDOM要素作成。
キャンバスの「width」に画像幅をDOM属性設定。
キャンバスの「height」に画像高をDOM属性設定。
キャンバスで描画開始。
IMGを[0,0]に画像描画。
定数の画像データは描画中コンテキストの「getImageData」を[0,0,画像幅,画像高]でJSメソッド実行。
定数の画像データ本体は画像データ$data。
定数の取得結果は空配列。
行で0から(画像高-1)まで繰り返す
定数の取得結果行は空配列。
列で0から(画像幅-1)まで繰り返す
取得結果行に(画像データ本体[(行×画像幅+列)×4]が128未満)を配列追加。
ここまで。
取得結果に取得結果行を配列追加。
ここまで。
取得結果を戻す。
ここまで。キャンバスを使用して、画像の色データを読み取る。
キャンバスを画面上に出さないために、『キャンバス作成』命令ではなく、作成した要素を自動で追加しない『DOM要素作成』命令を用いてキャンバスを作成する。
そして、作成したキャンバスに画像を描画し、getImageData() メソッドを用いて画像のデータを取得する。
さらに、取得した (フルカラーの) 画像のデータを二値に変換する。
今回は、白黒の画像しか入力されないことを前提とし、簡単のため赤成分のみで白 (消灯) か黒 (点灯) かを判定することにした。
最後に、読み取った色データを二次元配列で返す。
画像データの読み取り
表示画像は画像URLの画像読み待つ。
画像データは表示画像の画像データ取得。
行数は画像データの表行数。『画像読待』命令を用い、先ほど設定したURLから画像を読み込む。
さらに、用意した関数を用い、それを二値の二次元配列に変換する。
また、その結果から表示する行数 (=画像の高さ) を取得する。
ドットマトリクスLED風画面の構築
●(LEDをVに)点灯設定とは
もし、Vならば
LEDの「色」に赤色をDOMスタイル設定。
違えば
LEDの「色」に灰色をDOMスタイル設定。
ここまで。
ここまで。
●LED作成とは
定数のLEDは「●」のラベル作成。
LEDをオフに点灯設定。
LEDを戻す。
ここまで。まず、LEDに見立てる「●」の文字を作成する関数「LED作成」を用意する。
その文字に、LEDの点灯/消灯を表現する色を設定する関数「点灯設定」も用意する。
「LED作成」では、「点灯設定」を用いて、作成した部品を消灯した状態に初期化する。
マトリクスは「DIV」のDOM部品作成。
マトリクスに{
display: "inline-block",
padding: "0.2em",
whiteSpace: "nowrap",
lineHeight: "1em"
}をDOMスタイル一括設定。
マトリクスの「背景色」に黒色をDOMスタイル設定。ドットマトリクスLEDの土台となる要素を作成する。
外側に少し枠をつける (padding)
画面が狭くても、行の途中で折り返さない (whiteSpace)
1行を1列と同じくらいの幅で表示する (lineHeight)
というスタイルを設定した。
マトリクスにDOM親要素設定。
LED配列は空配列。
(行数)回
LED行は空配列。
(列数)回
LED作成してLED行に配列追加。
ここまで。
LED配列にLED行を配列追加。
改行作成。
ここまで。土台の中に、LEDに見立てた部品を作成し、二次元配列「LED配列」に格納する。
画像データに基づくLEDの状態の設定
●(OFFSETで)画像LED表示とは
行で0から(行数-1)まで繰り返す
列で0から(列数-1)まで繰り返す
定数の表示列は(OFFSET+列)を(画像データの表列数)で割った余り。
LED配列[行][列]を画像データ[行][表示列]に点灯設定。
ここまで。
ここまで。
ここまで。画像のどの列を表示範囲の左端にするかを OFFSET で指定し、実際にLEDの状態を設定する関数である。
でもこれ、よく見ると、ライブラリ化を想定するなら「LED配列」や「画像データ」も引数で指定できるようにするべきなのにしておらず、この場だけで使う単なる処理のグループ分けであれば「OFFSET」のかわりに関数の外に置いた「表示位置」を直接参照すればいいはずである。
このどっちもしていないというのは、中途半端なコードだなあ。反省。
表示位置は0。
0.2秒毎には
表示位置で画像LED表示。
表示位置は(表示位置+1)を(画像データの表列数)で割った余り。
ここまで。『秒毎』関数を用いて、「表示位置」を変えながら「画像LED表示」関数を用いることで、LEDの点灯パターンを進めていくようにした。
まとめ
なでしこを用いて、ドットマトリクスLED風の画面表示を作成し、そこに「大石泉すき」の文字を流すことができた。


コメント