#概要
フォームで画像をアップロードする際,圧縮・EXIF-Orientationを見て回転したうえで,送信・プレビューしたい場合がある。
input-fileで画像を受け取り,圧縮したdataUrlに変換することを考える。
また画像は,今回はただ圧縮するのではなく,正方形になるようにcropしてる。(この辺は,canvasをいじればいろいろできる)
#依存
jquery https://github.com/jquery/jquery
exif-js https://github.com/exif-js/exif-js
#要点
1.formObjectをBlobURLに変換
2.BlobURLをimageObjectに変換
3.imageObjectを圧縮して回転してcropしてdataUrlにて出力(canvas利用)
#ソース
sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<script type="text/javascript" src="jquery-1.12.3.min.js"></script>
<script type="text/javascript" src="exif.js"></script>
<script type="text/javascript">
(function($) {
$.fileImageViewer = function() {
// base64dataURLから圧縮したbase64dataURLを生成
function resizeImage(src, size, callback) {
var img = new Image();
img.onload = function() {
EXIF.getData(img, function() {
var dst = _resize(img, size)
callback(dst);
img = null; // for leak
});
};
img.src = src;
return;
}
// imageObjectから圧縮したbase64dataURLを生成
function _resize(img, compressSize) {
var exif = img.exifdata.Orientation
var raw_width = img.width;
var raw_height = img.height;
var canvas = document.createElement('canvas');
canvas.width = compressSize;
canvas.height = compressSize;
var ctx = canvas.getContext('2d');
ctx.translate(canvas.width / 2, canvas.height / 2);
switch (exif) {
case 1:
break;
case 2: // vertical flip
ctx.scale(-1, 1);
break;
case 3: // 180 rotate left
ctx.rotate(Math.PI);
break;
case 4: // horizontal flip
ctx.scale(1, -1);
break;
case 5: // vertical flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.scale(1, -1);
break;
case 6: // 90 rotate right
ctx.rotate(0.5 * Math.PI);
break;
case 7: // horizontal flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.scale(-1, 1);
break;
case 8: // 90 rotate left
ctx.rotate(-0.5 * Math.PI);
break;
default:
break;
}
var dx = -canvas.width / 2;
var dy = -canvas.height / 2;
var dw = canvas.width;
var dh = canvas.height;
var sx = Math.max((raw_width - raw_height) / 2, 0);
var sy = Math.max((raw_height - raw_width) / 2, 0);
var sw = Math.min(raw_height, raw_width);
var sh = Math.min(raw_height, raw_width);
ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
var url = canvas.toDataURL('image/jpeg');
ctx = null;
canvas = null;
return url;
}
return {
resizeImage : resizeImage
}
};
})(jQuery);
</script>
<script type="text/javascript">
$(function() {
var $viewer = $('#picture');
var $file = $('#file');
$file.change(function(){
var file = $file[0].files[0];
if(!file) return;
var src = window.URL.createObjectURL(file); // blob file
$.fileImageViewer().resizeImage(src, 100, function(dst){
$viewer.attr("src", dst);
});
});
});
</script>
</head>
<body>
<img src="" id="picture">
<input type="file" accept="image/*" id="file">
</body>
</html>
#改善点
・formObject->BlobURL->imageObject->dataURLと変換を何度も挟んで非効率ではないか?
・スマホでやるとメモリ不足で落ちる時がある。なにか対処法はないか?
ご指摘あればぜひ宜しくお願いします。