QImage数据对齐

时间:2016-12-16 12:51:07

标签: qt alignment qimage

的文档

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位对齐,或者我理解错了?

2 个答案:

答案 0 :(得分:2)

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

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

typedef unsigned int QRgb;   

我怀疑你是因为原始数据被“压缩”而崩溃。这意味着如果您的图像只有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

答案 1 :(得分:1)

  

但它至少不清楚究竟是什么意思。

该表达式是软件工程白话的一部分,与手头的具体情况无关:它与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));