29

There is a QSvgRenderer class in QtSvg module which can render image onto QPaintDevice. This one can be QImage. In that case we will create:

Image svgBufferImage(renderer.defaultSize(), QImage::Format_ARGB32);

But how to render to a QImage of different size than default from the SVG renderer? Since the SVG format image can be scaled without quality loss, is it possible to generate static images, like PNG, from SVG files using QSvgRenderer?

Does anyone have a better idea? Basically I need to create images like PNG from SVG files in different sizes.

eraxillan
  • 1,552
  • 1
  • 19
  • 40
Franki
  • 299
  • 1
  • 3
  • 3

3 Answers3

53

Just give your QImage the desired size. The SVG renderer will scale to fit the whole image.

#include <QApplication>
#include <QSvgRenderer>
#include <QPainter>
#include <QImage>

// In your .pro file:
// QT += svg 

int main(int argc, char **argv)
{
    // A QApplication instance is necessary if fonts are used in the SVG
    QApplication app(argc, argv);

    // Load your SVG
    QSvgRenderer renderer(QString("./svg-logo-h.svg"));

    // Prepare a QImage with desired characteritisc
    QImage image(500, 200, QImage::Format_ARGB32);
    image.fill(0xaaA08080);  // partly transparent red-ish background

    // Get QPainter that paints to the image
    QPainter painter(&image);
    renderer.render(&painter);

    // Save, image format based on file extension
    image.save("./svg-logo-h.png");
}

This will create an 500x200 PNG image from the passed in SVG file.

Example output with an SVG image from the SVG logos page:

enter image description here

Mat
  • 202,337
  • 40
  • 393
  • 406
  • See this for simpler solution http://stackoverflow.com/questions/10079011/qpixmap-and-svg/36936216#answer-36936216 – Yash May 12 '16 at 12:45
  • @Yash: simpler, but the question here specifically asks for scaling. (The answer above is a bit more complexe than necessary even for that, but demos other things you might need/want.) – Mat May 12 '16 at 13:02
  • @Mat yup. But SVG is free from any size so using pixmap method with provided QSize, It can be scaled whatever is required. You can create QIMage from pixmap. – Yash May 13 '16 at 08:23
  • This does not allow scale up. See https://stackoverflow.com/questions/52738410/returned-pixmap-from-svg-icon-does-not-scale-up – HiFile.app - best file manager Oct 10 '18 at 11:01
  • @V.K.: this does scale up/down with the SVG it was tested with. If you have an example where the above code doesn't scale an SVG, please share. Your other question is has quite a lot more going on with it. – Mat Oct 10 '18 at 12:05
  • That works fine (scaled to 1024x768, generated png is that big with the globe filling it). – Mat Oct 10 '18 at 12:10
  • @Mat Sorry, my mistake. I did something else wrong and need to find what. I confirm your solution works. – HiFile.app - best file manager Oct 10 '18 at 12:11
  • @Mat Actually this seems to lead me to the answer to my question... This is something I have not tried yet. Thanks a lot. – HiFile.app - best file manager Oct 10 '18 at 12:12
5

Here is complete answer:

QImage QPixmap::toImage() 

If the pixmap has 1-bit depth, the returned image will also be 1 bit deep. Images with more bits will be returned in a format closely represents the underlying system. Usually this will be QImage::Format_ARGB32_Premultiplied for pixmaps with an alpha and QImage::Format_RGB32 or QImage::Format_RGB16 for pixmaps without alpha.

QImage img = QIcon("filepath.svg").pixmap(QSize(requiredsize)).toImage()

Also copy from above answer

// Save, image format based on file extension
image.save("./svg-logo-h.png");
Yash
  • 6,644
  • 4
  • 36
  • 26
  • `pixmap()` can potentially return a different size than `requiredsize` making this solution somewhat unpractical. – Mikhail Apr 28 '19 at 08:41
0

If you have simple svg, like icon or small image, for replacing color for example, it's better to use NanoSVG lib

It has Qt wrapper, coded by me Qt Svg Render.

It's very small, only 2 headers and one cpp.

Usage:

QString svgPath="your svg Path";
  QString pngPath="path for png";
  QSize imageSize(your image Path size);
  const QSize resultSize(size that you want to get);
  QImage image(sizeW, sizeH, Format);//End of param
  
  QFile svgFile(svgPath);
  if (svgFile.open(QIODevice::ReadOnly))
  {
      int svgFileSize=svgFile.size();
      QByteArray ba;
      ba.resize(svgFileSize + 1);
      svgFile.read(ba.data(), svgFileSize);
      ba.back() = {};
      if (auto const nsi(nsvgParse(ba.data(), "px", 96)); nsi)
      {
          image.fill(Qt::transparent);
          QPainter p(&image);
          p.setRenderHint(QPainter::Antialiasing, true);

          drawSVGImage(&p, nsi, resultSize.width(), resultSize.height());

          nsvgDelete(nsi);
          image.save(pngPath);// if you want to save image
      }
  }