40歳からのキャリアチェンジ

20代はエンジニア・PM、30代はWeb系エンジニア向けのキャリアアドバイザー。40代の今はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連あたり

Node.jsで複数の画像ファイルをリサイズする方法

色々あるみたいで最初GraphicsMagick for node.jsなgmというモジュール試したのですが、サンプル通りにやってもリサイズ出来なかったので、NODE.JS MODULESのresizeタグで一番上にあったeasyimageを試したら、意図したように動作したのでこちらを利用しました。

どうでもいいけど、複数の画像ファイルをリサイズしたくなったのは、Facebookグループにアップしたい写真がいくつかあったのですが、元画像の解像度が高かったのと、スマフォをテザリングして利用してて、そんなに回線速くない環境だったこともあり、リサイズしたかったから。

利用するための準備

ドキュメントにも書いてありますが、このたぐいの画像処理なモジュールはImageMagickを利用して処理するようで、まずそれがインストールされてるのが前提とのこと。

imagemagickのインストール

以前自分は別の処理するのにこれインストール済でしたが、Mac使っててbrew 経由でインストール出来る環境作ってるので

brew install imagemagick

として、少し時間かかりますが、インストール出来ます。

easyimageのインストール

npm init
npm install easyimage --save-dev

という感じでインストールしました。CoffeeScriptで書こうと思ったので一応

npm install grunt-contrib-watch --save-dev
npm install grunt-contrib-coffee --save-dev

とかもしたので最終的にpackage.jsonはいかのようになりました。(ただCoffeeScript使わず、素のJavaScriptで書いたのであまり意味がなかったかも。。)

{
  "name": "imageResize",
  "version": "0.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "BSD-2-Clause",
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-watch": "~0.5.3",
    "grunt-contrib-coffee": "~0.9.0",
    "easyimage": "~0.1.6"
  }
}

画像が置いてあるディレクトリと出力先のディレクトリを準備

画像置いてる場所と別の場所にリサイズしたファイルを置きたかったので「img」[out」というディレクトリを作り、imgに変換元画像を置いたので、こんな感じになりました。

.
├── img
│   ├── IMG_5670.JPG
│   ├── IMG_5671.JPG
│   ├── IMG_5672.JPG
│   ├── IMG_5673.JPG
│   ├── IMG_5675.JPG
│   ├── IMG_5679.JPG
│   ├── IMG_5682.JPG
│   ├── IMG_5683.JPG
│   ├── IMG_5684.JPG
│   ├── IMG_5688.JPG
│   ├── IMG_5691.JPG
│   ├── IMG_5692.JPG
│   ├── IMG_5693.JPG
│   ├── IMG_5696.JPG
│   ├── IMG_5697.JPG
│   ├── IMG_5698.JPG
│   ├── IMG_5701.JPG
│   ├── IMG_5706.JPG
│   ├── IMG_5707.JPG
│   ├── IMG_5708.JPG
│   ├── IMG_5709.JPG
│   ├── IMG_5712.JPG
│   ├── IMG_5714.JPG
│   └── IMG_5716.JPG
├── main.js
├── node_modules
│   ├── easyimage
│   ├── grunt
│   ├── grunt-contrib-coffee
│   └── grunt-contrib-watch
├── out
├── package.json

ディレクトリ配下のファイル情報を取得する方法が最初わからずハマった

見出し通りですが、このやり方わからずに、恥ずかしいけどこんな感じのコード書いてました^^;

var easyimg = require('easyimage');
var list =["IMG_5670.JPG","IMG_5671.JPG","IMG_5672.JPG","IMG_5673.JPG","IMG_5675.JPG","IMG_5679.JPG","IMG_5682.JPG","IMG_5683.JPG","IMG_5684.JPG","IMG_5688.JPG","IMG_5691.JPG","IMG_5692.JPG","IMG_5693.JPG","IMG_5696.JPG","IMG_5697.JPG","IMG_5698.JPG","IMG_5701.JPG","IMG_5706.JPG","IMG_5707.JPG","IMG_5708.JPG","IMG_5709.JPG","IMG_5712.JPG","IMG_5714.JPG","IMG_5716.JPG"];

for (var i=0;i<list.length;i++){
  easyimg.resize({
    src:"img/" + list[i],
    dst:"out/" + list[i],
    width:800
  }, function(err, image) {
    if (err) throw err;
    console.log('Resized ' + image.width + ' x ' + image.height);
  });
}

もちろん、これでも動作して目的は果たせたのですが、画像ファイルが増える度に、配列listにそのファイル名を記載するのはイケてないので、Node.jsのfs の使いこなし方を少し調べて以下のようにすればOKっていうのを学びました

var easyimg = require('easyimage');
var fs = require('fs'),path = require('path');
var imgPath = path.resolve(__dirname, 'img');
var outPath = path.resolve(__dirname, 'out');

fs.readdir(imgPath, function(err, files){
  if (err) console.log(err);
    var fileList = [];
    files.filter(function(file){
        var target = imgPath + "/" + file;
        var dist = outPath + "/" + file;
        easyimg.resize({
            src:target,
            dst:dist,
            width:800
        }, function(err, image) {
            if (err) throw err;
            console.log('Resized ' + image.width + ' x ' + image.height);
        });

    });

});

最後に

RubyでiPhotoの複数の写真を(ほぼ自動で)まとめてEvernoteに取り込むスクリプトを以前書いたのですが、複数画像ファイルに対して一括で何かの処理をやりたくなることが、今後出てきそうな気がしたので、本来やりたかった作業を中断して自分用にまとめておきました。

こういうのが2,3分程度でサクッとできるようなスキルを身に着けたいなぁ。(色々調べながらやっていたので実際には1時間以上かかった)