jpegicon

ちょっと思いついたので作ってみたものです
といっても実は春の始まり頃に作ったもので一応ブログ内からリンクたどれば見れたのですでに知ってる人がいるかも知れません

textimg

textimg-ex

そういえば結構前にも似たものを作ったことがありました
文字列を色で暗号化


上のところに文字を入力すると下に画像が作られます
この画像をドラッグしてデスクトップなどに保存して、
もう一度ページを開き直して保存した画像をページにドロップすると・・・
あら不思議、入力したテキストが表示されるんです

画像の中に読める文字が表示されてるわけじゃありません
画像はよくわからない模様みたいなものです

Twitter みたいな文字数制限あるけど画像貼れるところに貼ると、分かる人にぞわかるメッセージが書けたりしますね

しくみ

仕組みは前のと同じ感じです
Chrome で #FFFFFFFF と #FFFF 形式の透過色も使えるようになったのを聞いて、 #FFFF と U+FFFF って似てるしそのままで文字と色の両方に使えそうと思ったことから作り始めました

例えば 「あ」 という文字は U+3042 という文字コードです
なので 「あ」 という文字は #3042 という色に置き換えます
これを全部の文字分並べてたものが見えてる画像です

文字数によっては綺麗な正方形にならないので最初の 1px は文字数を表していて
その数のピクセルより後はダミーです

Canvas の罠

こういうことするのって canvas が向いてるかなって思って使っていました
だけどなぜか正常に復元してくれません

おかしな動きのところだけ取り出してみるとこうなっていました
1px の色を canvas に書き込んでそれを読み取っています

function fn(r, g, b, a){
const cvs = document.createElement("canvas")
cvs.width = 1
cvs.height = 1
const ctx = cvs.getContext("2d")
ctx.globalAlpha = 1
ctx.fillStyle = `rgba(${r},${g},${b},${a/255})`
ctx.fillRect(0, 0, 1, 1)
return ctx.getImageData(0, 0, 1, 1).data
}
fn(200, 200, 200, 26)
// [206, 206, 206, 26] (Chrome)
// [ 196, 196, 196, 26 ] (Firefox)

fn(200, 200, 200, 179)
// [199, 199, 199, 179] (Chrome and Firefox)

fn(200, 200, 200, 144)
// [200, 200, 200, 144] (Chrome and Firefox)

fn(100, 200, 50, 3)
// [85, 255, 0, 3] (Chrome)
// [ 85, 170, 85, 3 ] (Firefox)

function fn(r, g, b, a){
const cvs = document.createElement("canvas")
cvs.width = 1
cvs.height = 1
const ctx = cvs.getContext("2d")
ctx.globalAlpha = 1
const id = ctx.createImageData(1, 1)
id.data[0] = r
id.data[1] = g
id.data[2] = b
id.data[3] = a
ctx.putImageData(id, 0, 0)
return ctx.getImageData(0, 0, 1, 1).data
}
fn(200, 200, 200, 26)
// [196, 196, 196, 26] (Chrome) (same as Firefox's fillRect)
// [ 205, 205, 205, 26 ] (Firefox)

fn(200, 200, 200, 179)
// [199, 199, 199, 179] (Chrome) (same as fillRect)
// [ 200, 200, 200, 179 ] (Firefox)

fn(200, 200, 200, 144)
// [200, 200, 200, 144] (Chrome and Firefox) (same as fillRect)

fn(100, 200, 50, 3)
// [85, 170, 85, 3] (Chrome) (same as Firefox's fillRect)
// [ 170, 255, 85, 3 ] (Firefox)

ある色で塗ってその色を取り出すだけなのに色が変わってしまってます
書き込みは fillRect と putImageData という 2 種類でためしています (上と下)
色が変わるにしてもどっちも一緒になりそうなのに一緒だったり違ったりします
なんかもうよくわかりません

あんまり自信はないですが、ぐぐってみた感じだと canvas は完全に指定した色を書き込めなくて OS やブラウザやグラフィック性能などで微妙に違う結果になる仕様があるみたいです
ということは色がずれると使い物にならない今回のツールに canvas は使えない!

pngjs

仕方ないので png を作ったり読み取ったりできるライブラリを使うことにしました

pngjs っていうのを使ってます
似たもので yahoo にも pngjs がありました
でも yahoo の方だとこのライブラリがまた別のライブラリを必要としていたりで重くなりそうなので依存のないシンプルなほうにしました
そっちのほうが Star も多いですしね

つかってみるとこっちでも困ったことがあって、もともと Node.js のツールなのでブラウザだと動かないところがありました
必要なメソッドがブラウザにはないみたいです

Uint8Array のメソッドにこういうの追加して動くように出来ました

Uint8Array.prototype.readUInt32BE = function(offset) {
return new DataView(this.buffer).getUint32(offset, false)
}
Uint8Array.prototype.readInt32BE = function(offset) {
return new DataView(this.buffer).getInt32(offset, false)
}

単純に文字コードとカラーコードを変換するツールをつくってみたかっただけなのに、なんでこんな苦労してるんでしょ
今回は以上です