为什么在 QImage 上使用 drawText 时 QPainter 似乎无法预测地缩放字体?

Why does QPainter seem to scale fonts unpredictably when using drawText on a QImage?

我正在使用 PyQt4 将两张单独的图像(一张 png 一张 jpg)加载到单独的 QImage 中(Linux、Windows,无关紧要)。图片均为 640x480。

self.image1 = QtGui.QImage('image1.png');
self.image2 = QtGui.QImage('image2.jpg');

当我使用以下代码将文本绘制到每个(再次分别)上时,生成的文本在大小和位置上有很大不同。

def ImageOverlay( self, img, text):

    #img is a QImage
    #ImageOverlay is called many times so font creation is done once.

    if self.font is None:
        self.font = QtGui.QFont('Sans',16)
        metrics = QtGui.QFontMetrics(self.font)
        self.fontheight = metrics.ascent();

    painter = QtGui.QPainter()
    painter.begin(img)
    painter.setOpacity(1.0)
    painter.setPen(QtCore.Qt.black)
    painter.setFont(self.font)
    painter.drawText( 1,self.fontheight, text )
    painter.end()

使用 ImageOverlay() 调用修改的每个图像随后被加载到 QLabel 中并以简单的网格布局显示。

渲染完全不同:

但是,如果我按像素(而不是点)重新设置字体大小,它似乎可以正常工作:

    self.font = QtGui.QFont('Sans', 16)
    self.font.setPixelSize(16)

我怀疑它与 QImage 的一个属性有关,该属性建议使用某种类型的上下文来呈现文本,但我无法找到发生这种情况的确切原因。

任何人都可以阐明为什么会发生这种情况,或者如果可能的话,请指出一些描述此行为的文档?

QtGui.QFontMetrics(self.font) (with a font not created for a specific paint device) 创建适合您显示分辨率的字体规格,这意味着它在点和像素大小之间转换时使用显示器的 dpi 值。

当您在 QPaintDevice(在您的情况下是 QImage)上绘制文本时,画家使用基于该绘画设备分辨率的字体规格。您可以使用画家的 fontMetrics() property, or by using the QFontMetrics(font, paintDevice) 构造函数访问此指标。

如果您比较两个图像的 image.dotsPerMeterX() and image.dotsPerMeterY() 值(或在图像编辑器中打开它们并检查那里的分辨率),我相信您会看到不同的值,这意味着它们的图像分辨率元数据不同,这就是呈现的文本大小不同的原因。

因此,如果您希望文本大小以像素为单位相同,请坚持使用 font.setPixelSize(),如果您同意相对于图像的 dpi 设置文本大小,则使用字体大小点,但使用 painter.fontMetrics().ascent() 来计算文本基线。