Search code examples
c++qtqt5webp

QMovie webp frame stutters


I'm using QMovie to play a webp animation on a QLabal, the code like:

Foo::Foo() {
    movie_ = new QMovie("/path/to/my.webp", "", this);
    ui->label->setMovie(movie_);
}
void Foo::on_pushButton_clicked() {
    movie_->stop();
    movie_->start();
}

But when I play the animation, the frame stutters, like:

the screenshot

I try to extract the webp frames by using QImage::save, the code like:

QImageReader *reader = new QImageReader("/path/to/my.webp");
reader->setDecideFormatFromContent(true);
for (int i = 0; i < reader->imageCount(); ++i) {
    QImage image;
    reader->read(&image);
    image.save(QString("frame_%1.png").arg(i));
    reader->jumpToNextImage();
}

all the extracted frames are stutters too, like:

frame_9.png

But when I extract frames by using google libwebp tool, there is no any problem.like:

frame_9_2.png

// extract frame 9, not problem
webpmux.exe -get frame 9  -o "frame_9.webp"
// paly webp animation, there is no any problem
vwebp.exe /path/to/my.webp

Is it a Qt problem? both Qt 5.9.4(i'm using) and Qt latest version(i'm trying) has this problem.


Solution

  • It seems a Qt bug, the bug has reported on Qt version 5.9.1: WebP: animations don't respect alpha

    Qt said the bug was solved on version 5.9.2, but the problems still exist even Qt 5.11.

    there is the offical solution:

    diff --git a/src/plugins/imageformats/webp/qwebphandler.cpp b/src/plugins/imageformats/webp/qwebphandler.cpp
    index 5a0ae4a..ce90158 100644
    --- a/src/plugins/imageformats/webp/qwebphandler.cpp
    +++ b/src/plugins/imageformats/webp/qwebphandler.cpp
    @@ -122,6 +122,8 @@ bool QWebpHandler::ensureScanned() const
                     that->m_bgColor = QColor::fromRgba(QRgb(WebPDemuxGetI(m_demuxer, WEBP_FF_BACKGROUND_COLOR)));
    
                     that->m_composited = new QImage(that->m_features.width, that->m_features.height, QImage::Format_ARGB32);
    +                if (that->m_features.has_alpha)
    +                    that->m_composited->fill(Qt::transparent);
    
                     // We do not reset device position since we have read in all data
                     m_scanState = ScanSuccess;
    @@ -193,6 +195,8 @@ bool QWebpHandler::read(QImage *image)
         } else {
             // Animation
             QPainter painter(m_composited);
    +        if (m_features.has_alpha && m_iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND)
    +            m_composited->fill(Qt::transparent);
             painter.drawImage(currentImageRect(), frame);
    
             *image = *m_composited;
    

    Here is my solution:

    1.add some code

    // ${QT_SRC}/qtimageformats/src/plugins/imageformats/webp/qwebphandler.cpp
    // function QWebpHandler::read
    if (m_features.has_alpha && (m_iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND || 
                m_iter.blend_method == WEBP_MUX_NO_BLEND)) {
          m_composited->fill(Qt::transparent);
    }
    

    2. rebuild qt webp plugin

    nmake module-qtimageformats

    1. replace qwebp.dll

    mv ${QT_DIR}/plugins/imageformats/qwebpd.dll ${QT_DIR}/plugins/imageformats/qwebpd.dll.bak

    cp ${REBUILD_WEBP_PLUGINS} ${QT_DIR}/plugins/imageformats/qwebpd.dll