在QML中旋转图像时减少CPU使用率

时间:2014-02-03 15:53:30

标签: c++ qml qt5 qtquick2

我创建了一个基于Qt 5.2的QML应用程序,我在Mac OS X和Windows(从XP到8)上部署。我的应用程序有一个主要动画,可以在用户直播时无限旋转图像。此动画是应用程序的核心部分,我无法将其删除。

旋转图像需要太多CPU能力,我正在寻找解决此问题的方法。其背后的原因是很多用户不支持OpenGL 2(在Windows上),我将不得不依靠MESA的DLL在软件中进行渲染,使得应用程序在这些机器上无法使用动画正在运行。

以下是我在QML中动画的当前实现:

Image {
  id: imgBroadcastState
  source: "images/broadcast_button.png"
  anchors.horizontalCenter: parent.horizontalCenter

  NumberAnimation on rotation {
    from: 0
    to: 360
    running: rootWindow.isBroadcasting
    loops: Animation.Infinite
    duration: 7000

    onRunningChanged:{
      if(!running) {
        imgBroadcastState.rotation = 0;
      }
    }
  }
}

我尝试的第一个解决方案是创建一个包含动画的所有帧的巨大精灵,然后加载AnimatedSprite。这减少了CPU,但显然不够,RAM消耗增加了三倍以上,高达300MB,这对旧的Windows XP机器来说不是一个好的解决方案。

我还尝试了对QQuickPaintedItem进行子类化并每30ms手动调用paint()(使用QTimer)来旋转图像。这也会降低CPU,但也不够。这是我使用的代码:

void MXPaintedItem::paint(QPainter *painter)
{
  QTransform rot;
  rot.rotate(m_angle);
  painter->setRenderHint(QPainter::Antialiasing);
  painter->setRenderHint(QPainter::SmoothPixmapTransform);
  painter->translate(width() / 2, height() / 2);
  painter->rotate(m_angle);
  // Use preloaded QImage
  painter->drawImage(QPoint(-width() / 2, -height() / 2), m_image);


  m_angle += 2.5;
}

有没有办法改善这一点并降低旋转动画的CPU使用率?

修改

当然我可以改变动画或不使用动画,但这不是一个长期的解决方案。最后,必须动态绘制/更新此图像以反映VUMeter并表示声级。因此,我需要找到一个合适的解决方案,允许我实时更新QML视图的一部分,而无需重绘整个UI并占用太多CPU。

EDIT2 : 我发现主CPU使用率不是轮换本身,而是每次都必须重绘整个UI的事实。您只需在return函数中调用paint()而不是旋转任何内容即可确保这一点。与动画图像本身相比,CPU使用情况相同,这表明问题来自每次更新场景中的一个QML组件时更新整个UI

3 个答案:

答案 0 :(得分:0)

如果您有内存空间且旋转次数很小,请为每次旋转使用一个位图。这就是自计算机开始以来编写“旋转器”的方式。

理论上说,bitblit比执行旋转变换更快,然后blitting结果图像。

答案 1 :(得分:0)

接下来我会尝试拍摄动画并制作动画GIF。无论您使用什么工具生成gif,都应该能够配置压缩/优化以获得您满意的质量/尺寸。

然后尝试使用QML AnimatedImage Element来显示GIF,这可能会提供更好的结果。

答案 2 :(得分:0)

经过更多调查后,我得出的结论是,没有简单的方法来优化这一点。通过QML本身可以获得最佳性能,因为它针对缓存元素进行了优化,并改善了场景重新绘制。

主要解决方案是仅重绘场景的一部分。使用QML和新的SceneGraph渲染无法实现这一点,并且不会在不久的将来进行规划。这个答案是由Qt中负责开发此功能的人员给出的。

CPU使用率本身高度依赖于硬件和显卡驱动程序,因为现在所有内容都基于OpenGL 2.0,并且依赖于硬件/驱动程序正确支持某些OpenGL操作的事实。