行動すれば次の現実

ほどよくモダンなシステム開発を目指しています。メインテーマは生産性、Ruby、Javascriptです。

Javascriptによる画像リサイズ処理の実装例(blueimp-load-imageなど)

画像アップロード処理をする際、昨今ではフロントサイドでもリサイズするのが主流である。

詳しくはこちらの記事を参照( 画像アップロード時はクライアントサイドでも圧縮処理をすべき理由 - SaaS開発者のあれこれ

Javascriptcanvas APIを使って実装するのが一般的なのだが、canvasで画像圧縮処理を一から実装とそれなりのコーディング量が必要である。

画像圧縮に関するJavascriptライブラリは山程あるので、一から実装するのは車輪の再開発感が否めない。

そのため、今回は既存のJavascriptライブラリを使用した実装例を記そうと思う。

blueimp-load-imageを使った実装例

blueimp-load-imageというnpmライブラリを使用して画像圧縮処理を実装する。

github.com

blueimp-load-imageは画像を加工したり、回転情報などを考慮してプレビュー画像を作成したりが簡単に実装できるライブラリである。

以下実装例

import * as loadImage from 'blueimp-load-image';

const resizeImageWorker = (imageFile, options = {
  maxHeight: 828,
  maxWidth: 1104,
  canvas: true,
  orientation: true,
}) => {
  return new Promise((resolve) => {
    loadImage(imageFile, (canvas) => {
      const type = 'image/jpeg';
      const dataUri = canvas.toDataURL(type);
      const bin = atob(dataUri.split(',')[1]);
      const buffer = new Uint8Array(bin.length);
      for (let i = 0; i < bin.length; i++) {
        buffer[i] = bin.charCodeAt(i);
      }
      resolve(new Blob([buffer.buffer], { type: type }))
    }, options);
  });
}

function createProductImages(payload) {
  const { productRecipeId, productImage } = payload;
  return resizeImageWorker(productImage).then((blob) => {
    const params = new FormData();
    params.append('product_image', blob);
    return axios.post(`/api/product_recipes/${productRecipeId}/product_images`,
      params, {
        headers: {
          'content-type': 'multipart/form-data',
        },
      });
  })
}

function* postProductImages(action) {
  const response = yield call(createProductImages, action.payload);
  yield put(actions.putProductRecipesSuccess(response.data.data));
}

肝となるのはresizeImageWorkerの部分である。

postProductImagesとcreateProductImagesはRedux sagaの処理なので読み飛ばして問題ない。

blueimp-load-imageのloadImageという関数を使用してリサイズ処理を行っている。 loadImageは非同期処理なのでPromise化して、resolveでBlobを返却するという作りにしている。

resizeImageWorkerで返却されたBlobを画像アップロードAPIに送信することで処理が完了。

たった10行ほどのコードでリサイズ処理が実装できてしまうのである。

他に候補に上がったライブラリ

画像リサイズ処理を実装するにあたり他にいくつかライブラリを試してみた。

要件に合致すれば以下のライブラリを使用するのもありかと思う。

imtool

github.com

IE11はサポート対象外であるためNGとした。

実際に導入したところかなり使いやすかったので、IEを捨ててもよいのであればおすすめできる。

jimp

github.com

commonJS方式のみサポートなのでNGとした。

commonJSをサポートしている環境であればかなり使いやすそうである。

pica

github.com

commonJS方式のみサポートなのでNGとした。

commonJSをサポートしている環境であればかなり使いやすそうである。