I have some legacy code that was writing to a NITF file to display some images. In the legacy code, it appears as if there was a LUT being used, and there was a section of code that wrote out a row at a time to the NITF file , and the values of that row were calculated like so:
// convert RGB to LUT values
unsigned char *lutData = new unsigned char[numBytes/3];
for (unsigned j = 0 ; j < numBytes/3 ; j++)
lutData[j] = (unsigned char) stuff;
Where data was my original array of unsigned chars.
So now I am try开发者_JAVA技巧ing to take that data array and output it into a QImage in my GUI.
It would seem to me in the NITF, there was a block of LUT data that was "rows x cols" in size, right? So I created an array of that lut data:
unsigned char *lutData = new unsigned char[imwidth * imheight];
QImage *qi = new QImage(imwidth,imheight, QImage::Format_Indexed8);
for (int i = 0 ; i < imheight ; i++)
{
#pragma omp parallel for
for (int j = 0 ; j < imwidth ; j++)
{
lutData[i*imwidth + j] = stuff;
}
}
and then I tried to populate the qimage like this:
for (int i = 0 ; i < imheight ; i++)
{
#pragma omp parallel for
for (int j = 0 ; j < imwidth ; j++)
{
qi->setPixel(j,i,qRgb(lutData[i*imwidth + j],lutData[i*imwidth + j],lutData[i*imwidth + j]));
}
}
However, this seems to more or less just give me a grayscale image, instead of my actual data.
What am I doing wrong?
Thanks!
The qRgb constructor looks like this:
qRgb(int r, int g, int b)
You're passing in the same value (lutData[i*imwidth + j]
) for all three colors, so you'll end up with a greyscale image.
Now, qRgb is just a typedef
ed unsigned int
, so if you store your colors in that format (RGB32 / ARGB32), you can just call:
qi->setPixel(j, i, lutData[i*imwidth + j])
But you might want to look into using QImage's built-in lookup table (aka color table) support - it might end up being as simple as:
QImage image(data, imwidth, imheight, QImage::Format_Indexed8);
QVector<QRgb> colorTable;
// Translate each color in lutData to a QRgb and push it onto colorTable;
image.setColorTable(colorTable);
Hope this helps!
Update: For reference purposes, here's the test code I used to try out QImage in indexed color mode (compiles without warnings with g++ - just remember to link to -lQtCore and -lQtGui):
#include <QtCore/QVector>
#include <QtGui/QApplication>
#include <QtGui/QImage>
#include <QtGui/QLabel>
#include <QtGui/QPixmap>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
unsigned char indices[1024];
for(int i = 0; i < 1024; ++i)
{
indices[i] = qrand() & 0x0f;
}
QVector<QRgb> ctable;
for(int i = 0; i < 16; ++i)
{
ctable.append(qRgb(qrand() & 0xff, qrand() & 0xff, qrand() & 0xff));
}
QImage image(indices, 32, 32, QImage::Format_Indexed8);
image.setColorTable(ctable);
QLabel label;
label.setPixmap(QPixmap::fromImage(image));
label.show();
return app.exec();
}
Very interesting image compression. Here's my try to convert a RGB888 image into a Index8 with your function:
QImage image8(image.size(), QImage::Format_Indexed8);
QVector<QRgb> lut(256);
for(int i=0;i<image888.height();++i) {
const uchar * p = image888.bits() + image888.bytesPerLine()*i;
uchar * q = image8.bits() + image8.bytesPerLine()*i;
for(int j=0;j<image.width();++j, p+=3) {
QRgb c = qRgb(p[0], p[1], p[2]);
int n = qRed(c)/51*36 + qGreen(c)/51*6+qBlue(c)/51;
lut[n] = c;
*q++ = n;
}
}
image8.setColorTable(lut);
It basically fills up the 8-bit color table as it converts from 888 to 8-bit data. For better result, you can accumulate the RGB values at an index, then average the values before putting them into the color table. It can also use some optimization on walking the image buffer.
精彩评论