画像ファイルをリサイズする
最近のスマートフォンで撮影した写真は解像度が高くそのまま送信してしまうとサーバー側の負荷が高くなってしまったり、通信時間がかかってタイムアウトになってしまう問題が発生してしまいます。
その為、クライアント側(javascript側)で画像をリサイズして解像度を小さくしてからサーバー側へ送信する処理は、Webアプリケーションにおいて(特にフロントエンドにおいて)は必須な対応であると考えます。
以下は、読み込んだ画像の縦または横のピクセルが指定したサイズよりも大きい場合は、アスペクト比を維持したまま指定したサイズにリサイズをすることでサーバーへ送信するファイルサイズを小さくしています。
サイズを小さくして解像度を下げすぎると表示される画像の見た目が荒くなりますが、サイズが大きいと画面を表示する際に読み込みが遅くなってしまいます。
画像の見た目が気にならない程度の解像度にサイズをリサイズすることがポイントです。
var image = new Image();
var fr=new FileReader();
fr.onload=function(evt) {
// リサイズする
image.onload = function() {
var width, height;
if(image.width > image.height){
// 横長の画像は横のサイズを指定値にあわせる
var ratio = image.height/image.width;
width = thumbnail_width;
height = thumbnail_width * ratio;
} else {
// 縦長の画像は縦のサイズを指定値にあわせる
var ratio = image.width/image.height;
width = thumbnail_height * ratio;
height = thumbnail_height;
}
// サムネ描画用canvasのサイズを上で算出した値に変更
var canvas = $('<canvas id="canvas" width="0" height="0" ></canvas>')
.attr('width', width)
.attr('height', height);
var ctx = canvas[0].getContext('2d');
// canvasに既に描画されている画像をクリア
ctx.clearRect(0,0,width,height);
// canvasにサムネイルを描画
ctx.drawImage(image,0,0,image.width,image.height,0,0,width,height);
// canvasからbase64画像データを取得
var base64 = canvas.get(0).toDataURL('image/jpeg');
// base64からBlobデータを作成
var barr, bin, i, len;
bin = atob(base64.split('base64,')[1]);
len = bin.length;
barr = new Uint8Array(len);
i = 0;
while (i < len) {
barr[i] = bin.charCodeAt(i);
i++;
}
var resizeBlob = new Blob([barr], {type: 'image/jpeg'});
callback({
fileName: blob.name,
ofileData: evt.target.result,
fileData: base64,
ofileSize: blob.size,
fileSize: resizeBlob.size,
fileType: resizeBlob.type
})
}
image.src = evt.target.result;
}
fr.readAsDataURL(blob);
HEIC形式の画像を変換する
また、iPhone11以降で撮影した写真はHEICというブラウザで表示できない形式の画像ファイルで保存されます。
その為、HEIC形式の画像ファイルの場合はJPEGなどブラウザで表示できる形式に変換する必要があります。
heic2any というライブラリを利用することで、JPEGなどブラウザで表示可能な形式に変換することが可能です。
heic2any({
blob: file,
toType: "image/jpeg",
quality: 1
}).then(function(resultBlob) {
var errors = validate(resultBlob);
if (0 < errors.length) {
errorCallback(errors);
nowLoading = false;
return;
}
resize(resultBlob, function(res) {
res.fileName = file.name;
successCallback(res);
nowLoading = false;
}, function(errors) {
errorCallback(errors);
nowLoading = false;
return;
});
});
デモ
画像ファイルを選択すると元の画像とリサイズ後の画像が一覧に表示されます。元の画像に比べて、リサイズ後の方がサイズが小さくなっている事が判ると思います。
こちらにデモページを用意しているのでご利用ください。
ソースコード
ソースコードはGitHubにて公開しております。