アスペクト比(縦横比)を維持して画像を縮小・拡大する
画像を「縮小」または「拡大」する際にアスペクト比(縦横比)を維持しないと画像が潰れてしまいます。今回はアスペクト比を維持しながら、画像を縮小、拡大する方法をご紹介します。サンプルコードはJavaScriptですが、他の言語でも流用できます。
[元のイメージ]
[アスペクト比を維持しないリサイズ]
[アスペクト比を維持したリサイズ]
サンプルの実行例
操作方法は最初に画像を読み込んで、「幅」または「高さ」を適当に入力すると、もう片方にアスペクト比を維持したサイズが自動入力されます。
実行ボタンを押すと「幅」「高さ」のサイズで画像がリサイズされます。
※上記は実行例の画像となっております。
サンプルコード
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
// キャンバス
var src_canvas;
var src_ctx;
var dst_canvas;
var dst_ctx;
// イメージ
var image;
window.onload = function(){
src_canvas = document.getElementById("SrcCanvas");
src_ctx = src_canvas.getContext("2d");
dst_canvas = document.getElementById("DstCanvas");
dst_ctx = dst_canvas.getContext("2d");
image = document.getElementById("img_source");
}
function run(){
// エラーチェック
// ※明示的にブラウザのValidation機能(HTML5)を発動させています。
if (!document.getElementById("num_width").checkValidity()){
return true;
}
if (!document.getElementById("num_height").checkValidity()){
return true;
}
// リサイズ後のサイズ
var width = parseInt(document.getElementById("num_width").value,10);
var height = parseInt(document.getElementById("num_height").value,10);
// エラーチェック
if (width < 1){
alert('この設定では画像の幅が0ピクセルになる為、実行できません。');
return false;
}
if (height< 1){
alert('この設定では画像の高さが0ピクセルになる為、実行できません。');
return false;
}
dst_canvas.width = width;
dst_canvas.height = height;
// 低品質(ブラウザの機能でリサイズ)
dst_ctx.drawImage(image,0,0,dst_canvas.width,dst_canvas.height);
document.getElementById("msg_destination").innerHTML =
'[リサイズ後] ' + dst_canvas.width + ' x ' + dst_canvas.height;
return false;
}
function setAspectRatio(option) {
// 幅が入力された
if (option == 1){
if (!document.getElementById("num_width").checkValidity()) return;
// 幅を基準にアスペクト比を調整する
var size = parseInt(document.getElementById("num_width").value,10);
var aspectratio = image.width / size;
var another = Math.round(image.height / aspectratio);
document.getElementById("num_height").value = another;
// 高さが入力された
}else if (option == 2){
if (!document.getElementById("num_height").checkValidity()) return;
// 高さを基準にアスペクト比を調整する
var size = parseInt(document.getElementById("num_height").value,10);
var aspectratio = image.height / size;
var another = Math.round(image.width / aspectratio);
document.getElementById("num_width").value = another;
}
}
// ユーザーによりファイルが追加された
function onAddFile(event) {
var files;
var reader = new FileReader();
if(event.target.files){
files = event.target.files;
}else{
files = event.dataTransfer.files;
}
// ファイルが読み込まれた
reader.onload = function (event) {
// イメージが読み込まれた
image.onload = function (){
document.getElementById("num_width").value = src_canvas.width = image.width;
document.getElementById("num_height").value = src_canvas.height = image.height;
// キャンバスに画像を描画
src_ctx.drawImage(image,0,0);
document.getElementById("msg_source").innerHTML =
'[元の画像] ' + image.width + ' x ' + image.height;
};
// イメージが読み込めない
image.onerror = function (){
alert('このファイルは読み込めません。');
};
image.src = reader.result;
};
if (files[0]){
reader.readAsDataURL(files[0]);
}
document.getElementById("inputfile").value = '';
}
</script>
</head>
<body>
<h4>画像の読み込み</h4>
<p></p>
<form>
<input type="file" id="inputfile" accept="image/jpeg,image/png,image/gif" onchange="onAddFile(event);">
<p></p>
<table>
<tr>
<td>幅</td><td><input type="number" id="num_width" style="width:80px;text-align:right;" min="1" max="10000" required onkeyup="setAspectRatio(1);"> px</td>
</tr>
<tr>
<td>高さ</td><td><input type="number" id="num_height" style="width:80px;text-align:right;" min="1" max="10000" required onkeyup="setAspectRatio(2);"> px</td>
</tr>
</table>
<p></p>
<input type="submit" onclick="return run();" value="実行">
</form>
<p></p>
<h3 id="msg_destination">[変換後]</h3>
<p></p>
<canvas id="DstCanvas"></canvas>
<p></p>
<h3 id="msg_source">[元の画像]</h3>
<p></p>
<img id="img_source" style="display:none;">
<canvas id="SrcCanvas"></canvas>
<p></p>
</body>
</html>
特に解説は要らないと思いますが、setAspectRatio()でアスクペクト比を算出しています。また、リサイズはブラウザの機能でリサイズしていますので、低品質です。高品質のリサンプリングを使用したリサイズは「画像の縮小」や「画像の拡大」で試せます。
高品質バイキュービック法(双三次補間)のリサンプリングによるリサイズのコードは現在は再利用、再配布不可ですが、将来的には画像エフェクトライブラリの一部としてオープンソースで公開するかも知れません。
スポンサーリンク
関連記事
公開日:2016年05月18日
記事NO:01962
プチモンテ ※この記事を書いた人
![]() | |
![]() | 💻 ITスキル・経験 サーバー構築からWebアプリケーション開発。IoTをはじめとする電子工作、ロボット、人工知能やスマホ/OSアプリまで分野問わず経験。 画像処理/音声処理/アニメーション、3Dゲーム、会計ソフト、PDF作成/編集、逆アセンブラ、EXE/DLLファイルの書き換えなどのアプリを公開。詳しくは自己紹介へ |
| 🎵 音楽制作 BGMは楽器(音源)さえあれば、何でも制作可能。歌モノは主にロック、バラード、ポップスを制作。歌詞は抒情詩、抒情的な楽曲が多い。楽曲制作は🔰2023年12月中旬 ~ | |









