QImage::fill(Qt::red) always black?

honiahaka10 picture honiahaka10 · Sep 17, 2015 · Viewed 7.2k times · Source

I am trying to figure out, how QImage works. For start i just want to create a 400x400 pixel QImage and try to fill it red. Well the QImage is filled but black... Also i want to create a monochromatic QImage. One color should be transparent and the other any other (for example: red). How can i do this? I tried it with setcolor, but this doesn't seem to work...

scene = new QGraphicsScene(this);
ui.graphicsView->setScene(scene);
QImage *image = new QImage(400, 400, QImage::Format_Indexed8); //QImage::Format_Mono);
image->fill(Qt::red);
//image->setColor(1, Qt::transparent);
//image->setColor(0, Qt::red);
scene->addPixmap(QPixmap::fromImage(*image));

Answer

kefir500 picture kefir500 · Sep 17, 2015

Short answer:

Use Format_RGB32 instead of Format_Indexed8 in your QImage constructor.

Detailed answer:

Format_Indexed8 uses the manually defined color table where each index represents a color. You have to create your own color table for your image:

QVector<QRgb> color_table;
for (int i = 0; i < 256; ++i) {
    color_table.push_back(qRgb(i, i, i)); // Fill the color table with B&W shades
}
image->setColorTable(color_table);

Also you can manually set each index for the current color table:

image->setColorCount(4); // How many colors will be used for this image
image->setColor(0, qRgb(255, 0, 0));   // Set index #0 to red
image->setColor(1, qRgb(0, 0, 255));   // Set index #1 to blue
image->setColor(2, qRgb(0, 0, 0));     // Set index #2 to black
image->setColor(3, qRgb(255, 255, 0)); // Set index #3 to yellow
image->fill(1); // Fill the image with color at index #1 (blue)

As you can see, Format_Indexed8 pixel values represent not RGB colors but the index values (which in turn represent the colors you set in the color table).

Format_Mono is another format which also uses the color table (note that only two colors are allowed in it).

Additional answer:

One color should be transparent and the other any other (for example: red).

If I correctly understood you, this code will do what you want:

// Create a 256x256 bicolor image which will use the indexed color table:

QImage *image = new QImage(256, 256, QImage::Format_Mono);

// Manually set our colors for the color table:

image->setColorCount(2);
image->setColor(0, qRgba(255, 0, 0, 255)); // Index #0 = Red
image->setColor(1, qRgba(0, 0, 0, 0));     // Index #1 = Transparent

// Testing - Fill the image with pixels:

for (short x = 0; x < 256; ++x) {
    for (short y = 0; y < 256; ++y) {
        if (y < 128) {
            // Fill the part of the image with red color (#0)
            image->setPixel(x, y, 0);
        }
        else {
            // Fill the part of the image with transparent color (#1)
            image->setPixel(x, y, 1);
        }
    }
}