Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-133782

Mistakenly rounding down "bytesPerLine" for QPixmap

    XMLWordPrintable

Details

    • Windows
    • 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.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            vgt Eirik Aavitsland
            luqiaochen Luqiao Chen
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes