みかづきブログ その3

3ヶ月つづけてみました。

モダンブラウザでバイナリを解析して画像の形式を識別する

FileReader の readAsArrayBuffer を引数にとって DataView のインスタンスをつくると、バイナリデータを解析するためのインスタンスをつくれることを知りました。
JPG、PNG、GIFはバイナリデータの先頭の文字列が決まっているようなので、アップされたファイルの形式を判定するコードを書いてみました。


JavaScript

(function(win, doc) {

  var HEAD    = {
        JPG    : [0xFF, 0xD8, 0xFF],
        PNG    : [0x89, 0x50, 0x4E, 0x47],
        GIF87a : [0x47, 49, 46, 38, 37, 61],
        GIF89a : [0x47, 49, 46, 38, 39, 61],
      };

  file.addEventListener("change", _handleFileChange, false);  
    
  function _handleFileChange(evt) {
    var reader = new FileReader(),
        data   = file.files[0];

    reader.onload = _handleReaderLoad;
    reader.readAsArrayBuffer(data);
  }

  function _handleReaderLoad(evt) {
    var dataView = new DataView(evt.target.result),
        img      = new Image(),
        keys     = Object.keys(HEAD),
        flags    = {};

    for (var i = 0, keysLength = keys.length; i < keysLength; ++i) {
        flags[keys[i]] = false;
        for (var j = 0, keyLength = keys[i].length; j < keyLength; ++j) {
            if (dataView.getUint8(j) === HEAD[keys[i]][j]) {
                if (!j) {
                    flags[keys[i]] = true;
                } else {
                    flags[keys[i]] = flags[keys[i]] && true;
                }
            } else {
                flags[keys[i]] = false;
                continue;
            }
        }
        if (flags[keys[i]]) {
            alert([keys[i]]);
            return;
        }
    }
  }

})(this, document);

DEMO