neosettler
neosettler

Reputation: 271

OpenEXR to QImage convertion

GetPixels() is from an EXR image loaded with FreeImage library (96-bit : 3 x 32-bit IEEE floating point). The idea is to convert the pixel data to a QImage::Format_RGB888.

Edit: I used Barcelona Rooftops

Here is what I've got so far:

uint l_h = m_ZImage->GetHeight();
uint l_w = m_ZImage->GetWidth();
float *l_data = (float*)m_ZImage->GetPixels();
m_QImage = QImage(l_w, l_h, QImage::Format_RGB888);
uchar *l_pixels = m_QImage.bits();

for (uint i = 0; i < l_h; ++i)
{
    for (uint j = 0; j < l_w; ++j)
    {
        uint l_id = (i * l_w) + j;
        l_pixels[l_id] = uchar(l_data[l_id] * 255); l_id++;
        l_pixels[l_id] = uchar(l_data[l_id] * 255); l_id++;
        l_pixels[l_id] = uchar(l_data[l_id] * 255);
    }
}

While the top third of the image is correct, the bottom 2/3 is black. I must be missing something very obvious but I'm having a hard time figuring it out!

Upvotes: 0

Views: 234

Answers (2)

Allan Jensen
Allan Jensen

Reputation: 564

I would use std::round(l_data[i] * 255.f)

Note also that QImages might pad each scan-line to 32bit. So instead of accessing QImage::bits(), I would suggest accessing QImage::scanline(y) (or alternatively bits combined with bytesPerLine()).

Upvotes: 0

neosettler
neosettler

Reputation: 271

Oh my, I forgot to take the channel count into account. Here is the simplified version:

uint l_h = m_ZImage->GetHeight();
uint l_w = m_ZImage->GetWidth();
uint l_count = l_w * l_h * m_ZImage->GetChannelCount();
float *l_data = reinterpret_cast<float*>(m_ZImage->GetPixels());
m_QImage = QImage(l_w, l_h, QImage::Format_RGB888);
uchar *l_pixels = m_QImage.bits();

for (uint i = 0; i < l_count; ++i)
{
    l_pixels[i] = ZMath::ClampToByte(l_data[i] * 255); /// Edit
}

On the other hand, the whites are incorrect as there is an off the chart rainbow effect. Piling up on the original question. Is there a convention to convert image data from 32bits to 8bits?

Upvotes: 2

Related Questions