この記事では『Canvasを使って画像をリサイズする方法』について、以下の内容をサンプルコードを用いてわかりやすく解説します。
- フロントエンドで画像リサイズを行う理由
- Canvasとは
- Canvasを使って画像をリサイズする方法
- ファイル選択ダイアログで選択した画像をCanvasでリサイズする方法
- リサイズした画像をダウンロードする方法
フロントエンドで画像リサイズを行う理由
スマートフォンやデジタルカメラの高解像度化に伴い、画像サイズが数MBに達することも多く、サーバーにアップロードする際の負荷が大きくなります。また、アップロードに時間がかかる可能性があります。
そこで、フロントエンド側で画像をリサイズすることで、以下のようなメリットが得られます。
- レスポンスの高速化- 大きな画像はアップロードと表示に時間がかかりますが、リサイズしてから送信することで、レスポンスが速くなります。
 
- サーバー負荷の軽減- クライアント側で画像をリサイズすることで、サーバー側での処理を軽減できます。
 
- ユーザー体験の向上- アップロード時間が短縮され、ユーザーに快適な操作感を提供します。
 
この記事では、JavaScriptのCanvasを使って画像をリサイズする方法を説明します。
Canvasとは
まず、Canvasについて説明します。CanvasはWeb APIの一つで、JavaScriptを使って画像やグラフィックを動的に描画・操作するために使われています。
<canvas>要素自体は「空の描画領域」なのでそのままでは何も表示されませんが、JavaScriptを使用してCanvas APIを操作することで、画像を描画したり、編集したりすることができるようになります。
なお、<canvas>要素に描画する際には、2Dグラフィック用の「2Dコンテキスト」や3Dグラフィック用の「WebGLコンテキスト」を用いる必要があります。
この記事では、画像のリサイズに2Dコンテキスト(getContext('2d'))を用いています。
キャンバス API (Canvas API) は JavaScript と HTML の <canvas> 要素によってグラフィックを描く方法を提供します。他にも、アニメーション、ゲームのグラフィック、データの可視化、写真加工、リアルタイム動画処理などに使用することができます。
https://developer.mozilla.org/ja/docs/Web/API/Canvas_API
Canvasを使って画像をリサイズする方法
Canvasを使って、画像をリサイズしているシンプルなサンプルコードを示しています。以下のサンプルコードでは、同じディレクトリ内にある画像ファイル(sample.jpg)をリサイズして表示しています。
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>画像リサイズ</title>
  </head>
  <body>
    <h3>元画像</h3>
    <!-- 同じディレクトリにある画像を表示 -->
    <img id="original-img" src="sample.jpg" alt="元画像" />
    <h3>リサイズした画像</h3>
    <img id="resized-img" src="" alt="リサイズした画像" />
    <script>
      // 「元画像を表示している<img>要素」と「リサイズした画像を表示する<img>要素」を取得
      const originalImg = document.getElementById('original-img');
      const resizedImg = document.getElementById('resized-img');
      // 元画像が読み込まれると実行される
      originalImg.onload = function () {
        // リサイズする幅を300pxに指定し、高さはアスペクト比を維持して調整
        const newWidth = 300;
        const aspectRatio = originalImg.height / originalImg.width;
        const newHeight = newWidth * aspectRatio;
        // Canvasの作成と描画
        const canvas = document.createElement('canvas'); // 新しい<canvas>要素を作成し、リサイズ用の描画エリアを設定
        canvas.width = newWidth;
        canvas.height = newHeight;
        const ctx = canvas.getContext('2d'); // Canvas に描画するために必要な CanvasRenderingContext2D を取得
        ctx.drawImage(originalImg, 0, 0, newWidth, newHeight); // Canvasを使って指定した幅と高さでリサイズして画像を描画
        // リサイズした画像を表示
        const resizedImgDataUrl = canvas.toDataURL('image/jpeg'); // リサイズした画像をData URL形式で返す
        resizedImg.src = resizedImgDataUrl;
      };
    </script>
  </body>
</html>上記のサンプルコードについて説明します。
HTML
<h3>元画像</h3>
<!-- 同じディレクトリにある画像を表示 -->
<img id="original-img" src="sample.jpg" alt="元画像" />
<h3>リサイズした画像</h3>
<img id="resized-img" src="" alt="リサイズした画像" />original-imgは元画像を表示するための<img>タグに設定している属性です。画像は同じディレクトリのsample.jpgを使用します。
resized-imgはリサイズした画像を表示するための<img>タグに設定している属性です。リサイズした画像をここに表示します。
JavaScript
HTML要素の取得
// 「元画像を表示している<img>要素」と「リサイズした画像を表示する<img>要素」を取得
const originalImg = document.getElementById('original-img');
const resizedImg = document.getElementById('resized-img');「元画像を表示している<img>要素」と「リサイズした画像を表示する<img>要素」を取得しています。
元画像の読み込み
originalImg.onload = function () {
...
}元画像を表示している要素(originalImg)の読み込みが完了すると、onloadイベントが発火します。
リサイズする幅と高さの指定
// リサイズする幅を300pxに指定し、高さはアスペクト比を維持して調整
const newWidth = 300;
const aspectRatio = originalImg.height / originalImg.width;
const newHeight = newWidth * aspectRatio;リサイズする幅と高さを指定しています。高さはアスペクト比を維持して調整しています。
Canvasの作成と描画
// Canvasの作成と描画
const canvas = document.createElement('canvas'); // 新しい<canvas>要素を作成し、リサイズ用の描画エリアを設定
canvas.width = newWidth;
canvas.height = newHeight;
const ctx = canvas.getContext('2d'); // Canvas に描画するために必要な CanvasRenderingContext2D を取得
ctx.drawImage(originalImg, 0, 0, newWidth, newHeight); // Canvasを使って指定した幅と高さでリサイズして画像を描画新しい<canvas>要素を作成し、リサイズ用の描画エリアを設定しています。また、リサイズした画像サイズに合わせて、Canvasのwidthとheightを設定しています。
getContext('2d')を使用してCanvasRenderingContext2Dを取得しています。これにより、2Dの描画操作が可能になります。
drawImageメソッドを使用して、元画像をCanvasに描画しています。引数に新しい幅と高さを指定することで、指定したサイズにリサイズしています。
リサイズした画像を表示
// リサイズした画像を表示
const resizedImgDataUrl = canvas.toDataURL('image/jpeg'); // リサイズした画像をData URL形式で返す
resizedImg.src = resizedImgDataUrl;canvas.toDataURL('image/jpeg')では、Canvasの内容をJPEG形式の「Data URL」に変換しています。このData URLは、画像を文字列の形式に変えたもので、Data URLをHTMLのsrc属性に使うことで画像を直接表示することができます。また、ダウンロードリンクにも使用することができます。このData URLをresizedImg.srcに設定することで、リサイズした画像がHTML上に表示されます。
ファイル選択ダイアログで選択した画像をCanvasでリサイズする方法
次に、ファイル選択ダイアログで選択した画像をCanvasを使ってリサイズしているサンプルコードを以下に示します。
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>画像リサイズ</title>
  </head>
  <body>
    <!-- 画像選択:<input type="file">でファイルを選択すると、fileup関数が発火します。 -->
    <input type="file" accept="image/jpeg,image/png,image/gif" onchange="fileup(this)" />
    <h3>選択された画像</h3>
    <img id="original-img" src="" alt="元画像" />
    <h3>リサイズした画像</h3>
    <img id="resized-img" src="" alt="リサイズした画像" />
    <script>
      // 「元画像を表示する<img>要素」と「リサイズした画像を表示する<img>要素」を取得
      const originalImg = document.getElementById('original-img');
      const resizedImg = document.getElementById('resized-img');
      // fileup関数内の処理
      function fileup(input) {
        // 選択された画像ファイルを読み込むためのFileReaderオブジェクトを作成
        const reader = new FileReader();
        reader.onload = function () {
          // 画像処理用のHTMLImageElementオブジェクトの作成
          const imgReader = new Image();
          imgReader.onload = function () {
            // 選択された画像を表示
            originalImg.src = reader.result;
            // 画像タイプ取得
            const imgType = imgReader.src.substring(5, imgReader.src.indexOf(';'));
            // リサイズする幅を300pxに指定し、高さはアスペクト比を維持して調整
            const newWidth = 300;
            const aspectRatio = imgReader.height / imgReader.width;
            const newHeight = newWidth * aspectRatio;
            // Canvasの作成と描画
            const canvas = document.createElement('canvas'); // 新しい<canvas>要素を作成し、リサイズ用の描画エリアを設定
            canvas.width = newWidth;
            canvas.height = newHeight;
            const ctx = canvas.getContext('2d'); // Canvas に描画するために必要な CanvasRenderingContext2D を取得
            ctx.drawImage(imgReader, 0, 0, newWidth, newHeight); // Canvasを使って指定した幅と高さでリサイズして画像を描画
            // リサイズした画像を表示
            const resizedImgDataUrl = canvas.toDataURL(imgType); // リサイズした画像をData URL形式で返す
            resizedImg.src = resizedImgDataUrl;
          };
          // 画像ソースを指定し、画像を読み込む
          imgReader.src = reader.result;
        };
        // 選択されたファイルをData URL形式で読み込む
        reader.readAsDataURL(input.files[0]);
      }
    </script>
  </body>
</html>上記のサンプルコードについて説明します。
HTML
<input type="file" accept="image/jpeg,image/png,image/gif" onchange="fileup(this)" /><input type="file">要素を使用します。この要素をクリックすると、ファイル選択ダイアログが開きます。onchangeでファイル選択後にfileupイベントが発火します。
JavaScript
選択されたファイルをData URL形式で読み込む
function fileup(input) {
  // 選択された画像ファイルを読み込むためのFileReaderオブジェクトを作成
  const reader = new FileReader();
  reader.onload = function () {
    ...
  };
  reader.readAsDataURL(input.files[0]);
}reader.readAsDataURL(input.files[0])によって、選択されたファイルをData URL形式で読み込んでいます。読み込みが完了すると、reader.onloadイベントが発火します。
読み込んだ画像をHTMLImageElementオブジェクトに変換
// 画像処理用のHTMLImageElementオブジェクトの作成
const imgReader = new Image();
imgReader.onload = () => {
 ...
};
// HTMLImageElementオブジェクトのsrcにFileReaderのresultプロパティを設定
imgReader.src = reader.result;imgReader.src = reader.resultで、HTMLImageElementオブジェクトのsrcプロパティにFileReaderオブジェクトのresultプロパティを設定しています。この処理では、HTMLImageElementオブジェクトにFileReaderで読み込んだ画像データを設定しています。設定後、imgReader.onloadイベントが発火します。
【補足】リファクタリング
各処理を分割すると以下のようになります。
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>画像リサイズ</title>
  </head>
  <body>
    <!-- 画像選択:<input type="file">でファイルを選択すると、fileup関数が発火します。 -->
    <input type="file" accept="image/jpeg,image/png,image/gif" onchange="fileup(this)" />
    <h3>選択された画像</h3>
    <img id="original-img" src="" alt="元画像" />
    <h3>リサイズした画像</h3>
    <img id="resized-img" src="" alt="リサイズした画像" />
    <script>
      // 「元画像を表示する<img>要素」と「リサイズした画像を表示する<img>要素」を取得
      const originalImg = document.getElementById('original-img');
      const resizedImg = document.getElementById('resized-img');
      // 画像ファイルをData URL形式で読み込み、Data URLを返す
      const readAsDataURL = function (imgFile) {
        return new Promise((resolve) => {
          // 選択された画像ファイルを読み込むためのFileReaderオブジェクトを作成
          const reader = new FileReader();
          reader.onload = function () {
            resolve(reader.result);
          };
          // 選択されたファイルをData URL形式で読み込む
          reader.readAsDataURL(imgFile);
        });
      };
      // 画像のURLを元にHTMLImageElementオブジェクトを作成し、読み込んだ画像を返す
      const loadImage = function (src) {
        return new Promise((resolve) => {
          // 画像処理用のHTMLImageElementオブジェクトの作成
          const imgReader = new Image();
          imgReader.onload = function () {
            resolve(imgReader);
          };
          // 画像ソースを指定し、画像を読み込む
          imgReader.src = src;
        });
      };
      // HTMLImageElementオブジェクトからリサイズした画像のData URLを生成して返す
      const resizeImgAndOutputDataUrl = function (img) {
        // MIMEタイプを取得
        const imgType = img.src.substring(5, img.src.indexOf(';'));
        // リサイズする幅を300pxに指定し、高さはアスペクト比を維持して調整
        const newWidth = 300;
        const aspectRatio = img.height / img.width;
        const newHeight = newWidth * aspectRatio;
        // Canvasの作成・Canvasへの描画:
        const canvas = document.createElement('canvas'); //Canvasの作成
        canvas.width = newWidth;
        canvas.height = newHeight;
        const ctx = canvas.getContext('2d'); // Canvas に描画するために必要な CanvasRenderingContext2D を取得
        ctx.drawImage(img, 0, 0, newWidth, newHeight); // Canvasを使って指定した幅と高さでリサイズして画像を描画
        return canvas.toDataURL(imgType); // リサイズした画像をData URL形式で返す
      };
      // fileup関数内の処理
      async function fileup(input) {
        // 選択された画像ファイルをData URL形式で取得
        const inputImgDataUrl = await readAsDataURL(input.files[0]);
        // 元画像を表示
        originalImg.src = inputImgDataUrl;
        // Data URLからHTMLImageElementオブジェクトを作成
        const inputImg = await loadImage(inputImgDataUrl);
        // HTMLImageElementオブジェクトをリサイズしてData URL形式で取得
        const resizedImgDataUrl = resizeImgAndOutputDataUrl(inputImg);
        // リサイズした画像を表示
        resizedImg.src = resizedImgDataUrl;
      }
    </script>
  </body>
</html>
リサイズした画像をダウンロードする方法
以下のサンプルコードでは、ファイル選択ダイアログで開いた画像をCanvasを使ってリサイズし、そのリサイズ画像をダウンロードできるようにしています。
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>画像リサイズ</title>
  </head>
  <body>
    <!-- 画像選択:<input type="file">でファイルを選択すると、fileup関数が発火します。 -->
    <input type="file" accept="image/jpeg,image/png,image/gif" onchange="fileup(this)" />
    <h3>選択された画像</h3>
    <img id="original-img" src="" alt="元画像" />
    <h3>リサイズした画像</h3>
    <img id="resized-img" src="" alt="リサイズした画像" />
    <p><a id="download" href="#" download="no-name.png">ダウンロード</a></p>
    <script>
      // 「元画像を表示する<img>要素」と「リサイズした画像を表示する<img>要素」を取得
      const originalImg = document.getElementById('original-img');
      const resizedImg = document.getElementById('resized-img');
      // fileup関数内の処理
      function fileup(input) {
        // 選択された画像ファイルを読み込むためのFileReaderオブジェクトを作成
        const reader = new FileReader();
        reader.onload = function () {
          // 画像処理用のHTMLImageElementオブジェクトの作成
          const imgReader = new Image();
          imgReader.onload = function () {
            // 選択された画像を表示
            originalImg.src = reader.result;
            // 画像タイプ取得
            const imgType = imgReader.src.substring(5, imgReader.src.indexOf(';'));
            // リサイズする幅を300pxに指定し、高さはアスペクト比を維持して調整
            const newWidth = 300;
            const aspectRatio = imgReader.height / imgReader.width;
            const newHeight = newWidth * aspectRatio;
            // Canvasの作成と描画
            const canvas = document.createElement('canvas'); // 新しい<canvas>要素を作成し、リサイズ用の描画エリアを設定
            canvas.width = newWidth;
            canvas.height = newHeight;
            const ctx = canvas.getContext('2d'); // Canvas に描画するために必要な CanvasRenderingContext2D を取得
            ctx.drawImage(imgReader, 0, 0, newWidth, newHeight); // Canvasを使って指定した幅と高さでリサイズして画像を描画
            // リサイズした画像を表示
            const resizedImgDataUrl = canvas.toDataURL(imgType); // リサイズした画像をData URL形式で返す
            resizedImg.src = resizedImgDataUrl;
            // ダウンロード設定:リサイズした画像をダウンロードできるようにします。
            const dl = document.getElementById('download');
            dl.href = resizedImgDataUrl;
            // 元のファイル名を取得
            const originalFile = input.files[0];
            const originalFileName = originalFile.name;
            // ダウンロードのファイル名を変更
            dl.download = `resized_${originalFileName}`;
          };
          // 画像ソースを指定し、画像を読み込む
          imgReader.src = reader.result;
        };
        // 選択されたファイルをData URL形式で読み込む
        reader.readAsDataURL(input.files[0]);
      }
    </script>
  </body>
</html>HTML
<a id="download" href="#" download="no-name.png">ダウンロード</a><a>タグはリンクとして機能しますが、download属性を設定することで、リンク先のファイルをダウンロードできるようにしています。この属性にはダウンロードファイルのファイル名も指定でき、ここでは初期設定として"no-name.png"としています。クリックするとリサイズした画像がダウンロードされます。
JavaScript
ダウンロード設定
// ダウンロード設定:リサイズした画像をダウンロードできるようにします。
const dl = document.getElementById('download');
dl.href = resizedImgDataUrl;
// 元のファイル名を取得
const originalFile = input.files[0];
const originalFileName = originalFile.name;
// ダウンロードのファイル名を変更
dl.download = `resized_${originalFileName}`;dl.href = resizedImgDataUrlでは、リサイズした画像のData URLをリンクのhref属性に設定しています。これにより、リンクをクリックしたときにリサイズ画像がダウンロードされるようになります。
また、selectedFileNameには、選択された元ファイルの名前が格納されているため、この名前に基づいてdownload属性をresized_${selectedFileName}に更新しています。これにより、ダウンロードしたファイルの名前は元のファイル名にresized_を加えた名前になります。
本記事のまとめ
この記事では『Canvasを使って画像をリサイズする方法』について、以下の内容を説明しました。
- フロントエンドで画像リサイズを行う理由- サーバー負荷の軽減、レスポンスの高速化、ユーザー体験の向上。
 
- Canvasとは- HTMLの<canvas>要素とJavaScriptのCanvas APIを使い、動的な画像描画や操作が可能。
 
- HTMLの
- Canvasを使って画像をリサイズする方法- JavaScriptで<canvas>要素を作成し、指定した幅と高さで画像を描画。
- drawImage()を用いてアスペクト比を保持したリサイズ。
 
- JavaScriptで
- ファイル選択ダイアログを利用した画像リサイズ- <input type="file">を利用し、選択画像をCanvasでリサイズ。
 
- リサイズした画像をダウンロードする方法- toDataURL()でData URLを取得し、リンクの- href属性に設定してダウンロード可能に。
 
- サンプルコードのリファクタリング- 各処理を関数化し、可読性を向上。
 
お読み頂きありがとうございました。