どんな感じになるのか
ここから、iPhoneで撮った写真を選択してみてください。
http://runstant.com/simiraaaa/projects/e9efe5c7
縦で撮った写真だと90度回転します。
回転しないようにするサンプル
使用したライブラリ
https://github.com/blueimp/JavaScript-Load-Image
このライブラリのv2.6.2をrawgit.comのcdn化サービスを使って下記のURLから読み込みます。
https://cdn.rawgit.com/blueimp/JavaScript-Load-Image/v2.6.2/js/load-image.all.min.js
サンプル
http://runstant.com/simiraaaa/projects/loadImageExifOrientation
ここから、iPhoneで撮った写真を選択してみてください。
回転せずに、表示されると思います。
コードの説明
HTML部分
<head>
タグ内でライブラリを読み込みます。
<!-- 省略 -->
<script src="https://cdn.rawgit.com/blueimp/JavaScript-Load-Image/v2.6.2/js/load-image.all.min.js"></script>
<!-- 省略 -->
<body>
タグ内は、ファイル選択用の<input type="file">
と、表示用の<div>
が書いてあります。
<div>
<label>iPhoneで縦向きに撮った写真を選択してください。
<input type="file" name="file" id="file" />
</label>
</div>
<div id="dst">
<p>画像クリックで別ウィンドウで開く</p>
</div>
CSS部分
あんまり関係ないですが、大きい画像がそのまま表示されると見えないので、widthを300pxになるようにしてます。
canvas {
width: 300px;
}
Script部分
コメントに細かく書いてあるので、ザックリ流れを説明します。
- まず、
window.onload
の中で処理をしています。 -
input[file]
のonchange
で画像ファイルが選択された時、3へ -
load
関数に画像が読み込み終わったら、div#dst
にcanvas
を追加する関数を渡します。 -
load
関数では、まず、回転してるか調べるためにloadImage.parseMetaData
を実行します。 - 回転に関する情報は、
exif
というデータの中に格納されているので、exif
がある場合だけ、回転させるオプションをセットします。 -
loadImage
関数を呼び出して、画像の読み込みが完了すると、3.のcanvas
を追加する関数が呼び出されます。
onload = function() {
var input = document.getElementById('file');
var dst = document.getElementById('dst');
input.onchange = function() {
// 選択中のファイルの一つ目
var file = this.files[0];
// ファイルを選択しなかった場合
if(!file) return;
// ファイル形式
console.log(file.type);
// ファイル形式の中にimageが含まれない場合
if(!/image/.test(file.type)) {
alert('画像を選択してください。');
return;
}
// 読み込み用の関数で読み込み完了時に、HTMLにcanvas追加
load(file, function(canvas) {
dst.appendChild(canvas);
// canvas がクリックされた時に、別ウィンドウで画像を開く
canvas.onclick = function() {
open(this.toDataURL('image/png'));
};
});
};
function load(file, callback) {
// canvas: true にすると canvas に画像を描画する(回転させる場合は必須オプション)
var options = {canvas: true};
loadImage.parseMetaData(file, function (data) {
if (data.exif) {
console.log("exifに格納されている情報:\n", data.exif.getAll());
// options の orientation は小文字。 exif.getの 'Orientation' は先頭大文字
// ここでcanvasの回転を指定している
options.orientation = data.exif.get('Orientation');
console.log('Orientation: ' + options.orientation);
}
// 画像の読み込み。完了時に callback が呼び出される
loadImage(file, callback, options);
});
}
};
canvasで出てきてるので、サーバに送るときは、FormData API
や、canvas.toDataURL()
などで、画像データを送ってやれば、回転してない画像が登録できると思います。(サーバ側での処理に合わせて、適切な方法で送信してください)
回転する原因
Script部分の説明でも出てきたexifに含まれる、Orientationという回転を表すデータが原因です。
exifについては、私も詳しくは理解できていませんが、jpeg画像の最初の方のバイト列に格納されているようです。
画像を表示できるアプリの多くは、このexifによって、表示の仕方が変わっていて、Orientationがあれば、自動的に指定された角度で回転して表示しているのではないかと思います。
ブラウザだとiPhoneの<img>
タグを除いては、基本的にOrientationによる回転は自動的にはされないので、そこを自分で実装する必要があるということだと思っています。
また、exifのOrientationに回転の指定があれば、iPhoneに限らず、デジカメなどで撮った写真でも発生する現象だと思います。
この辺りは曖昧なので、間違ってる部分があれば、指摘していただけるとありがたいです。