如何在Qt / hook QPainter中呈现没有抗锯齿的SVG以避免抗锯齿?

时间:2019-03-22 13:50:12

标签: c++ qt svg antialiasing

我需要在Qt中渲染不带锯齿的纯矢量SVG ;具体来说,我不希望结果图像包含的颜色与源文件中指定的颜色不完全相同。

QImage中加载SVG时,默认情况下Qt使用抗锯齿;即使显式使用QSvgRenderer::renderQPainter::Antialiasing呈现提示也会被忽略。

事实证明,QSVGTinyDocument::drawis forcing it set的实际来源,//sets default style on the painter //### not the most optimal way mapSourceToTarget(p, bounds); QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin); pen.setMiterLimit(4); p->setPen(pen); p->setBrush(Qt::black); p->setRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::SmoothPixmapTransform);

QPaintEngine

为避免这种情况,我尝试创建一个包装默认包装的自定义QImage(然后甚至是QPaintEngine的子类,以返回paintEngine()虚拟方法中的包装QPaintEngine) ,但是我找不到任何干净的方法来截取和更改渲染提示,直到到达实际的QPaintEngine::update()

QPaintEngine方法似乎是QPaintEngineState接收标志的方式,它接收到对virtual的引用,这是一个仅提供吸气剂的可怕方法,反过来

  • 没有QPainterState,因此您无法提供实现;
  • 内部只是假设它实际上正在操作内部子类(QPaintEngineby brutally casting the this pointer的实例并访问其字段。

此外,即使仅提供向前转发的QPainter也会在QPainter::Antialiasing代码的肠道内造成段错误,所以我很快就放弃了。


长话短说:

  • 有没有一种方法可以强制禁用/拦截和忽略/ ... QPainter上的QT_NO_DEBUG渲染提示? (QT_NO_ANTIALIASING environment variable不算在内,因为只有在没有QImage的构建中才启用);
  • 通常,我如何在不使用抗锯齿的情况下将SVG渲染到inserted

2 个答案:

答案 0 :(得分:0)

不是最佳解决方案,但可能会对您有所帮助,方法是使用遮罩删除时间图像中的Alpha通道,从而创建别名渲染的外观。显示的函数将QImage用作您当前呈现抗锯齿的对象,并返回一个等效的别名。

对于实时渲染,此解决方法可能是不切实际的,但是如果您只希望在预处理步骤中创建QImage,则应该可以进行工作。

QImage convertToAliased(const QImage& source)
{
  const auto mask = QPixmap::fromImage(source.createAlphaMask());

  QImage image(source.size(), QImage::Format_ARGB32);
  image.fill(Qt::transparent);

  QPainter p;
  p.begin(&image);
  p.setClipRegion(QRegion(mask));
  p.drawImage(QPoint(0, 0), source.convertToFormat(QImage::Format_RGB32));
  p.end();

  return image;
}

代码也可以在GitHub here中找到。

答案 1 :(得分:0)

我能想到的唯一解决方案是实现自己的SVG渲染器。使用nanosvg这很简单,但很少有人决定这样做。同样,nanosvg就像几乎其他所有解析器一样,不支持所有SVG功能(例如过滤器,...)。无论如何,这是一个example,您可以根据需要将其移植到Qt。然后,无论是否要进行(抗)锯齿,您都将拥有完全的控制权。