Reputation: 69
I have a 16 bit grayscale QImage::Format_Grayscale16
of unsigned short
values contiguous in memory. It displays properly on a QLabel
after converting it to a pixmap. I now need to colorize it with a given colortable that maps intensities to a particular RGB value:
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);
Note: The images are actually 12 bit, but are stored the same as a 16 bit image. Hence the 4096 limit for the RGB mapping.
Unfortunately I am having trouble. Firstly, is conversion to the RGB16 format correct? I have posted another question very similar, but for 8 bit grayscale. The Qt doc for setColorTable()
states:
Only monochrome and 8-bit formats.
so I'm assuming I can't use this for my 16 bit image. Is the best course of action maybe to scale down and convert to an 8 bit? Any performance optimaztions would be great as well because the images are supposed to stream in real-time.
Upvotes: 1
Views: 1430
Reputation: 3803
qRgb(int,int,int)
creates an QRgb
which stores 8-bits per channel (while the arguments are ints, they are masked against 0xff). qRgb64(..)
will accept (and use) 16-bit values to create a QRgb64
which has the necessary precision.
Unfortunately, there isn't a QImage::Format_Indexed16
yet (see QTBUG-75536) contributing to why Qt doesn't support color tables directly with 16-bit grayscales. If you don't need the contrast data in the lower 8-bits (or just 4-bits in your case since only the 12 upper bits have real data) and the color table is always the same, converting to Format_Indexed8
and using a color table will be the most straightforward method.
If you do need the contrast data in the lower bits, you'll need to manually scale those 12-bits across the 8-bit per channel RGB. Create a new QImage
with the same width/height and loop through the original data pixel-by-pixel. Gray16Lib is a Qt library with examples of various algorithms that attempt to preserve contrast (disclaimer, I wrote it).
Upvotes: 2
Reputation: 69
One somwhat expensive solution is as follows:
Create a new 8 bit image using convertToFormat(QImage::Format_Grayscale8)
Colorize by creating a QImage of format Indexed8
, setting its colortable, and copying the 8 bit QImage data to this new Indexed8
format image. See my other question for more details.
This works, but if anyone knows a faster method, feel free to respond. There seems to be a lot of copying with this. I already have to traverse the image once to map the 12 bit to the 16 bit range.
Upvotes: 0