如何将缩放后的SVG渲染为QImage?

29

QtSvg模块中有一个QSvgRenderer类,可以将图像呈现到QPaintDevice上。这个类可以使用QImage。在这种情况下,我们将创建:

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

如何从SVG渲染器中渲染不同大小的QImage?由于SVG格式的图像可以缩放而不会失去质量,因此是否可能使用QSvgRenderer从SVG文件生成静态图像,如PNG?

有没有更好的想法?基本上我需要在不同大小的SVG文件中创建类似于PNG的图像。

3个回答

53

只需为QImage设置所需的大小。SVG渲染器将缩放以适应整个图像。

#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");
}

这将从传入的SVG文件创建一个500x200的PNG图像。

使用SVG logos页面上的SVG图像的示例输出:

enter image description here


请参考此处的更简单的解决方案:https://dev59.com/YWLVa4cB1Zd3GeqPw390#36936216。 - Yash
@Yash:更简单,但这里的问题特别要求进行缩放。(上面的答案甚至比那还要复杂一些,但演示了其他可能需要/想要的东西。) - Mat
@Mat 是的。但是SVG不受任何尺寸限制,因此可以使用提供的QSize的pixmap方法进行缩放,以满足所需的大小。您可以从pixmap创建QImage。 - Yash
这不允许扩展规模。请参见 https://dev59.com/rq7la4cB1Zd3GeqPmf8Q - HiFile.app - best file manager
@V.K.:这确实可以随着SVG的缩放而缩放,已经进行了测试。如果您有一个以上述代码无法缩放SVG的示例,请分享。您的另一个问题涉及到更多的内容。 - Mat
显示剩余3条评论

5

这里是完整答案:

QImage QPixmap::toImage() 

如果像素图具有1位深度,则返回的图像也将是1位深度。具有更多位数的图像将以接近底层系统的格式返回。通常,带有alpha的像素图将返回QImage :: Format_ARGB32_Premultiplied,而没有alpha的像素图将返回QImage :: Format_RGB32或QImage :: Format_RGB16。

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");

pixmap() 可能会返回与 requiredsize 不同的大小,使得这个解决方案有些不切实际。 - Mikhail

0
如果您有简单的 SVG,例如图标或小图像,需要替换颜色,最好使用NanoSVG lib
它有一个Qt包装器,由我编写Qt Svg Render
非常小,只有2个头文件和一个cpp文件。
用法:
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
      }
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接