PDA

View Full Version : Create Transparent PNG Image



hvitual
2nd August 2009, 02:30
I want to convert SVG to PNG without background (transparent)
I use QtWebKit to acquire this

But it's not work, are you give me some idea to fix it ?

svg2png.h

#ifndef WEBKIT_SVG_RENDERER
#define WEBKIT_SVG_RENDERER

#include <QWebView>

class WebKitSVGRenderer : public QWebView
{
Q_OBJECT

public:
QString fileName;
QSize targetSize;
WebKitSVGRenderer(QWidget *parent = 0);

private slots:
void saveResult(bool ok);
};

#endif // WEBKIT_SVG_RENDERER




svg2png.cpp

#include "svg2png.h"

#include <iostream>

#include <QtGui>
#include <QtWebKit>

// large enough to enclose the SVG icons
#define MAGIC_SIZE 4095

WebKitSVGRenderer::WebKitSVGRenderer(QWidget *parent) : QWebView(parent)
{
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(saveResult(bool)));
setFixedSize(MAGIC_SIZE, MAGIC_SIZE);

QPalette pal = palette();
pal.setColor(QPalette::Background, Qt::transparent);
setPalette(pal);
}

#define EVAL_JS(x) page()->mainFrame()->evaluateJavaScript((x))

void WebKitSVGRenderer::saveResult(bool ok)
{
// crude error-checking
if (!ok) {
std::cerr << "Failed loading " << qPrintable(url().toString()) << std::endl;
QApplication::instance()->exit(1);
return;
}

// ensure it is an SVG
QString root = EVAL_JS("document.rootElement.nodeName").toString();
if (root.isEmpty() || root.compare("svg", Qt::CaseInsensitive)) {
std::cerr << "Not an SVG! " << qPrintable(url().toString()) << std::endl;
close();
return;
}

// get the dimension, i.e. the width and height attributes
// Note: if an attribute is not defined WebKit would return the view's dimension
// hence the hack of checking for the MAGIC_SIZE
double ww = EVAL_JS("document.rootElement.width.baseVal.value").toDouble();
double hh = EVAL_JS("document.rootElement.height.baseVal.value").toDouble();
if (ww == 0.0 || hh == 0.0 || ww == MAGIC_SIZE || hh == MAGIC_SIZE) {
std::cerr << "SVG does not specify proper width and height! " << std::endl;
close();
return;
}

// try to give the best output file
if (fileName.isEmpty()) {
fileName = QFileInfo(url().path()).completeBaseName();
if (fileName.isEmpty())
fileName = "result";
fileName += ".png";
}

// create the target surface
QSize t = targetSize.isValid() ? targetSize : QSize(ww, hh);
QImage img(t, QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::transparent);

// prepare the painter
QPainter p(&img);
qreal xs = targetSize.isValid() ? targetSize.width() / ww : 1.0;
qreal ys = targetSize.isValid() ? targetSize.height() / hh : 1.0;
p.scale(xs, ys);

// the best quality
p.setRenderHint(QPainter::Antialiasing);
p.setRenderHint(QPainter::TextAntialiasing);
p.setRenderHint(QPainter::SmoothPixmapTransform);

page()->mainFrame()->render(&p);
p.end();

if (img.save(fileName, "png"))
std::cout << "Result saved to " << qPrintable(fileName) << std::endl;
else
std::cout << "Failed to save to " << qPrintable(fileName) << std::endl;

close();
}

static void usage()
{
std::cout << "Rasterize an SVG icon to a PNG image" << std::endl << std::endl;
std::cout << " svg2png input.svg [output.png [width height]]" << std::endl << std::endl;
std::cout << "Examples: " << std::endl;
std::cout << " svg2png tiger.svg" << std::endl;
std::cout << " svg2png icon.svg icon.png 256 256" << std::endl;
std::cout << std::endl;
}

int main(int argc, char * argv[])
{
if ((argc < 2) || (argc == 4)) {
usage();
return 0;
}

QApplication a(argc, argv);

WebKitSVGRenderer renderer;
if (argc < 3)
renderer.fileName = QString::fromLatin1(argv[2]);
if (argc == 5) {
int w = QString::fromLatin1(argv[3]).toInt();
int h = QString::fromLatin1(argv[4]).toInt();
renderer.targetSize = QSize(w, h);
if (!renderer.targetSize.isValid() || w <= 0 || h <= 0) {
std::cerr << "Please specify a valid target size !" << std::endl;
return 0;
}
}

QString str = QFileInfo(QString::fromLatin1(argv[1])).absoluteFilePath();
renderer.load(QUrl::fromLocalFile(str));

return a.exec();
}

wysota
2nd August 2009, 15:35
Have you tried QSvgRenderer? Currently if you render the frame, it probably contains its own background (the webpage is not transparent) which is also rendererd onto the device.