2016-12-16 301 views
0

QImage的数据对齐

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

该文档描述了该数据,由参数 '数据' refered,必须是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

我假设通过“数据”它们表示使用的字节数组。通过对齐,它们意味着阵列的第一个字节将是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

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

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