Background for images with alpha channel



  • I'm making an image viewer, and i have made it shows animated images, but i can't find the way to set the background for those that have an alpha channel. It's easy to make it with static images, using qpainter, but i don't know how to do it with animated images.

    by the way, i'm learning both Qt and english, so please be patient :-P



  • Please, show you code, how you work with QMovie, and I don't understand you need "Alpha background" as in Title or "background for images with alpha channel" as in topic body? :)



  • On a side note, QMovie is perfectly paintable with QPainter (you obtain the current frame with currentImage() or currentPixmap()).



  • @QMovie movie = new QMovie (file->absoluteFilePath());
    if (!movie->isValid()) {
    qDebug()<<tr("Could not open %1 image").arg(file->absoluteFilePath());
    return;
    }

    movie->start();
    imageLabel->setMovie(movie);
    imageLabel->resize(movie->scaledSize());@

    that's the code.

    how do you suggest i use QPainter?



  • imageLabel has type QLabel, right? QLabel is subclass of QWidget, QWidget is subclass of QPaintDevice.
    Use QPainter for imageLabel



  • So, I think Vass meant to overwrite "paintEvent":http://doc.qt.nokia.com/4.7/qwidget.html#paintEvent and do the painting by yourselve instead of let QImageLabel do the painting for you.



  • yes, it's a QLabel Object. Ok, i understand what you say but don't know how to use QPainter for imageLabel



  • If you do the painting on your own, you overwrite paint event like the following code:

    @
    void myWidgetClass::paintEvent(QPaintEvent*)
    {
    QPainter paint(this);
    paint.drawImage(rect(), myMove.currentImage());
    }
    @



  • Gerolf It seems to me what I with you said about different things. As I understand samkpo has movie with alpha channel, and He want set background under this movie. You said about animate background for something with use Qmovie.



  • yes, that's what i want



  • what exactly?



  • Ok, sorry, then I misunderstood....



  • i have a movie with alpha channel and i want to set a background under this movie



  • This code makes the background red. It's important to call setAutoFillBackground(true) on the label, otherwise the background will not be changed!

    @
    QPalette pal = ui->label->palette();
    pal.setBrush(QPalette::Window, Qt::red);
    ui->label->setPalette(pal);
    ui->label->setAutoFillBackground(true);
    @



  • You need to subclass QLabel (or simply write a new widget from scratch) and in its paintEvent paint the background and then the current QMovie frame; or you can enable autoFillBackground and change the label's background palette. :)



  • bq. Vass wrote
    Gerolf It seems to me what I with you said about different things. As I understand samkpo has movie with alpha channel, and He want set background under this movie. You said about animate background for something with use Qmovie.

    But then you can just paint the background beffore drawing the move:

    @
    void myWidgetClass::paintEvent(QPaintEvent*)
    {
    QPainter paint(this);
    painter.draw... // draw the background here
    paint.drawImage(rect(), myMove.currentImage());
    }
    @

    Or position a label or widget with the needed background exactly below the imageLabel. (so position one widget with setgeometry or make obne label a child of the other one). Or does QLabel not draw the movie with transparent background?



  • Gerolf, ok, there's always more than one way to achieve things, but setting the background palette and autoFillBackground should be enough in this case :-)



  • Gerolf I don't know, I think what enough lay one widget under this. Or you are right, call set background before current frame paint.



  • nop, the palette stuff didn't work, when i call setMovie the background is gone, and even calling setBackgroundColor from QMovie doesn't work, so i've done something that fixes my problem, but in a way that isn't the better i guess.

    @void ImageViewer::setGifImage()
    {
    QPixmap m = scuareBackground();
    //m is an square 32x32, wich is the base for the alpha background.

    QPixmap temp(gifSize);
    //create a pixmap qith the same size that the gif image

    QPainter q(&temp);
    q.drawTiledPixmap(0,0,gifSize.width(), gifSize.height(), m);
    q.drawPixmap(0, 0, movie->currentPixmap());
    q.end();

    imageLabel->setPixmap(temp);
    }
    @

    that's an slot i've made, and it's used in here:

    @gifSize=(QPixmap(archivo->absoluteFilePath()).size());

    movie->start();
    connect(movie, SIGNAL(frameChanged(int)), this, SLOT(setGifImage()));

    //imageLabel->setMovie(movie);
    imageLabel->resize(gifSize);@

    of course i have to make a lot of improvements but it's something.

    if you have something to add or correct do it please



  • Setting background color via palette works for me. I don't know if you want to set only a background color or a background image. The latter would be harder to achieve.



  • If you go that way, I would suggest using the paintEvent, as you are creating a temporary image for each changed frame. Then you cans also derive the label (or from QWidget diretly) and implement thepaint event. Then connect the signal with update and it should work with less temporary objects / images.

    @
    {
    ...
    gifSize=(QPixmap(archivo->absoluteFilePath()).size());

    movie->start();
    connect(movie, SIGNAL(frameChanged(int)), pImageLabel, SLOT(update()));
    
    //imageLabel->setMovie(movie);
    imageLabel->resize(gifSize);
    ...
    

    }

    void CMyImageLabel::CMyImageLabel(QPixmap backSquare) :
    m_squareBackground(backSquare)
    {
    }

    void CMyImageLabel::paintEvent()
    {
    QPainter paint(this);
    paint.drawTiledPixmap(rect(), m_squareBackground);
    paint.drawImage(rect(), myMove.currentImage());
    }
    @



  • Volker, i want to set both image and color.

    Gerolf, thanks for the improved code, and now i have two questions: the slot update() is from QWidget? (remember i said i was learning) and, can you explain better what is CMyImageLabel?



  • samkpo, ok if I understand you right you have

    • background color (e.g. red) on your lebel
    • a semi-background image with transparency on top of the background color
    • a movie with transparency on top of the semi-background image

    Am I right?



  • update is a "slot of QWidget":http://doc.trolltech.com/4.7/qwidget.html#update, right.

    CMyImageLabel is a custom class, derived from QLabel or QWidget. If you need no functionality from QLabel (as you draw your image on your own) you can derive it from QWidget. Make the movie and the background image a member of the class. then connect the update slot and draw in the paintEvent.



  • Volker, not exactly, i want to have:

    • background color on my label
    • a movie with transparency on top of the label

    or

    • an image on top of my label
    • a movie with transparency on top of the image

    i mean, it's not the color and the image together as backgrounds, it's the color or the image

    Gerolf, ok, i think i understand



  • samkpo, I made up my mind. You will have to make your own widget, as Gerolf supposed. Basically you have to reimplement the paintEvent:

    movielabel.h

    @
    #ifndef MOVIELABEL_H
    #define MOVIELABEL_H

    #include <QWidget>
    #include <QPixmap>
    #include <QMovie>

    class MovieLabel : public QWidget
    {
    Q_OBJECT
    public:
    explicit MovieLabel(QWidget *parent = 0);

    signals:

    public slots:
    void start();
    void setMovie(const QString &file);
    void setBGPixmap(const QString &file);
    void setBGColor(QColor c);

    void drawFrame(int frameNumber);
    

    protected:
    void paintEvent(QPaintEvent *e);

    QMovie movie;
    QPixmap bgPixmap;
    QPixmap currentFrame;
    

    };

    #endif // MOVIELABEL_H
    @

    movielabel.cpp
    @
    #include "movielabel.h"

    #include <QPainter>
    #include <QPaintEvent>
    #include <QDebug>

    MovieLabel::MovieLabel(QWidget *parent) :
    QWidget(parent)
    {
    setAutoFillBackground(true);
    connect(&movie, SIGNAL(frameChanged(int)), this, SLOT(drawFrame(int)));
    }

    void MovieLabel::start()
    {
    movie.start();
    }

    void MovieLabel::setMovie(const QString &file)
    {
    movie.setFileName(file);
    }

    void MovieLabel::setBGPixmap(const QString &file)
    {
    bgPixmap.load(file);
    }

    void MovieLabel::setBGColor(QColor c)
    {
    QPalette p = palette();
    p.setColor(QPalette::Window, c);
    setPalette(c);
    }

    void MovieLabel::paintEvent(QPaintEvent *e)
    {
    if(bgPixmap.isNull())
    QWidget::paintEvent(e);

    QPainter p(this);
    if(!bgPixmap.isNull())
        p.drawPixmap(e->rect(), bgPixmap, e->rect());
    
    p.drawPixmap(e->rect(), currentFrame, e->rect());
    

    }

    void MovieLabel::drawFrame(int frameNumber)
    {
    currentFrame = movie.currentPixmap();
    repaint();
    }
    @

    You will have to reimplement sizeHint and some more methods and insert some sanity checks for the movie and the pixmaps to make it a fully mature widget.



  • ok guys, thanks a lot, i'll let you know when i finish it.



  • [quote author="samkpo" date="1292799006"]ok guys, thanks a lot, i'll let you know when i finish it.[/quote]

    Good luck!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.