B3S
menu close

Javascript

JavaScriptで画像リサイズする


えだ

更新日:2021/10/27


えだです。

前々から画像をアップロードするシステムの悩みで、1ファイルあたりのサイズが大きすぎる問題がありました。

総量問題だけで言うとアップ後にサーバー側処理でリサイズする方法でもいいのですが、環境(※1)や負荷を考えるとアップ前に縮小しておくべきです。

で、アップ前ということはクライアント側だけで完結する必要があります。

<div>
  <canvas id="canvas" ></canvas>
  <input id="uploadFile" name="image" type="file" />
  <input type="hidden" id="base64">
</div>

<script>
$("#uploadFile").change(function() {
  const maxwidth = 200;

  const file = this.files[0];
  if (!file.type.match(/^image\/(png|jpeg|gif)$/)) return;
  const image = new Image();
  const reader = new FileReader();
  reader.onload = function(evt) {
    image.onload = function() {
      const width = maxwidth;
      const height = image.height * (maxwidth / image.width);
      const canvas = $("#canvas");
      canvas.attr("width",width);
      canvas.attr("height",height);
      const ctx = canvas[0].getContext('2d');
      ctx.drawImage(image,0,0,width,height);

      const base64 = canvas[0].toDataURL("image/png");
      $("#base64").val(base64);
    }
    image.src = evt.target.result;
  }
  reader.readAsDataURL(file);
});
</script>

【解説】

canvasをサイズ指定で生成してそこに画像を描画させ、それを送信する算段です。

サンプルでは変更後の横幅をmaxwidthを固定で指定して、それに合わせて縦幅を縮小しています。

リサイズ画像をtoDataURL()でBase64に変換して文字列化し、それをpostするようにします。

$img = base64_decode($post->base64);
$filename = 'sample.jpg';
file_put_contents($filename, $img);

【解説】

サーバ側ではpostデータをbase64_decode()で戻します。

 

【おわりに】

JavaScriptオンリーだと面倒かなと思って敬遠してました。
他メンバーから困りごとの解決策を聞かれた時にこの理論で出来るよと答えたのですが、空論を伝えるだけなのも寂しいので実装してみました。

※1:PHPだとupload_max_filesizeで制限してて、よく見るレンタルサーバのデフォルトで2MBです