JavaScript バイナリファイルを読み込む - Why it doesn't work?
JavaScript バイナリデータを扱う。4バイトの数値の配列をunsigned long(uint32)型の数値へ変換する - Why it doesn't work?
JavaScript バイナリデータの配列をUTF-8文字列へ変換する - Why it doesn't work?
久しぶりのJavaScriptです。そして、このバイナリシリーズもまだ続いてます。
外部データのバイナリデータに含まれてるPNG画像のデータを抽出し、それをブラウザ上で表示したいと考えました。
通常はファイル名をimgタグに指定します、当然ながらバイナリデータを指定しても表示されません。
<img src="sample.png">
調べたところ、Base64でエンコードした画像データなら表示できると言うことで、バイナリの画像データをBase64でエンコードすることにしました。
<img src="data:image/png;base64,iVBORw0KGgo....">
ちょっと大きなデータで申し訳ないですが、実際のPNG画像のバイナリデータを使用してみました。
1. 取得したバイナリデータを文字列に変換後、base64文字列に変換する方法
var data = [ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x08, 0x06, 0x00, 0x00, 0x00, 0xB9, 0xB7, 0x37, 0xD9, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0E, 0xC4, 0x00, 0x00, 0x0E, 0xC4, 0x01, 0x95, 0x2B, 0x0E, 0x1B, 0x00, 0x00, 0x00, 0x1E, 0x49, 0x44, 0x41, 0x54, 0x28, 0x53, 0x63, 0xBC, 0x72, 0xE1, 0xC4, 0x7F, 0x06, 0x12, 0x01, 0x13, 0x94, 0x26, 0x09, 0x8C, 0x6A, 0x82, 0x82, 0x51, 0x4D, 0x60, 0xC0, 0xC0, 0x00, 0x00, 0x95, 0xD0, 0x03, 0x83, 0x79, 0x73, 0x2C, 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 ]; var b64 = "data:image/png;base64," + btoa(String.fromCharCode.apply(String, data)); console.log(b64);
2. BlobとFile APIを使用する方法
var data = new Uint8Array([ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x08, 0x06, 0x00, 0x00, 0x00, 0xB9, 0xB7, 0x37, 0xD9, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xAE, 0xCE, 0x1C, 0xE9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0E, 0xC4, 0x00, 0x00, 0x0E, 0xC4, 0x01, 0x95, 0x2B, 0x0E, 0x1B, 0x00, 0x00, 0x00, 0x1E, 0x49, 0x44, 0x41, 0x54, 0x28, 0x53, 0x63, 0xBC, 0x72, 0xE1, 0xC4, 0x7F, 0x06, 0x12, 0x01, 0x13, 0x94, 0x26, 0x09, 0x8C, 0x6A, 0x82, 0x82, 0x51, 0x4D, 0x60, 0xC0, 0xC0, 0x00, 0x00, 0x95, 0xD0, 0x03, 0x83, 0x79, 0x73, 0x2C, 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 ]); var blob = new Blob([data], { type: "image/png" }); var reader = new FileReader(); reader.onload = function() { var b64 = reader.result; console.log(b64); } reader.readAsDataURL(blob);
どちらの方法でも以下のようなデータが出力されるので、これをイメージタグに設定すればブラウザ上で表示されます。
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAMCAYAAAC5tzfZAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAeSURBVChTY7xy4cR/BhIBE5QmCYxqgoJRTWDAwAAAldADg3lzLDMAAAAASUVORK5CYII=
方法2のポイントは、Uint8Arrayタイプの配列にデータを設定すること、エンコードの完了は非同期で通知されることです。
他にも方法はあるようですが、今回はこれまで。