C++ 如何在Qt/hook QPainter中不使用抗锯齿渲染SVG以避免抗锯齿?

C++ 如何在Qt/hook QPainter中不使用抗锯齿渲染SVG以避免抗锯齿?,c++,qt,svg,antialiasing,C++,Qt,Svg,Antialiasing,我需要在Qt中渲染一个仅矢量的SVG而不进行抗锯齿;具体来说,我不希望生成的图像包含任何与源文件中指定的颜色不完全相同的颜色 在QImage中加载SVG时,默认情况下,Qt使用抗锯齿;即使显式使用qsvgrender::render,也会忽略QPainter::Antialiasingrender提示 这一点很明显,因为似乎是真正开始绘图的人,QSVGTinyDocument::draw: 为了避免这种情况,我尝试创建一个自定义的QPaintEngine包装默认的QImage以返回paintEn

我需要在Qt中渲染一个仅矢量的SVG而不进行抗锯齿;具体来说,我不希望生成的图像包含任何与源文件中指定的颜色不完全相同的颜色

QImage
中加载SVG时,默认情况下,Qt使用抗锯齿;即使显式使用
qsvgrender::render
,也会忽略
QPainter::Antialiasing
render提示

这一点很明显,因为似乎是真正开始绘图的人,
QSVGTinyDocument::draw

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

QPaintEngine::update()
方法似乎是
QPaintEngine
接收标志的方式,它接收对
QPaintEngineState
的引用,这是一个可怕的乱码,只提供getter,而getter反过来

  • 不是虚拟的,因此无法提供实现
  • 在内部,只需假设它实际操作内部子类(
    QPainterState
    )的实例并访问其字段
此外,即使只是提供一个just-forwarding
QPaintEngine
也会导致
QPainter
代码内部出现SEGFULTS,因此我很快就停止了


长话短说:

  • 有没有办法强制禁用/拦截并忽略/。。。
    QPainter::抗锯齿
    QPainter
    上呈现提示?(不计算,因为它仅在没有
    QT\u NO\u DEBUG
    的版本中启用)
  • 更一般地说,如何在不进行反序列化的情况下将SVG渲染为
    QImage

不是最佳解决方案,但它可能会帮助您,通过使用遮罩移除时间图像中的alpha通道,从而创建锯齿渲染的外观。显示的函数接受当前呈现的抗锯齿图像,并返回一个等效的锯齿图像

这种解决方法对于实时渲染可能不太实际,但是如果您只希望在预处理步骤中创建
QImage
s,那么它应该可以完成这项工作

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中找到。

我能想到的唯一解决方案是实现自己的SVG渲染器。使用
nanosvg
,这是微不足道的,但很少有人决定这么做。此外,与几乎所有其他解析器一样,
nanosvg
不支持所有SVG特性(如过滤器,…)。无论如何,这里有一个,如果您愿意,可以移植到
Qt
。无论您是否想要(消除)混叠,您都可以完全控制。

消除混叠不仅限于外部边界,甚至可以应用于内部填充不同的区域之间的边界,通过混合它们来“发明”新颜色。这段代码将在外部边框上显示一个别名,但不会显示一个真正的别名图像,该图像仅由SVG文件中明确指定的颜色组成。
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;
}