Search code examples
qtmaskqimageqpixmap

how to modify pixels of QBitmap


I want to work with masks on a QImage. To handle the mask, I have a QBitmap. Now I'm looking for a fast way to do this things:

  1. Invert the Bits of the mask
  2. Set pixels of the mask to a new value

is there a fast way to do this? Or can I only use a QPainter Object to modify the QBitmap?

Greetings


Solution

  • Your best bet is to use QImage with the format set to QImage::Format_Mono. This way you create a 1-bit per pixel image you can use as a mask.

    1. For inverting the pixels, use the invertPixels method.
    2. QImage bits can be accessed using the bits or scanLine methods.

    To use the QImage as a mask, you'll have to convert it to a QPixmap first:

    QPixmap mask = QPixmap::fromImage(img);
    painter.setClipRegion(QRegion(mask));
    

    Since QImage::Format_Mono encodes the pixels MSB first (means first pixel will be stored in most significant bit of the first byte) with 8 pixels/byte, you'll need some bit-magic to access the correct bit for the given x/y position:

    int GetPixel(const QImage& img, const int x, const int y) const
    {
        const uchar mask = 0x80 >> (x % 8);
        return img.scanLine(y)[x / 8] & mask ? 1 : 0;
    }
    
    void SetPixel(QImage& img, const int x, const int y, const int pixel)
    {
        const uchar mask = 0x80 >> (x % 8);
        if (pixel)
            img.scanLine(y)[x / 8] |= mask;
        else
            img.scanLine(y)[x / 8] &= ~mask;
    }
    

    Of course, don't use a function like SetPixel when you're manipulating a lot of pixels on the same row, as you don't want to lookup scanLine(y) for each pixel. Be creative!