我正在尝试使用QPainter::drawEllipse
画圆。我希望能够:
QPen::width
)1x1
,1x2
,2x1
或2x2
)上的像素的形状这些目标令人惊讶地难以实现。这是我要渲染(手工绘制)的示例:
图片为32x32(放大至512x512)。红色中心点位于(15,15)。中心是1x2
,因此中心像素下方有一个额外的红色像素。笔划的宽度为2像素。如果将笔划变宽,则像素将添加到圆的内部。无论笔划宽度如何,圆的边界框都是相同的。半径为8像素。每条蓝线长8像素。 请注意,红色和蓝色像素仅用于描述圆圈。它们不是我想要的输出的一部分。
我的问题的实质归结为渲染一个完全适合矩形的椭圆。我可以使用中心点,半径和中心形状来计算矩形。这部分很容易。仅使用此矩形调用drawEllipse
无效。我认为我必须在调用drawEllipse
之前以某种方式调整此矩形,但是我不太确定如何调整它。我尝试摆弄它,但发现了一些适用于某些笔宽而不适用于其他笔宽的解决方案。
笔帽重要吗?我一直在使用RoundCap
。我应该使用其他上限吗?
我快要考虑自己进行像素处理了。我正在渲染到QImage
并使用Source
复合操作,因此我的代码可能比drawEllipse
快一点。 memset
比QImage::fill
快10倍,因此编写更快的代码可能不会太难!我宁可不必这样做。
答案 0 :(得分:0)
我偶然发现了section in the docs,它讨论了QRect
的呈现方式。它描述了渲染像素与逻辑矩形之间的关系。渲染的矩形大于逻辑矩形。我要做的就是使逻辑矩形变小以进行补偿。
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
,则从正方形渲染不对称圆。对于位置和大小的某些组合,即使大小为正方形,也会呈现出不规则的不对称圆形。
这是您可以轻松复制的怪异图像:
使用以下代码进行生产:
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
的圆,所以现在我只允许我的应用程序中不使用粗圆。如果无法完美渲染,则完全不会渲染。尽管我仍希望此方法有效,但我并未将此答案标记为可接受。
答案 1 :(得分:0)
我可能为时已晚,但仍供将来参考:
不幸的是,Qt 使用贝塞尔曲线绘制椭圆(截至目前,可能很快就会改变),这是椭圆的一个很好的近似值,但并不完美。绘制像素完美的椭圆需要在像素级别手动实现。