Search code examples
imageqtcolorspixelscanline

getting image color information from both RGB32 and indexed type images


I am trying to access the image colors in a QImage.

The method that I found most in docs is based on the scanline function...

I tried and it worked... on RGB32 images. I had surprising - and unpleasant results when using the exact method to get color data for 8 bit indexed or monochrome images.

This was my code:

// note RGBTriple is a struct containing unsigned R, G, B
// rgbImage.pixels is a RGBTriple* array

RGBTriple* pTriple = rgbImage.pixels;
for (int y = 0; y < source.height(); y++)
{
    const unsigned char* pScanLine = source.scanLine(y);
    for (int x = 0; x < source.width(); x++)
    {
         QRgb* color = (QRgb*)pScanLine;
         pTriple->R = qRed(*color);
         pTriple->G = qGreen(*color);
         pTriple->B = qBlue(*color);
         ++pTriple;
         pScanLine += 4;
    }
}

Running the same code with images 8bit indexed or monochrome, I got errors in creating getting colors. The documentation says that scanline is aligned to multiples of 32b - but since that is a multiple of 8 and 2 I didn't think it would be a problem.

Once I found out that I am not getting correct results for all types of input images, I changed it to

RGBTriple* pTriple = rgbImage.pixels;
for (int y = 0; y < source.height(); y++)
{
    for (int x = 0; x < source.width(); x++)
    {
        pTriple->R = qRed(source.pixel(x, y));
        pTriple->G = qGreen(source.pixel(x, y));
        pTriple->B = qBlue(source.pixel(x, y));
        ++pTriple;
    }
}

Works perfectly... I wonder if it is slower or will have other unexpected behavior ? After all, I am using the pixel() function - even on indexed images - to get color information, which actually should be stored differently... that seems like it should fail...

Is there a way to make the first version, using scanline, work for other image types ?

Why does it seem like using scanline to get the data is the preferred method ?


Solution

  • I tried and it worked... on RGB32 images. I had surprising - and unpleasant results when using the exact method to get color data for 8 bit indexed or monochrome images.

    You should not be surprised because the indexed and monochrome images are different formats. The first code snippet you posted is based on the knowledge on how RGB32 (and RGB32 only) is layed out in memory.

    Think about it. In a monochrome image R=G=B. So only one channel need to be saved in memory.

    If your goal is to obtain an rgb image inside rgbImage.pixels use QImage::convertToFormat() :

    QImage source;
    QImage dest =  source.convertToFormat( QImage::Format_RGB888 );
    memcpy(rgbImage.pixels, dest.bits(),dest.byteCount () );