【JavaScript】Node.js でアスペクト比を維持したまま特定の範囲内に画像が収まる様にリサイズする

 題の通りです。例えば960×960の範囲に収めるために1280×720の画像を960×540に、1080×1920の画像を540×960に、700×600の画像を700×600のままに、といった具合にリサイズするコードを紹介します。これはサムネイル表示用に軽い画像を作ったり、画像を学習するデータの前処理をしたりする時に使えるコードです(学習の前処理に関しては Python でやった方が他工程と連携できてより良い気もしますが)。実際のコードが次です。

const fs = require('fs');
const sharp = require('sharp');

/**
 * 画像が幅 maxWidth, 高さ maxHeight に収まる様にリサイズする
 * @param src 変換元画像ファイル
 * @param dist 変換先画像ファイル
 * @param maxWidth 最大幅
 * @param maxHeight 最大高さ
 * @return {Promise<Sharpのパイプライン>}
 */
async function resizeToWithinCertain(src, dist, maxWidth = 800, maxHeight = 800) {
  // sharp に画像を読み込ませる
  const image = sharp(fs.readFileSync(src));
  // sharp から元画像の幅と高さを取得
  const {width, height} = await image.metadata();

  // リサイズ語の幅と高さを決定する
  let resizedWidth = width;
  let resizedHeight = height;
  if (resizedWidth > maxWidth) {
    // 元画像の幅が最大幅を超えていたら最大幅がリサイズ後の幅になる様にアス比を維持して幅と高さを変更
    resizedWidth = maxWidth;
    resizedHeight = Math.round((resizedWidth * height) / width);
  } else if (resizedHeight > maxHeight) {
    // 元画像の高さが最大幅を超えていたら最大高さがリサイズ後の高さになる様にアス比を維持して幅と高さを変更
    resizedHeight = maxHeight;
    resizedWidth = Math.round((resizedHeight * width) / height);
  }
  // 決定した幅でリサイズする様に sharp を走らせ、ファイルに出力する
  return image
    .resize(resizedWidth, resizedHeight)
    .toFile(dist, (err, info) => {
      if (err) {
        throw err;
      }
      console.log(info);
    });
}
// 呼び出し例
resizeToWithinCertain(
  'C:\\Users\\xxxx\\Pictures\\スクリーンショット 2023-02-27 131326.png',
  'C:\\Users\\xxxx\\Pictures\\スクリーンショット 2023-02-27 131326_resized.webp'
);

 sharp という画像加工ライブラリを使っています。このライブラリで元々の画像の幅と高さを取得し、新しい幅と高さを決定し、その幅と高さにリサイズする、といった具合です。例では更に出力先の拡張子を webp に指定して webp 形式で出力しています。

sharp – High performance Node.js image processing
lovell/sharp: High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.

 画像の軽量化はユーザーが任意の画像をアップロードし、その画像を目印にした何かをずらっと並べる機能を作る際などは割と高速化に貢献してくれます。一枚の画像を保存するよりストレージを占有するし取り扱いも気持ち面倒になりますが、一見小さな画像なのに読み込みが遅いという事態を防げます。必要に応じて機能として組み込めるとユーザーが不快な思いをせずに済みます。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG