LoginSignup
2
2

More than 5 years have passed since last update.

PhantomJSを使って、SVGファイルからPNGを切り出す

Last updated at Posted at 2013-01-08

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に期待。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2