Reputation: 487
I'm loading two separate images, one png one jpg, into separate QImages using PyQt4 (Linux, Windows, doesn't matter). The images are both 640x480.
self.image1 = QtGui.QImage('image1.png');
self.image2 = QtGui.QImage('image2.jpg');
When I drawText onto each (again separately) with the following code, the resulting text is vastly different in size and placement.
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()
Each image, which is modified with the ImageOverlay() call, is then loaded into a QLabel and displayed in a simple grid layout.
The rendering is completely different:
However, if I re-set the font-size by pixel (as opposed to points), it appears to work as I would expect:
self.font = QtGui.QFont('Sans', 16)
self.font.setPixelSize(16)
I suspect it has to do with an attribute of the QImage that is suggesting some type of context with which to render the text, but I have not been able to find a definitive reason why this is happening.
Can anyone shed some light on why this happens or, if possible, point me to some documentation that describes this behavior?
Upvotes: 0
Views: 1041
Reputation: 69012
QtGui.QFontMetrics(self.font)
(with a font not created for a specific paint device) creates a font metric suitable for you display resolution, that means it uses the dpi value of your display when converting between sizes in points and pixels.
When you're drawing text on a QPaintDevice
(in your case a QImage
), the painter uses a font metric based on that paint devices' resolution. You can access this metric using the painters' fontMetrics()
property, or by using the QFontMetrics(font, paintDevice)
constructor.
If you compare the two images' image.dotsPerMeterX()
and image.dotsPerMeterY()
values (or open them in an image editor and check the resolution there), I'm sure you'll see different values, meaning the image resoltion from their metadata is different, that's why the rendered text size is different.
So if you want the text size to be the same in pixels, stick with font.setPixelSize()
, if you're ok with the text size being set relative to the images' dpi, use a font size in points but use painter.fontMetrics().ascent()
to calculate the text baseline.
Upvotes: 2