non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

非アプリでiPhoneのカメラロールの写真を扱う

先週末、息子の通っている保育園で餅つき大会にいって、なれない餅つきをしてきたkjunichiです。

 

背景

iOS6になりinputタグのtype=fileの指定が可能になった。
これにより、iPhoneから写真のアップロードが非ネイティブアプリで
可能になった。

しかし、サーバーにファイルをアップロードする分には問題ないのだが、
とはいえ、カメラロールの写真のサイズはそれなりにデカい。
クライアントサイドで扱えないか?
となるわけですが、カメラロールの写真のサイズはMobile Safariで
扱える画像サイズを遥かに超えており、困った。

何とかしてみた

サーバーにアップロードできるんだから、
内部的には、あるていど画像データを扱えているのだろう?
何か方法は無いものかと途方に暮れいた2012年。。

ローカルファイルをバイナリーデータとして読み込めることを知る

先日、File APIでDataURLとして読み込まず、素のバイナリーに近い
形で扱える。FileReader#readAsBinaryStringなるメソッドを
Google DriveAPIJavaScriptで叩こうとしていた際に知った。


さらに調べると、バイナリ配列として扱える
FileReader#readAsArrayBuffer
があった!

JPEGデコーダはやっぱりあるし。

今回はjpgjsを使用。
撮影時の回転情報を反映してくれないが、それはおいおい。

これらをまとめると

var item = document.getElementById('picInput').files[0];
var reader = new FileReader();
reader.onload = function (e) {
    var j = new JpegImage();
    var buffer = new Uint8Array(reader.result);
    j.parse(buffer);

    var c = document.getElementById("filterdImage");
    // 算数苦手なので、10分の1にとりあえず指定して、画像サイズを小さくする。
    c.width = j.width / 10;
    c.height = j.height / 10;
    var ctx = c.getContext("2d");
    var d = ctx.getImageData(0, 0, j.width / 10, j.height / 10);
    j.copyToImageData(d);
    ctx.putImageData(d, 0, 0);
};
reader.readAsArrayBuffer(item);

Jsdo.itのサンプル

iOS6で扱える画像サイズの制約をかわせるかの実験

分かった事

プライバシーに敏感な昨今の事、このやり方だと、写真のGPS情報は取得出来ないようです。

関連記事