QImage数据对齐

QImage data alignment

的文档

QImage::QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR)

说明参数'data'引用的数据必须是32位对齐的。 http://doc.qt.io/qt-5/qimage.html#QImage-3 但至少不清楚具体是什么意思。我假设,每个像素需要 32 位。但事实并非如此。构建这样的图像是可行的:

uint8_t* rgb = new uint8_t[3 * height * width];
QImage Img(rgb, width, height, QImage::Format_RGB888);

但这令人困惑。当我想从图像中获取像素值时,我想我需要这样做(因为数据是 32 位对齐的,而 Qrgb 是 32 位的):

QRgb*rawPixelData = (QRgb*) Img.bits();
for(uint32_t i = 0; i < (Img.width * Img.height); ++i)
{
  qDebug() << "Red" << qRed(rawPixelData[i]);
  qDebug() << "Green" << qGreen(rawPixelData[i]);
  qDebug() << "Blue" << qBlue(rawPixelData[i]);
}

但这不起作用(导致崩溃)。所以,我假设数据不是 32 位对齐的。那么,数据不是32位对齐的,还是我理解有误?

我假设 "data" 是指使用的字节数组。通过对齐,它们意味着数组的第一个字节将是 32 位对齐的,因此 data % 4 将始终为 0。它不是每个像素的内部对齐,只是包含像素数据的内存块的对齐.

此外,bits() returns 是指向无符号字节的指针,而不是指向 QRgb 的指针。 QRgb 本质上只是一个整数:

typedef unsigned int QRgb;   

我怀疑您遇到了崩溃,因为原始数据是 "compacted"。这意味着如果您的图像只有 RGB 而没有 alpha,它将只使用 24 位或每个像素 3 个字节,因为这将消除 25% 的内存使用开销。结果,您正在偏离实际数据并发生崩溃。

您应该尝试将其迭代为 w * h * 3 无符号字符并为每个下一个像素递增 3,并且您的 rgb 将分别是 i, i+1, i+2.

处的字节

如果您的图像格式是 RGBA,它可能会起作用。

事实上,如果您仔细检查 byteCount,您会发现内部使用的字节数是给定格式的最小字节数:

  QImage img(100, 100, QImage::Format_RGB888);
  qDebug() << img.byteCount(); // 30000 or 3 bytes or 24 bits

  QImage img2(100, 100, QImage::Format_RGB555);
  qDebug() << img2.byteCount(); // 20000 or 2 bytes or 15 bits

  QImage img3(100, 100, QImage::Format_RGBA8888);
  qDebug() << img3.byteCount(); // 40000 or 4 bytes or 32 bits

But it's at least unclear what is meant exactly.

该表达是软件工程术语的一部分,与手头的具体情况无关:它与 Qt、图像或像素无关。

支持Qt的平台上,它具有以下严格含义:

uchar *data = ...;
Q_ASSERT(reinterpret_cast<uintptr_t>(data) & 3 == 0);

或者,在任意的C++17平台上,它具有以下严格含义:

size_t size = ...;
uchar *data = ...;
Q_ASSERT(std::align(4, size, reinterpret_cast<void*&>(data), size) ==
         reinterpret_cast<void*>(data));