PDA

View Full Version : Darken QPixmap



FlyDoodle
18th September 2019, 15:45
Hello !

I want to know is it possible to darken my images inside the Qt ( using a method ) or do i have to change the whole image with the darken one i made in Paint program?
I use :



Player::Player(QGraphicsPixmapItem *parent)
{
setPixmap(QPixmap(":/Images/PlayerMoveDownStill.png"));

}


I want something like this for example:
13264

d_stranz
18th September 2019, 17:30
You could read every pixel from the pixmap (easier to do if you convert the QPixmap into a QImage first), multiply each R, G, and B value by some fraction < 1, then replace it in the image.

For example, if you used a 90% factor (to get an image 10% darker), a white pixel with R = 255, G = 255, and B = 255 would become a slightly grey pixel with 255 -> 255 * 0.9 = 230. This might not give you the best effect, but it could be done at run time and you would not have to draw an entirely new set of images.

FlyDoodle
18th September 2019, 21:01
Yes something like that is what i was looking for, tho i have one more question, could you please tell me how do i convert QPixmap into QImage ? :3 I'm still learning about Qt and reading Documentation and understanding it is quite troublesome for me.

FlyDoodle
19th September 2019, 05:39
Actually i think i've found how to convert it to QImage, thank you

FlyDoodle
19th September 2019, 16:42
I thought i knew how to do it when i was traveling with a train but now that i tried doing it it doesn't work... Can someone please tell me how to do it properly, or what am i missing here... I tried doing something and the picture stay the same :


Player::Player(QGraphicsPixmapItem *parent)
{
QPixmap *t = new QPixmap(":/Images/PlayerMoveDownStill.png");
setPixmap(*t);
//setOpacity(0.5);
setPos(game->width()/2-this->boundingRect().width()/2,game->height()/2-this->boundingRect().height()/2);

QImage tmp = t->toImage();
QColor color;

for(int i=0;i<tmp.height();i++){
for(int k=0;k<tmp.width();k++){
//color.setRgb(255*0.5,255*0.5,255*0.5);
color.setRgb(tmp.pixel(k,i));
//color.setAlpha(tmp.pixelColor(k,i).alpha());
color.setRgb(color.red()*0.5,color.blue()*0.5,colo r.green()*0.5);
tmp.setPixelColor(k,i,color);
}
}

t->fromImage(tmp);
}

d_stranz
19th September 2019, 18:38
First, you do not need to create the QPixmap using "new". The call to setPixmap() will make a copy, so you can simply create the pixmap on the stack. As your code is written now, the QPixmap you create is a memory leak.

Second, you should call setPixmap() after you modify the image. Because setPixmap() is making a copy, your code sets it with the original, unmodified pixmap.

Fix your code like this:



Player::Player(QGraphicsPixmapItem *parent)
{
// Load the QImage directly from the resource. No need to create a QPixmap first
QImage tmp( ":/Images/PlayerMoveDownStill.png", "PNG" );

for(int i=0;i<tmp.height();i++)
{
for(int k=0;k<tmp.width();k++)
{
QColor color( tmp.pixelColor( k, i ) );
color.setRgb(color.red()*0.5,color.blue()*0.5,colo r.green()*0.5);
tmp.setPixelColor(k,i,color);
}
}

// Now, convert the image to a pixmap and set it on the graphics object
QPixmap t = QPixmap::fromImage( tmp );
setPixmap( t );
setPos(game->width()/2-this->boundingRect().width()/2,game->height()/2-this->boundingRect().height()/2);
}

FlyDoodle
19th September 2019, 19:31
Normally i just do this when using QPixmap :

setPixmap(QPixmap("filename"));

tho i didn't know setPixmap makes a copy of QPixmap, thank you for that.
And i tried your code and it worked well, thank you but i have one more problem. First picture was transparent but this one after converting it back to Pixmap seems to not be ( background is black ) and i looked for a solution on web and i found out that this line of code is supposed to make it transparent :

tmp.fill(qRgba(0,0,0,0));

But Format_RGB32 doesn't support transparency and i don't know how to set the image to a different format ( Format_ARGB32 ), tried putting it into constructor but none of the constructors have filename and format type as paramaters.
This is how the darken image looks :
13265

d_stranz
19th September 2019, 21:25
In the code that modifies the QImage pixel, check first to see if the alpha channel is zero. If it is, do not modify the pixel. And when setting the pixel, be sure to copy the alpha channel, not just RGB.



Player::Player(QGraphicsPixmapItem *parent)
{
// Load the QImage directly from the resource. No need to create a QPixmap first
QImage tmp( ":/Images/PlayerMoveDownStill.png", "PNG" );

for(int i=0;i<tmp.height();i++)
{
for(int k=0;k<tmp.width();k++)
{
QColor color( tmp.pixel( k, i ) ); // changed this from pixelColor() to ensure alpha is copied
if ( color.alpha() != 0 ) // modify only the pixels with non-zero alpha
{
color.setRgb(color.red()*0.5,color.blue()*0.5,colo r.green()*0.5, color.alpha() );
tmp.setPixelColor(k,i,color);
}
}
}

// Now, convert the image to a pixmap and set it on the graphics object
QPixmap t = QPixmap::fromImage( tmp );
setPixmap( t );
setPos(game->width()/2-this->boundingRect().width()/2,game->height()/2-this->boundingRect().height()/2);
}

FlyDoodle
20th September 2019, 19:13
Thanks for the reply and showing me how to do it, unfortunately it didn't work but i tried couple of things and instead of:

if ( color.alpha() != 0 )

I did :

if ( tmp.pixel(k,i) != 0)

And now it works just fine :D :
13266

Thank you for taking your time and helping me out with this, and everything so far, i really appreciate it !!! Now i can implement day and night into my game :o

d_stranz
20th September 2019, 21:34
unfortunately it didn't work

Strange. Maybe constructing a QColor from a QRgb value doesn't copy the alpha channel, so it gets set to 255 by default. Obviously QImage::pixel() returns the alpha channel along with the rgb channels, because you would not be able to compare it to zero otherwise. I learned something too.