QT QImage, how to extract RGB?
Asked Answered
G

4

13

I want to extract RGB from each pixel in QImage. Ideally, I want to use the img.bits() function.

QImage img;

if( img.load("Red.jpg") )
{
    uchar *bits = img.bits();

    for (int i = 0; i < 12; i++)
    {
        std::cout << (int) bits[i] << std::endl;
    }
}

How to manipulate the returned bits? I expected all red because the picture is a pure red image created in Paint. However, I get 36, 27, 237, 255, 36 etc...

Graves answered 12/9, 2012 at 6:25 Comment(1)
Reading with bits() depends heavily on the image format. Try to convert the format to something more suitable for your scenario, e.g. img = img.convert(QImage::Format_ARGB32). Then the bytes should come out as 0, 255, 0, 0, [loop] if I'm not mistaken.Gunthar
P
17
QImage img( "Red.jpg" );

if ( false == img.isNull() )
{
    QVector<QRgb> v = img.colorTable(); // returns a list of colors contained in the image's color table.

    for ( QVector<QRgb>::const_iterator it = v.begin(), itE = v.end(); it != itE; ++it )
    {
        QColor clrCurrent( *it );
        std::cout << "Red: " << clrCurrent.red()
                  << " Green: " << clrCurrent.green()
                  << " Blue: " << clrCurrent.blue()
                  << " Alpha: " << clrCurrent.alpha()
                  << std::endl;
    }
}

However this example above does returns the color table. Color table does not includes same colors twice. They will be added once in order of appearance.
If you want to get each pixels color, you can use next lines:

for ( int row = 1; row < img.height() + 1; ++row )
    for ( int col = 1; col < img.width() + 1; ++col )
    {
        QColor clrCurrent( img.pixel( row, col ) );

        std::cout << "Pixel at [" << row << "," << col << "] contains color ("
                  << clrCurrent.red() << ", "
                  << clrCurrent.green() << ", "
                  << clrCurrent.blue() << ", "
                  << clrCurrent.alpha() << ")."
                  << std::endl;
    }
Petie answered 12/9, 2012 at 7:8 Comment(4)
Why did you start from row = 1, not row = 0?Graves
Cause I was remembering that image or pixmap starts indexing from 1, not 0. Probably mistaking. Did you tried it? Starts from 0 or what?Petie
Tried it on QT5. row and col should be in range from 0 to width-1/height-1. And also you mixed up width() and height() in for loops.Looker
Qt documentation says that QImage::pixel() / setPixel() are slow. It recommends you to use bits() or scanLine() (and their respective const versions) if you plan to process a great deal of pixels.Trude
U
6

Reference for bits() says:

Returns a pointer to the first pixel data. This is equivalent to scanLine(0).

So if you check reference for scanLine()

If you are accessing 32-bpp image data, cast the returned pointer to QRgb* (QRgb has a 32-bit size) and use it to read/write the pixel value. You cannot use the uchar* pointer directly, because the pixel format depends on the byte order on the underlying platform. Use qRed(), qGreen(), qBlue(), and qAlpha() to access the pixels.

One other option would probably be pixel() member function.

Hope that helps.

Unrestrained answered 12/9, 2012 at 6:44 Comment(0)
C
4

One of the problems with using the bits() function is that you need to know the format of the original image. You should convert it to RGB by using convertToFormat.

img = img.convertToFormat(QImage::Format_RGB888);

Now, when you call bits(), the data will be in the RGB format with the proper data alignment.

uchar *bits = img.bits();

for (int i = 0; i < (img.width() * img.height() * 3); i++)
{
    std::cout << (int) bits[i] << std::endl;
}
Congress answered 12/9, 2012 at 20:23 Comment(5)
fyi: you can cast img.bits() to a pointer of type QRgb. So you doesn't need to know the type of the image. Just iterate over each pixel and use qRed(), qGreen(), qBlue...and so onAcorn
@501-notimplemented how do you cast it? I'm trrying const QRgb *rawPixelData = static_cast<const QRgb *>(pixelSource.constBits()); but apparently it's an invalid static cast...Ousel
hi @Troyseph, you can use QRgb *rawPixelData= (QRgb*)(pixelSource.bits()) without static_cast.Acorn
@501-notimplemented C style cast... gross =P doesn't that end up being a reinterpret_cast?Ousel
it must be reinterpret_cast. So use C-style cast!Brant
H
0

In Qt 5.6 was introduced QColor QImage::pixelColor(int x, int y) method, so you can directly get color information from image pixel.

Howdy answered 20/6, 2020 at 8:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.