Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-44447

Enable AnimatedImage to not cache each frame

    XMLWordPrintable

Details

    • 2a28bebdc8548c1171a3f255651edafe685da003

    Description

      When you use an AnimatedImage element to display a .gif, the current implementation will cache a decoded copy of each frame of the .gif. For larger/longer animated images, this can occupy an absurd amount of memory. For example, to display the attached .gif, Qt allocates over 200MB of memory.

      The following (incorrect) patches reduces the amount of memory consumed down to that needed by a single frame:

      qtbase:

      diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp
      index 03e46ab..24a8680 100644
      --- a/src/gui/image/qgifhandler.cpp
      +++ b/src/gui/image/qgifhandler.cpp
      @@ -239,7 +239,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
               table[1] = &stack[(1 << max_lzw_bits) * 3];
           }
      
      -    image->detach();
      +    // image->detach();
           int bpl = image->bytesPerLine();
           unsigned char *bits = image->bits();
      
      diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
      index 4e10b4c..a8aaa2c 100644
      --- a/src/gui/image/qimage.cpp
      +++ b/src/gui/image/qimage.cpp
      @@ -1581,7 +1581,7 @@ uchar *QImage::bits()
       {
           if (!d)
               return 0;
      -    detach();
      +    // detach();
      
           // In case detach ran out of memory...
           if (!d)
      diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
      index 65e7fb0..09f1be4 100644
      --- a/src/gui/image/qpixmap_raster.cpp
      +++ b/src/gui/image/qpixmap_raster.cpp
      @@ -193,7 +193,7 @@ void QRasterPlatformPixmap::fill(const QColor &color)
                           toFormat = QImage::Format_ARGB32_Premultiplied;
      
                       if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) {
      -                    image.detach();
      +                    // image.detach();
                           image.d->format = toFormat;
                       } else {
                           image = QImage(image.width(), image.height(), toFormat);
      @@ -338,7 +338,7 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC
               inPlace = inPlace && sourceImage.isDetached();
               image = sourceImage;
               if (!inPlace)
      -            image.detach();
      +            // image.detach();
               if (image.d)
                   image.d->format = QImage::Format_RGB32;
           } else if (inPlace && sourceImage.d->convertInPlace(format, flags)) {
      

      qtdeclarative:

      diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp
      index 342394a..baababc 100644
      --- a/src/quick/items/qquickanimatedimage.cpp
      +++ b/src/quick/items/qquickanimatedimage.cpp
      @@ -365,7 +365,7 @@ void QQuickAnimatedImage::movieRequestFinished()
                   this, SLOT(playingStatusChanged()));
           connect(d->_movie, SIGNAL(frameChanged(int)),
                   this, SLOT(movieUpdate()));
      -    d->_movie->setCacheMode(QMovie::CacheAll);
      +    d->_movie->setCacheMode(QMovie::CacheNone);
      
           d->status = Ready;
           emit statusChanged(d->status);
      

      If it is agreed that we should allow AnimatedImage to not cache the decoded version of every frame, I can work on a patch that does that.

      Attachments

        Issue Links

          Activity

            People

              daiweili Daiwei Li
              daiweili Daiwei Li
              Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: