3

QImage has a constructor QImage (uchar *data, int width, int height, int bytesPerLine, Format format) that creates a QImage from an existing memory buffer.

Is the order of bytes (uchars) platform-dependent? If I put the values for alpha, red, green, and blue in it with increasing indices, alpha is swapped with blue and red is swapped with green. This indicates a problem with endian-ness.

I now wonder whether the endian-ness is platform-dependent or not. The Qt documentation does not say anything about this.

If it is NOT platform-dependent, I would just change the order of storing the values:

texture[ startIndex + 0 ] = pixelColor.blue();
texture[ startIndex + 1 ] = pixelColor.green();
texture[ startIndex + 2 ] = pixelColor.red();
texture[ startIndex + 3 ] = pixelColor.alpha();

If it is platform-dependent, I would create an array of uint32, store values computed as alpha << 24 | red << 16 | green << 8 | blue, and reinterpret_cast the array before passing it to the QImage() constructor.

Best regards,

Jens

Jens Müller
  • 302
  • 4
  • 13

2 Answers2

2

It depends on the format. Formats that state the total number of bits in a pixel are endian-dependent. Like Format_ARGB32 indicates a 32-bit integer whose highest 8 bits are alpha, which on a little endian machine, the same 8 bits are the last byte in the byte sequence.

Formats with individual bits in the sequence like Format_RGB888 are not endian-dependent. Format_RGB888 says the bytes are arranged in memory in R,G,B order regardless of endian.

To access bytes in the buffer, I would use Q_BYTE_ORDER macro to conditionally compile in the corresponding byte access code, instead of using shifts.

I personally use Format_RGB888 since I don't deal with alpha directly in the image. That saves me the problem of dealing with endian difference.

Stephen Chu
  • 12,724
  • 1
  • 35
  • 46
  • "Formats with individual bits in the sequence like Format_RGB888 are not endian-dependent." It seems `Format_RGB666` would still be endian dependent. It might only be safe to say that if the description includes "byte-ordered" or "halfword-ordered" that the channels actually flow using the stated order in memory, but otherwise they are formed as a full word (and thus flow backwards on a typical x86 endian CPU). `Format_RGB888` explicitly says "byte ordered", whereas `BGR888` does not ‍♀️. – Dwayne Robinson Aug 18 '21 at 03:23
0

From the Qt Docs:

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.

James
  • 24,676
  • 13
  • 84
  • 130
  • Thanks. I would have expected such a warning in the documentation of the enum values of QImage::Format, not the function QImage::scanLine ... – Jens Müller Oct 19 '12 at 20:07