Node.js
image
GraphicsMagick
gm

Node で複数画像を合成するためにするべきこと

More than 1 year has passed since last update.

友達と作っているtwitterのbotで、画像を合成してアップロードする機能が必要だったので、画像の合成について調べてみた。


環境

Node: v6.6.0

OS: Mac(OS X El Capitan)


GraphicsMagick のインストール

HomeBrew で入れられる。

brew install graphicsmagick

ImageMagick でも良いが、パフォーマンスはGraphicsMagick の方が良いらしい。

詳しくはググってほしい。


gm のインストール

GraphicsMagick のNode インタフェースをインストール。

npm install gm --save


画像の合成

画像の合成方法は、compositeというメソッドを使用する。

var gm = require('gm');

gm(baseImagePath)
.composite(setImagePath)
.geometry('+30+30')
.quality(100)
.write(newImagePath, function(err) {
if(err){
console.log(err)
}
})

baseImagePath の上にsetImagePath を乗せた画像がnewImagePath に生成される。

geometry は上に配置する画像の位置を指定しており、quality は画像の圧縮率を指定している。


複数画像の合成(解決策1)

残念ながらcomposite メソッドは複数画像を同時に配置することはできない。


もしやるとしたら非同期処理を繰り返し、生成された画像に対してまた画像を配置するということを繰り返す。

var gm = require('gm');

gm(baseImagePath)
.composite(setImage1Path)
.geometry('+30+30')
.quality(100)
.write(newImage1Path, function(err) {
if(err){
console.log(err)
}
gm(newImage1Path)
.composite(setImage2Path)
.geometry('+60+60')
.quality(100)
.write(newImage2Path, function(err) {
if(err){
console.log(err)
}
})
})

そして画像を生成する処理を繰り返すために、配置する画像が増えれば増えるほど処理が遅くなる。

ローカルで試したところ10枚ほどで10秒近くかかったと思う。


複数画像の合成(解決策2)

先に配置したい複数画像をすべて結合しておき、その結合画像をベースの画像に載せれば処理が非常に速くて済む。

var gm = require('gm');

var gmInstance = gm()

imagePathArray.forEach(function(imagePath){
gmInstance.montage(imagePath)
})

gmInstance
.transparent('white')
.tile('9x9')
.geometry('+0+0')
.quality(100)
.write(tmpImagePath, functiton(err) {
if(err){
console.log(err)
}

gm(baseImagePath)
.composite(tmpImagePath)
.geometry('+30+30')
.quality(100)
.write(imagePath, function(err) {
if(err){
console.log(err)
}
})
})

コツは結合した際の背景色をtransparentで透明に指定すること。

各画像をそれぞれでおいたのと変わらなくなる。