Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
6.8.2
-
-
3d389ee2a (dev), 87e53579e (6.9), d144adbb5 (6.8), ee4b2d1e8 (tqtc/lts-6.5)
Description
The method of concern is "initBitMapInfoHeader":
https://github.com/qt/qtbase/blob/dev/src/gui/image/qpixmap_win.cpp#L39C20-L39C40
where it calculates "bytesPerLine" by
const DWORD bytesPerLine = pad4(DWORD(width) * bitCount / 8);
It is a problem when the argument passed to pad4 is of such value of "4n+x" where n is integer and x is decimal, i.e. some multiple of 4 plus a decimal part. Taking width of 165 and bitCount of 1 as example. That method call becomes "pad4(165 / 8)" which then becomes "pad4(20)" while the exact value is "pad4(20.625)". But since it is a division between 2 integers, so 0.625 is dropped. As a result, the padding of "20.625", which is value larger than 20, is 20. The correct value should be 24.
A solution can be using double in calculation and then ceiling, like:
const DWORD bytesPerLine = pad4(qCeil(DWORD(width) * bitCount / 8.0));
Then 20.625 stays as it is then rounded to 21. The result will be correct 24.
Update: the original reporter says that the error can come from QImage::toHBITMAP (unfortunately no reproducer but only snippet):
void paintBitmap(HDC hdc, QWindow* pWindow, CGroupBox* pGrpbx, const QSize& size)
{
HDC hdcMem = CreateCompatibleDC(hdc);
QRect holerect = calculateHoleArea(pGrpbx);
QColor backgrColor = pGrpbx->palette().window().color();
QPixmap pixmap = createPixmap(pGrpbx, pWindow, backgrColor, size, holerect);
HBITMAP hbitmap = pixmap.toImage().toHBITMAP();
QImage image = pixmap.createMaskFromColor(holeColor, Qt::MaskInColor).toImage();
HBITMAP hmask = image.toHBITMAP();
......
As far as I see, this part:
QImage image = pixmap.createMaskFromColor(holeColor, Qt::MaskInColor).toImage(); HBITMAP hmask = image.toHBITMAP();
indeed may lead to error. QPixmap::createMaskFromColor returns a QBitmap which is monochrome, i.e. 1 bit count per pixel. That is not divisible by 8 and may lead to integer division issue.