JavascriptでJPEG画像からEXIFのOrientation情報のみを取得する
2015-08-10
Javascriptを使ってクライアントサイドで画像を縮小する場合に必要となるOrientation情報を、最小のコードと処理でJPEG画像から取得する関数を作りました。
クライアントサイドで画像を縮小してプレビューし、アップロードすることで通信帯域やサーバの負荷を抑えるJavascriptは比較的簡単に作れます。しかしiPhoneで試してみるとなんか変な状態になってしまいました。調べてみるとiOS6でメガピクセル画像をCanvasに描画するとおかしくなってしまう件と、その対処というページを見つけて、iPhone側に問題がありそうで、解決策も提示されているようです。
そこで必要となるのが、画像の正しい方向(回転とか鏡像とか)なのですが、JPEG内のEXIF情報に書き込まれているっぽいです。EXIF情報を取得するためのJavascriptコードもいろいろあるのですが、EXIF全体を読むため汎用的に作られていて、コードが大きくて処理も冗長な感じです。必要なのはOrientationのみなので、それに特化した関数を作ってみました。
EXIFのOrientationのみを取得するJavascript関数
function getOrientation(imgDataURL){
var byteString = atob(imgDataURL.split(',')[1]);
var orientaion = byteStringToOrientation(byteString);
return orientaion;
function byteStringToOrientation(img){
var head = 0;
var orientation;
while (1){
if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 218) {break;}
if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 216) {
head += 2;
}
else {
var length = img.charCodeAt(head + 2) * 256 + img.charCodeAt(head + 3);
var endPoint = head + length + 2;
if (img.charCodeAt(head) == 255 & img.charCodeAt(head + 1) == 225) {
var segment = img.slice(head, endPoint);
var bigEndian = segment.charCodeAt(10) == 77;
var count;
if (bigEndian) {
count = segment.charCodeAt(18) * 256 + segment.charCodeAt(19);
} else {
count = segment.charCodeAt(18) + segment.charCodeAt(19) * 256;
}
for (i=0; i < count; i++){
var field = segment.slice(20 + 12 * i, 32 + 12 * i);
if ((bigEndian && field.charCodeAt(1) == 18) || (!bigEndian && field.charCodeAt(0) == 18)) {
orientation = bigEndian ? field.charCodeAt(9) : field.charCodeAt(8);
}
}
break;
}
head = endPoint;
}
if (head > img.length){break;}
}
return orientation;
}
}
この関数の入力値は、JPEGファイルをbase64エンコードしたDataURL形式にしています。これはHTML5のFileReaderでローカルファイルを読み出すときに一番使いやすい形式です。