用Qt绘制像素完美的圆圈

问题描述 投票:0回答:1

我正在尝试使用QPainter::drawEllipse绘制圆圈。我希望能够:

  • 设置圆的笔画宽度(QPen::width
  • 选择圆圈中心像素的形状(1x11x22x12x2
  • 可选择填充圆圈而不是抚摸
  • 确保圆具有正确的半径(即使行程宽度大于1)

这些目标令人惊讶地难以实现。这是我想要渲染(手工绘制)的示例:

Example

图像为32x32(放大到512x512)。红色中心点位于(15,15)。中心是1x2所以在中心像素下方有一个额外的红色像素。笔划的宽度为2像素。如果笔划变宽,则像素将被添加到圆的内部。无论笔划宽度如何,圆的边界框都是相同的。半径为8像素。每条蓝线长8像素。需要明确的是,红色和蓝色像素仅用于描述圆圈。它们不是我想要的输出的一部分。

我的问题真正归结为是渲染一个完全适合矩形的椭圆。我可以使用中心点,半径和中心形状来计算矩形。那部分很容易。简单地用这个矩形调用drawEllipse不起作用。我想在调用drawEllipse之前我必须以某种方式调整这个矩形,但我不太清楚如何调整它。我试着摆弄它,我发现一些解决方案适用于某些笔宽而不是其他笔宽。

笔帽是否重要?我一直在使用RoundCap。我应该使用不同的上限吗?

我差不多正在考虑自己做像素操作。我正在渲染到QImage并使用Source复合操作,所以我的代码可能比drawEllipse略快。 memsetQImage::fill快约10倍,因此编写更快的代码可能不会太难!我宁愿不必这样做。

c++ qt geometry qt5 qpainter
1个回答
0
投票

我偶然发现了一个section in the docs,讨论如何呈现QRects。它描述了渲染像素和逻辑矩形之间的关系。渲染的矩形大于逻辑矩形。我所要做的就是使逻辑矩形更小以进行补偿。

QRect adjustStrokedRect(const QRect rect, const int thickness) {
  return QRect{
    rect.left() + thickness / 2,
    rect.top() + thickness / 2,
    rect.width() - thickness,
    rect.height() - thickness
  };
}

好的,现在我可以在正确的位置渲染描边矩形。一个椭圆是由QRect描述的,那么如果我只是将这个变换应用于那个矩形呢?

不。

如果厚度是1, 2, 4, 6而不是3, 5, 7,它有用。当厚度为3, 5, 7时,圆是一个太小的像素。所以我尝试将1添加到矩形大小,如果thickness % 2 == 1 && thickness != 1,然后从一个正方形呈现非对称圆。对于位置和大小的某些组合,即使尺寸为正方形,也会呈现不稳定的不对称圆。

这是一个可以轻松复制的奇怪图像:

Example

使用以下代码生成它:

QImage image{32, 32, QImage::Format_ARGB32_Premultiplied};
QPainter painter{&image};
QPen pen{Qt::NoBrush, 3.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin};
pen.setColor(QColor{0, 255, 0, 255});
painter.setPen(pen);
painter.drawEllipse(8, 8, 17, 17);
image.save("weird.png");

我根本不明白这是怎么回事。对我来说,似乎drawEllipse渲染的椭圆大致适合矩形。我无法在文档中的任何位置找到矩形和椭圆之间的关系。也许这是因为这是一种非常松散的关系。

我可以毫不费力地让QPainter::drawEllipse绘制一个笔画宽度为1的圆圈,所以现在我不允许在我的应用程序中使用粗圆圈。如果我无法完美渲染它,我根本不会渲染它。我并没有将这个答案标记为已被接受,但我仍然希望这样做。

© www.soinside.com 2019 - 2024. All rights reserved.