【问题标题】:QImage data alignmentQImage数据对齐
【发布时间】:2016-12-20 01:56:40
【问题描述】:

文档

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 位对齐的,还是我理解错了?

【问题讨论】:

    标签: qt alignment qimage


    【解决方案1】:

    我假设“数据”是指使用的字节数组。对齐意味着数组的第一个字节将是 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
    

    【讨论】:

      【解决方案2】:

      但至少不清楚具体是什么意思。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-04
        • 2011-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多