Как раскрасить 16-битное изображение в градациях серого с помощью Qt?

У меня есть 16-битные оттенки серого QImage::Format_Grayscale16 из unsigned short значений, смежных в памяти. Он правильно отображается на QLabel после преобразования его в растровое изображение. Теперь мне нужно раскрасить его с помощью заданной таблицы цветов, которая сопоставляет интенсивности с конкретным значением RGB:

QVector<QRgb> table_16;
for (double i = 0; i < 4096; ++i) {

    table_16.append(qRgb(
        (int)std::round(std::clamp( -4 * std::abs(i - 4095.0 * 3 / 4) + 4095.0 * 3 / 2, 0.0, 4095.0)),
        (int)std::round(std::clamp(-4 * std::abs(i - 4095.0 * 2 / 4) + 4095.0 * 3 / 2, 0.0, 4095.0)),
        (int)std::round(std::clamp( -4 * std::abs(i - 4095.0 * 1 / 4) + 4095.0 * 3 / 2, 0.0, 4095.0))));

}

table_16[0] = qRgb(4095, 4095, 4095);

Примечание. Изображения на самом деле 12-битные, но хранятся так же, как и 16-битные изображения. Отсюда ограничение 4096 для отображения RGB.

К сожалению, у меня проблемы. Во-первых, корректно ли преобразование в формат RGB16? Я разместил еще один очень похожий вопрос, но для 8-битных оттенков серого. Документ Qt для setColorTable() гласит:

Только монохромные и 8-битные форматы.

поэтому я предполагаю, что не могу использовать это для своего 16-битного изображения. Может быть, лучший способ действий - уменьшить масштаб и преобразовать в 8-битный? Любая оптимизация производительности также была бы отличной, потому что изображения должны передаваться в режиме реального времени.


person Joe Natal    schedule 15.01.2020    source источник


Ответы (2)


qRgb(int,int,int) создает QRgb, в котором хранится 8 бит на канал (в то время как аргументы представляют собой целые числа, они замаскированы под 0xff). qRgb64(..) будет принимать (и использовать) 16-битные значения для создания QRgb64 с необходимой точностью.

К сожалению, пока нет QImage::Format_Indexed16 (см. QTBUG-75536), объясняющего, почему Qt не поддерживает таблицы цветов напрямую с 16-битными оттенками серого. Если вам не нужны данные контраста в младших 8 битах (или только 4 бита в вашем случае, поскольку только 12 старших битов имеют реальные данные) и таблица цветов всегда одна и та же, преобразование в Format_Indexed8 и использование цвета table будет самым простым методом.

Если вам нужны данные о контрасте в младших битах, вам нужно вручную масштабировать эти 12 бит по 8 битам на канал RGB. Создайте новый QImage с той же шириной/высотой и прокрутите исходные данные попиксельно. Gray16Lib — это библиотека Qt с примерами различных алгоритмов, которые пытаются сохранить контраст (отказ от ответственности, это я написал).

person Linville    schedule 16.01.2020

Одно довольно дорогое решение выглядит следующим образом:

Создайте новый 8-битный образ, используя convertToFormat(QImage::Format_Grayscale8)

Раскрасьте, создав QImage формата Indexed8, установив его таблицу цветов и скопировав 8-битные данные QImage в это новое изображение формата Indexed8. Смотрите мой другой вопрос для более подробной информации.

Это работает, но если кто-то знает более быстрый метод, не стесняйтесь отвечать. Кажется, здесь много копий. Мне уже нужно пройти по изображению один раз, чтобы сопоставить 12-битный диапазон с 16-битным.

person Joe Natal    schedule 15.01.2020