Javascriptで画像圧縮してみる

この記事は、[リンクバルアドベントカレンダー2022](https://qiita.com/advent-calendar/2022/linkbal)の11日目の記事です。

## はじめに

Webサイトで画像をアップロードする場合が多いと思います。
もし容量が大きければ大きいほどアップロード時間もかかって、サーバーへの負荷が増加してしまいます。
それでサーバー側で画像の圧縮処理を行なって画像サイズを小さくしていることが多いですが、Web側で画像をサーバーにアップロード前に画像圧縮を行う場合もあります。
今回の記事ではWeb側で画像圧縮を単純で行なってみたいと思います。
[Browser Image Compression](https://github.com/Donaldcwl/browser-image-compression)を使います。
## Browser Image Compression
`Browser Image Compression`とはWebページで画像の圧縮を行うことができるようにする`JavaScript`モジュールです。
`Browser Image Compression`を読み込む方法は2つあります。
#### npmやyanで読み込む</h6>

```
npm install browser-image-compression --save
# or
yarn add browser-image-compression
```

```js
import imageCompression from 'browser-image-compression';
```

#### CDNで読み込む

```html
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.0/dist/browser-image-compression.js"></script>
```

この記事では`CDN`で読み込む方法を利用して、画像を圧縮してみましょう。

## 実装

まずは画像をアップロード用のために`HTML`ファイルを作りました。

```index.html
<!DOCTYPE html>
<html>
  <head>
    <title>画像圧縮</title>
    <meta charset="utf-8">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.0/dist/browser-image-compression.js"></script>
  </head>
  <body>
    <div class="content">
      <h2>画像圧縮してみる</h2>
      <input type="file" accept="image/*" onchange="handleImageUpload(event);">
      <div id="original-size"></div>
      <div id="compressed-size"></div>
      <p id="compressed-image"></p>
    </div>
    <script src="compress-image.js"></script>
  </body>
</html>
```
`HTML`ファイルには`input`タグと画像圧縮前後の表示する情報の`div`タグと圧縮した画像の表示するところを設置しておきます。
`CDN`で`Browser Image Compression`を読み込むことにするので`head`タグで`script`タグを追加するのが必要です。それに、`input`の`onchange`イベントをハンドルしたいので、カスタム`script`ファイル(`compress-image.js`)も`body`タグに追加しました。

```compress-image.js
const originalSize = document.getElementById('original-size');
const compressedSize = document.getElementById('compressed-size');
const compressedImage = document.getElementById('compressed-image');

function handleImageUpload(event) {
  const imageFile = event.target.files[0];

  // reset content
  originalSize.textContent = '';
  compressedSize.textContent = '';
  compressedImage.innerHTML = '';

  const options = {
    maxSizeMB: 1,
    maxWidthOrHeight: 1920
  }

  imageCompression(imageFile, options)
    .then(function (compressedFile) {
      const img = URL.createObjectURL(compressedFile);
      originalSize.textContent = `元画像のサイズ: ${(imageFile.size / 1024 / 1024).toFixed(2)} MB`;
      compressedSize.textContent = `圧縮した画像のサイズ: ${(compressedFile.size / 1024 / 1024).toFixed(2)} MB`;
      compressedImage.innerHTML += `
          <a href="${img}" target="_blank">
            <img src="${img}" width="400" alt="">
          </a>`
    })
    .catch(function (error) {
      console.log(error.message);
    });
}
```
画像を選択した後、`handleImageUpload`メソッドが呼ばれます。ここで、画像圧縮処理を入れます。
画像圧縮する前に、`options`に最大サイズを1Mにして最大縦横を1920pxにしすのを設定しています。他のオプションもあるので[browser-image-compressionの仕様](https://github.com/Donaldcwl/browser-image-compression#main-function)を参考可能です。
`options`を設定したら、画像圧縮初めのために`imageCompression`を実行して、圧縮したファイルは`compressedFile`引数に返されます。返した情報でフロント側で画像圧縮前後の情報と圧縮した画像を表示させるようにします。(以下の画像みたいです)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548029/1960851d-99ef-3e05-c87d-230fb2ba1c40.png)

## 終わりに

画像圧縮の実装について単純で紹介しました。
いかがでしょうか。
Web開発にはある程度役立っていただければぜひ参考にして使ってみてください。

## 参考

[https://github.com/Donaldcwl/browser-image-compression](https://github.com/Donaldcwl/browser-image-compression)