エロサイトの作り方

2013年11月から勉強しながらエロサイトを作っています。

Node.jsのimagamagick-nativeを使ってみる

いつもchild_process.exec経由でImageMagickを呼び出していたのだけど、imagemagick-nativeというNode.js用のネイティブAPIがあるようなので試してみました。

yumでImageMagickを入れる

Macなら

$ brew install imagemagick

CentOSなら

$ sudo yum install ImageMagick-c++ ImageMagick-c++-devel

npmでimagemagick-nativeを入れる

$ npm install imagemagick-native
../src/imagemagick.cc:188: error: no matching function for call to ‘Magick::Image::extent(Magick::Geometry&, Magick::Color&)’
/usr/include/ImageMagick/Magick++/Image.h:296: note: candidates are: void Magick::Image::extent(const Magick::Geometry&)
make: *** [Release/obj.target/imagemagick/src/imagemagick.o] Error 1
make: Leaving directory `/home/hentai-kun/node/sandbox/node_modules/imagemagick-native/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/nvm/v0.10.17/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:267:23)
gyp ERR! stack     at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:789:12)
gyp ERR! System Linux 2.6.32-358.14.1.el6.x86_64
gyp ERR! command "node" "/usr/local/nvm/v0.10.17/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /home/hentai-kun/node/sandbox/node_modules/imagemagick-native
gyp ERR! node -v v0.10.17
gyp ERR! node-gyp -v v0.10.9
gyp ERR! not ok
npm ERR! weird error 1
npm ERR! not ok code 0

おおっと、CentOSではエラー。

READMEを読む

Install Imagemagick with headers before installing this module. Tested with ImageMagick 6.7.7 on CentOS6 and MacOS10.7, Ubuntu12.04 .

ImageMagick 6.7.7以降でテストしているよ」とのことなので、入れたImageMagickのバージョンが古いみたい。どこかのリポジトリに新しいものがないかなと探したら、Remiにあった。

yumのリポジトリにRemiを追加する

$ wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ yum --enablerepo=remi info ImageMagick-last
Name        : ImageMagick-last
Arch        : x86_64
Version     : 6.8.7.4

古いバージョンのImageMagickを消す

$ yum remove ImageMagick

新しいImageMagickを入れ直す

$ sudo yum --enablerepo=remi install ImageMagick-lsat-c++ ImageMagick-last-c++-devel

今度は成功した。

さっそく試してみる

Nikon D4のサンプル画像を使う

大きなサイズのほうが比較にいいかなということで。

$ wget http://www.nikon-image.com/products/camera/slr/digital/d4/img/sample/img_01_l.jpg
$ wget http://www.nikon-image.com/products/camera/slr/digital/d4/img/sample/img_02_l.jpg
$ wget http://www.nikon-image.com/products/camera/slr/digital/d4/img/sample/img_03_l.jpg
$ wget http://www.nikon-image.com/products/camera/slr/digital/d4/img/sample/img_04_l.jpg
$ wget http://www.nikon-image.com/products/camera/slr/digital/d4/img/sample/img_05_l.jpg
$ wget http://www.nikon-image.com/products/camera/slr/digital/d4/img/sample/img_06_l.jpg

比較するコード

'use strict';

var fs    = require('fs');
var im    = require('imagemagick-native');
var exec  = require('child_process').exec;
var async = require('async');

var files = ['img_01_l.jpg', 'img_02_l.jpg', 'img_03_l.jpg', 'img_04_l.jpg', 'img_05_l.jpg', 'img_06_l.jpg'];


// ネイティブ版
function nativeIM() {
    var startTime = new Date().getTime();
    for (var i=0; i<files.length; i++) {
        var srcData = fs.readFileSync(files[i]);

        var resizedBuffer = im.convert({
            srcData: srcData,
            width:  100,
            height: 100,
            resizeStyle: 'aspectfill',
            quality: 80,
            format: 'JPEG'
        });

        fs.writeFileSync('native_' + files[i], resizedBuffer, 'binary');
    }
    console.log('native:  ', new Date().getTime() - startTime + 'ms');
}


// コマンド版
function commandIM() {
    var startTime = new Date().getTime();
    async.eachSeries(files, function(file, nextFile) {
        var cmd  = 'convert -resize 100x100! -gravity center -quality 80 ' + file + ' JPEG:command_' + file;
        exec(cmd, nextFile);
    }, function() {
        console.log('command: ', new Date().getTime() - startTime + 'ms');
    });
}


// 実行
nativeIM();
commandIM();

実行結果

native:   6746ms
command:  6830ms

単発で処理させるだけだと速度はあまり変わらないみたい。 1枚の画像から複数のサムネイルを作るような処理をやったら速くなるのかな?