Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-997

No equivalent of cast to QRgb* when accessing QImage.scanLine result

    Details

    • Type: Bug
    • Status: Reported
    • Priority: P3: Somewhat important
    • Resolution: Unresolved
    • Affects Version/s: 5.12.2
    • Fix Version/s: None
    • Component/s: PySide
    • Labels:
      None
    • Platform/s:
      All

      Description

      When using QImage.scanLine to access a QImage scanline by scanline, there's no way to cast that result to QRgb* to access it in a byte-order-independent manner like the C++ docs says:

      Warning: If you are accessing 32-bpp image data, cast the returned pointer to QRgb* (QRgb has a 32-bit size) and use it to read/write the pixel value. You cannot use the uchar* pointer directly, because the pixel format depends on the byte order on the underlying platform. Use qRed(), qGreen(), qBlue(), and qAlpha() to access the pixels.

      Would be good if there was some way to get a view of the bytes as an array of ints instead, that can be used with qRed(..), qGreen(..) et.c.

      Bonus of course if it's still fast, since that's one of the points of using scanLine in the first place

      To clarify, consider this C++ snippet:

      #include <QImage>
      #include <QColor>
      #include <QDebug>
      
      int main(int, char *[]) {
          QImage image(2, 2, QImage::Format_RGB32);
          image.setPixel(0, 0, QColor(Qt::red).rgb());
          image.setPixel(1, 0, QColor(Qt::green).rgb());
          image.setPixel(0, 1, QColor(Qt::blue).rgb());
          image.setPixel(1, 1, QColor(Qt::darkBlue).rgb());
      
          for (int y = 0; y < image.height(); ++y) {
              const auto scanLine = (QRgb *)image.scanLine(y);
              for (int x = 0; x < image.width(); ++x) {
                  const auto pixel = scanLine[x];
                  qDebug() << "pixel at" << x << y << "is"
                      << "r =" << qRed(pixel)
                      << "g =" << qGreen(pixel)
                      << "b =" << qBlue(pixel);
              }
          }
      
          return 0;
      }
      

      And prints:

      pixel at 0 0 is r = 255 g = 0 b = 0
      pixel at 1 0 is r = 0 g = 255 b = 0
      pixel at 0 1 is r = 0 g = 0 b = 255
      pixel at 1 1 is r = 0 g = 0 b = 128
      

      Here's the "same" in Python:

      from PySide2.QtCore import Qt
      from PySide2.QtGui import QImage, qRed, qGreen, qBlue, QColor
      
      image = QImage(2, 2, QImage.Format_RGB32)
      image.setPixel(0, 0, QColor(Qt.red).rgb())
      image.setPixel(1, 0, QColor(Qt.green).rgb())
      image.setPixel(0, 1, QColor(Qt.blue).rgb())
      image.setPixel(1, 1, QColor(Qt.darkBlue).rgb())
      
      for y in range(image.height()):
          scanLine = image.scanLine(y)
          for x in range(image.width()):
              pixel = scanLine[x]
              print('pixel at {},{} is r = {}, g = {}, b = {}'.format(
      x, y, qRed(pixel), qGreen(pixel), qBlue(pixel)))
      

      And it prints.

      pixel at 0,0 is r = 0, g = 0, b = 0
      pixel at 1,0 is r = 0, g = 0, b = 0
      pixel at 0,1 is r = 0, g = 0, b = 255
      pixel at 1,1 is r = 0, g = 0, b = 0
      

      This was just to illustrate the point. The result is obviously wrong, because the scan line has not been cast to an array of ints, it's still an array of bytes. One can access the individual bytes of course and take out the r,g,b components that way, but it's not portable as the byte-order is platform dependent.

        Attachments

        1. make-apidoc.log.gz
          442 kB
        2. make-apidoc-second-attempt.log.gz
          474 kB
        3. pyside2-build-second-attempt.log.gz
          49 kB
        4. qimage.png
          qimage.png
          28 kB
        5. result.png
          result.png
          128 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

            • Assignee:
              crmaurei Cristian Maureira-Fredes
              Reporter:
              estan Elvis Stansvik
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:

                Gerrit Reviews

                There are no open Gerrit changes