为什么在 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()
来计算文本基线。
我正在使用 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()
来计算文本基线。