Three.jsでテクスチャ用の画像ファイルを読み込んだときに、画像ファイルの種類を判定したかったので、そのときに調べたことをまとめる。
Three.jsでテクスチャの画像をローカルにある画像に変更するやドラッグ&ドロップでThree.jsのテクスチャ画像を入れ替えるでファイルを読み込むと、FILEオブジェクトを取得できるのでFILE.typeでMIMEタイプがわかる。はじめはこれで判定しようとしたが、どうもこのMIMEタイプは拡張子で判別されているようで心もとない。
読み込んだ画像ファイルをFileReader オブジェクトでデータURI形式として読み込む処理はすでに作成済みで、データURI形式で読み込むと画像ファイルはBase64方式になる。そこで、読み込んだファイルの先頭部分のBase64方式データを比較して画像の種類を判定することにした。
Base64は、バイナリデータを64種類の英数字のみでテキストデータに変換する方式で、3バイトのデータが4文字に変換される。Base63についてはBase64についてを参照。
pngの場合、先頭8バイトは固定の16進数89 50 4E 47 0D 0A 1A 0Aになる。先頭の3バイトをBase64に変換するとiVBOという文字列になるので、Base64方式のデータの先頭4文字を読み込んでiVBOと一致したらpngと判定するような処理をすることで、FILEオブジェクトのMIMEタイプを参照するよりは正確な判定ができる。
実際にpng画像を読み込んだときのデータURI形式の中身を見ると以下のようになっている。iVBO以降が画像データ。カンマ以降を画像データか判定すればよさそう。
data:image/png;base64,iVBORw0KGgoAAAA...
ドラッグ&ドロップでThree.jsのテクスチャ画像を入れ替えるでpng画像しかテクスチャ画像として使えないようにして、png以外のファイルがドロップされたときにアラートメッセージを表示するには、以下のようにtextureSwitchを書き換える。
Three.jsでテクスチャの画像をローカルにある画像に変更するやドラッグ&ドロップでThree.jsのテクスチャ画像を入れ替えるでファイルを読み込むと、FILEオブジェクトを取得できるのでFILE.typeでMIMEタイプがわかる。はじめはこれで判定しようとしたが、どうもこのMIMEタイプは拡張子で判別されているようで心もとない。
読み込んだ画像ファイルをFileReader オブジェクトでデータURI形式として読み込む処理はすでに作成済みで、データURI形式で読み込むと画像ファイルはBase64方式になる。そこで、読み込んだファイルの先頭部分のBase64方式データを比較して画像の種類を判定することにした。
Base64は、バイナリデータを64種類の英数字のみでテキストデータに変換する方式で、3バイトのデータが4文字に変換される。Base63についてはBase64についてを参照。
pngの場合、先頭8バイトは固定の16進数89 50 4E 47 0D 0A 1A 0Aになる。先頭の3バイトをBase64に変換するとiVBOという文字列になるので、Base64方式のデータの先頭4文字を読み込んでiVBOと一致したらpngと判定するような処理をすることで、FILEオブジェクトのMIMEタイプを参照するよりは正確な判定ができる。
実際にpng画像を読み込んだときのデータURI形式の中身を見ると以下のようになっている。iVBO以降が画像データ。カンマ以降を画像データか判定すればよさそう。
data:image/png;base64,iVBORw0KGgoAAAA...
ドラッグ&ドロップでThree.jsのテクスチャ画像を入れ替えるでpng画像しかテクスチャ画像として使えないようにして、png以外のファイルがドロップされたときにアラートメッセージを表示するには、以下のようにtextureSwitchを書き換える。
function textureSwitch( event ){ // 要素内イベントのキャンセル event.preventDefault(); // 1つ目のファイルのみ読み込む var file = event.dataTransfer.files[0]; // FileReader オブジェクトの作成 var reader = new FileReader(); reader.onload = function( event ) { // ファイルデータの先頭位置を取得 var startImg = 1 + event.target.result.indexOf( ',' ); // 先頭4文字分を取得 var buffer = event.target.result.slice( startImg, startImg+4); // pngの先頭部分と一致するか判定 if( buffer.indexOf( 'iVBO' ) == -1) { alert( 'Invalid file' ); } else { // 「img」でエレメントオブジェクト作成 var img = document.createElement( 'img' ); img.src = event.target.result; // テクスチャの更新 cube.material.map = new THREE.Texture( img ); cube.material.map.needsUpdate = true; } }; // データURLとしてファイルを読み込む reader.readAsDataURL( file ); }
0 件のコメント:
コメントを投稿