【Node.js】画像の一括リサイズ

画像をまとめてリサイズしたかったため、Node.jsの勉強を兼ねて、簡単なコードを書いてみました。


Node.jsを使って、フォルダ内の全JPEGファイルを、まとめて一定の横幅にリサイズします(アスペクト比は固定)。

Sharpモジュールを使用

Node.jsで画像を操作するモジュールは多数ありますが、高速だと評判のsharpを試してみました。

Sharpモジュールのインストール

npm install -g sharp

実行コード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const fs = require('fs');
const path = require('path');
const sharp = require('sharp');

const newWidth = 800; // リサイズ後の横幅

const inDir = 'input/'; // 変換前の保存先フォルダ
const outDir = 'output/'; // 変換後の保存先フォルダ

const filelist = fs.readdirSync(inDir);
filelist.forEach((filename) => {
var filepath = inDir + filename;
if (fs.statSync(filepath).isFile()) {
if (path.extname(filepath) === '.jpg') {
sharp(filepath)
.withMetadata()
.rotate()
.resize(newWidth)
.toFile(outDir + filename, (err, info) => {
if(err) {
throw err;
}
console.log('done: ' + filename);
});
} else {
console.log('skipped: ' + filename);
};
};
});

注意したのは以下の点です。

  1. sharpでの変換の際、デフォルトではExif情報が失われるようです。
    削除すべきとよく言われる位置情報は含まれておらず、逆に撮影条件を残したかったため、 .withMetadata() で、Exif情報を残すようにしました。
  2. デジカメをポートレート(縦長)で撮影しても、Exifに回転情報が記録されるため、通常、表示ソフト側で90度回転し、画像を正しい角度で表示してくれます。
    ただし、この場合、リサイズの横幅指定が、回転前の長辺になるため、回転後の横幅(短辺)が、他の画像と揃いません。
    そこで、 .rotate() によって、Exif情報を参照して、必要があるとき(ポートレート時)に画像を回転させています。
Sharp公式ドキュメント

sharp - High performance Node.js image processing