はじめに
前記事「スマホで撮影した写真を白黒二値化してサーマルプリンタに出力する」では、単純な白黒二値化のアルゴリズムのため、期待外れな印刷結果となった。今回は誤差拡散法に変更した内容をまとめます。
誤差拡散法
前回の単純な白黒二値化があまりにもがっかりな結果であったので、誤差拡散法で白黒二値化しました。使用したアルゴリズムはフロイド-スタインバーグ・ディザリングと言われるもので、Wikipediaに書かれていた擬似コードを参考にJavascriptに書き直しました。
グレースケールのイメージを入力して白黒二値化します。
//誤差拡散法(Floyd-Steinberg dithering)
const oldImage = grayscaleImage; //グレースケールのイメージ
const newImage = new Array(width * height).fill(0);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
let pixel = oldImage[y * width + x];
let quantError; //誤差
if (pixel > 127.5) {
quantError = pixel - 255;
pixel = 255;
} else {
quantError = pixel;
pixel = 0;
}
newImage[y * width + x] = pixel;
// 誤差拡散
if (x != width - 1) {
oldImage[y * width + (x + 1)] += 7 / 16 * quantError;
}
if ((x != 0) && (y != height - 1)) {
oldImage[(y + 1) * width + (x - 1)] += 3 / 16 * quantError;
}
if (y != height - 1) {
oldImage[(y + 1) * width + x] += 5 / 16 * quantError;
}
if (x != width - 1 && y != height - 1) {
oldImage[(y + 1) * width + (x + 1)] += 1 / 16 * quantError;
}
}
}
結果は以下の通り。左から元画像、中央はグレースケール化画像、右がフロイド-スタインバーグ法による白黒画像です。素晴らしい出来です。元画像のサイズ[2176x4608]を、プリンタの仕様に合わせて384x813にリサイズしています。
白黒カメラプリンタ
この記事のタイトルである「スマホで撮影した写真を白黒二値化してサーマルプリンタに出力する」アプリを「白黒カメラプリンタ」と名付けました。画面イメージを示します。
(「白黒カメラプリンタ」は こちら からどうぞ。別ウィンドウで開きます。obnizを持ってない方でも「obniz idを聞いてくるダイアログでキャンセル」すれば、各イメージの確認はできます。)

なお、DP-EH600アクセスライブラリの詳細は、後日別記事で紹介いたします。
2018.12.23追記
DP-EH600アクセスライブラリをこちらに公開しました。
「印刷」を押すとサーマルプリンタから出力します。(当然ですが、obnizとオンラインになっている必要があります。)

この縦長の写真で印刷時間は22〜3秒の性能です。
まとめ
自分としては当初の目的が達成できたと思っていて大満足です。お正月に家族が揃った時に、これで写真を撮ってその場で印刷して見せてあげようと思います。
(完)