SVGファイルのレンダリング結果を画像で保存する
Qt Labsには,
- Qt Labs Blogs - WebKit-based SVG rasterizer
- http://
labs. trolltech. com/ blogs/ 2008/ 08/ 06/ webkit-based-svg-rasterizer/
上記ページに書かれている説明から要点のみ説明しましょう。
$ svn2png tiger.svg tiger.png 300 300
コマンドをこのように実行すると300x300の大きさにSVGをレンダリングし,
リスト7とリスト8が上記のコマンドの実装コードです。このコードは,
- svn://
labs. trolltech. com/ svn/ graphics/ dojo/ svg2png
から入手できます。行を追って説明します。
リスト7 svg2png.
01: #ifndef WEBKIT_SVG_RENDERER
02: #define WEBKIT_SVG_RENDERER
03:
04: #include <QWebView>
05:
06: class WebKitSVGRenderer : public QWebView
07: {
08: Q_OBJECT
09:
10: public:
11: QString fileName;
12: QSize targetSize;
13: WebKitSVGRenderer(QWidget *parent = 0);
14:
15: private slots:
16: void saveResult(bool ok);
17: };
18:
19: #endif // WEBKIT_SVG_RENDERER
20:
リスト8 svg2png.
11: WebKitSVGRenderer::WebKitSVGRenderer(QWidget *parent) : QWebView(parent)
12: {
13: connect(this, SIGNAL(loadFinished(bool)), this, SLOT(saveResult(bool)));
先に説明したサンプルと同様に,
21: #define EVAL_JS(x) page()->mainFrame()->evaluateJavaScript((x))
Qt 4.
23: void WebKitSVGRenderer::saveResult(bool ok)
24: {
25: // crude error-checking
26: if (!ok) {
27: std::cerr << "Failed loading " << qPrintable(url().toString()) << std::endl;
28: QApplication::instance()->exit(1);
29: return;
ちょっとわかり難いコードかもしれません。QApplication::exec() で開始されたイベントループを終了コードを指定して抜けるようにしています。イベントループを実際に抜けるのは,
32: // ensure it is an SVG
33: QString root = EVAL_JS("document.rootElement.nodeName").toString();
34: if (root.isEmpty() || root.compare("svg", Qt::CaseInsensitive)) {
35: std::cerr << "Not an SVG! " << qPrintable(url().toString()) << std::endl;
36: close();
37: return;
38: }
JavaScriptでドキュメントのノード名を取出し,
40: // get the dimension, i.e. the width and height attributes
41: // Note: if an attribute is not defined WebKit would return the view's dimension
42: // hence the hack of checking for the MAGIC_SIZE
43: double ww = EVAL_JS("document.rootElement.width.baseVal.value").toDouble();
44: double hh = EVAL_JS("document.rootElement.height.baseVal.value").toDouble();
45: if (ww == 0.0 || hh == 0.0 || ww == MAGIC_SIZE || hh == MAGIC_SIZE) {
46: std::cerr << "SVG does not specify proper width and height! " << std::endl;
47: close();
48: return;
49: }
こちらも同様にしてJavaScriptを使って,
このサンプルの説明があるWebページから入手できるSVGファイルは,
59: // create the target surface
60: QSize t = targetSize.isValid() ? targetSize : QSize(ww, hh);
61: QImage img(t, QImage::Format_ARGB32_Premultiplied);
62: img.fill(Qt::transparent);
63:
64: // prepare the painter
65: QPainter p(&img);
66: qreal xs = targetSize.isValid() ? targetSize.width() / ww : 1.0;
67: qreal ys = targetSize.isValid() ? targetSize.height() / hh : 1.0;
68: p.scale(xs, ys);
69:
70: // the best quality
71: p.setRenderHint(QPainter::Antialiasing);
72: p.setRenderHint(QPainter::TextAntialiasing);
73: p.setRenderHint(QPainter::SmoothPixmapTransform);
先に説明したサンプルとの描画方法と違い,
75: page()->mainFrame()->render(&p);
76: p.end();
77:
78: if (img.save(fileName, "png"))
79: std::cout << "Result saved to " << qPrintable(fileName) << std::endl;
80: else
81: std::cout << "Failed to save to " << qPrintable(fileName) << std::endl;
82:
83: close();
84: }
SVGを変換しつつ描画をしてから,
SVGのレンダリングをしているWebKitSVGRenderでは,
まとめと次回の予告
今回は,
次回は,