2016-12-16 13 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 и альфа, оно будет использовать только 24 бит или 3 байта на пиксель, потому что это устранит 25% -ный объем использования памяти. В результате вы удаляете фактические данные и получаете крах.

Вам следует попробовать повторить его как w * h * 3 unsigned chars и увеличивать на 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));