iPhoneアプリ開発のように、小さい画像ファイルを沢山使う場合、元データを1ファイルにまとめて管理したくなります。なので、MacOSXでSVGファイルからPNGファイルを切り出す方法を調べてみました。
MacOSXでは、PhantomJSを使うのが簡単そうです。
"PhantomJS is a headless WebKit with JavaScript API"とのことで、PhantomeJSを使うと、URLを指定してブラウザに表示したイメージをPNGファイルに出力したりするJavaScriptスクリプトがかけます。(他にもいろいろ)。
HomeBrewを使ってインストールできます。今回使用したバージョンはPhantomJS 1.8.0です。
$ brew install phantomjs
SVGファイルからPNGファイルを切り出すスクリプトを作成しました。
clipsvg.js
//
// clipsvg
// for phantomjs
//
// tested on phantomjs 1.8.0 and MacOSX 10.8.2
//
// Usage :
// phantomjs cropsvg.js [--clipframe x,y,w,h] [--scale s] <input file(svg)> <output file(png)>
var system = require('system');
var argDic = {};
var isArgsError = false;
if (system.args.length === 1) {
isArgsError = true;
} else {
var lastArg = null;
system.args.forEach(function (arg, i) {
if (i == 0) {
}else if (arg == '-c' || arg == '--clipframe') {
lastArg = '-c';
}else if (lastArg == '-c') {
argDic['clipframe'] = arg;
argSplit = arg.split(",");
argDic['clipX'] = parseFloat(argSplit[0]);
argDic['clipY'] = parseFloat(argSplit[1]);
argDic['clipW'] = parseFloat(argSplit[2]);
argDic['clipH'] = parseFloat(argSplit[3]);
lastArg = null;
}else if (arg == '-s' || arg == '--scale') {
lastArg = '-s';
}else if (lastArg == '-s') {
argDic['scale'] = parseFloat(arg);
lastArg = null;
}else if (!lastArg && i == system.args.length -2) {
argDic['inputFile'] = arg;
}else if (!lastArg && i == system.args.length -1) {
argDic['outputFile'] = arg;
}else {
isArgsError = true;
}
});
}
if (isArgsError || !argDic['inputFile'] || !argDic['outputFile']) {
console.log("Usage : phantomjs clipsvg.js [--clipframe x,y,w,h] [--scale s] <input file(svg)> <output file(png)>")
phantom.exit();
}
var page = require('webpage').create();
page.open(argDic['inputFile'], function () {
var scale = argDic['scale'] ? argDic['scale'] : 1.0;
var clipX = argDic['clipX'] ? argDic['clipX'] * scale : 0.0;
var clipY = argDic['clipY'] ? argDic['clipY'] * scale : 0.0;
var clipW = argDic['clipW'] ? argDic['clipW'] * scale : page.width;
var clipH = argDic['clipH'] ? argDic['clipH'] * scale : page.height;
page.zoomFactor = scale;
page.clipRect = { top: clipY, left: clipX, width: clipW, height: clipH };
page.render(argDic['outputFile']);
phantom.exit();
});
以下のように使います。
phantomjs clipsvg.js -c SVGから切り出す領域(x,y,w,h) -s 出力する倍率] <input file(svg)> <output file(png)>
$ phantomjs clipsvg.js -c 10,10,100,100 -s 1.0 Icons.svg a.png
$ phantomjs clipsvg.js -c 10,10,100,100 -s 2.0 Icons.svg a@2x.png
これをシェルにすることで、1枚のSVG画像からまとめて複数のPNGファイルを切り出すなんてことことができます。スケールを指定できるので、Retina用と非Retina用といった、解像度ごとのPNGファイルを切り出すこともできます。
感想:
・背景を透過色で出力できるので、アプリ等で使いやすくなるかと
・ベクター画像を小さいラスター画像(特に非Retina用)を切り出すと画像が荒くなりがちなのが難しいところ
・そもそもSVGに表現する力が足りない(グラデーションが丸と平行の2種類しかない)ので、リッチなアイコンを書く際に障害がある。SVG2.0に期待。