【问题标题】:How can I resize image as fast as QLabel does?如何像 QLabel 一样快速调整图像大小?
【发布时间】:2011-07-19 01:52:41
【问题描述】:

我正在尝试编写一个基于 Qt 的应用程序来显示和处理图像。
我希望图像始终扩展到保持其纵横比的窗口大小。
不幸的是,QLabel 没有选项来保持附加像素图的纵横比。
所以我写了一个自定义小部件并实现了 resizeEvent() 和 paintEvent() 来调整图像的大小
并绘制它:

   class MyLabel : public QWidget
   {
     Q_Object

   public:
     MyLabel(): pixmap("test.tif") {} 

   protected:
     void resizeEvent(QResizeEvent *event)
     {
       pixmap_scaled = pixmap.scaled(size(), Qt::KeepAspectRatio);
     }

     void paintEvent(QPaintEvent *event)
     {
       QPainter p(this);
       p.drawPixmap(0, 0, pixmap_scaled);
       p.end();
     }

   private:
     QPixmap pixmap, pixmap_scaled;
   };  

但图像的大小调整不如 QLabel 那样平滑。

然后我看一下qlabel.cpp中QLabel的paintEvent函数,看看它是如何显示像素图的。
似乎像素图曾经转换为 QImage 并缩放到窗口大小,
然后再次转换为 QPixmap。
我有点惊讶,因为在 QPixmap 和 QImage 之间进行转换是一项昂贵的操作
根据 Qt 参考手册,但我尝试重写我的小部件的 paintEvent() 来做同样的事情
作为 QLabel::paintEvent()。然后调整大小变得比预期的要慢得多。

我想知道为什么 QLabel 的大小调整如此之快。是“隐式数据共享”的好处吗?
当然不可能将 QLabel 的paintEvent() 复制到我的班级,因为私有数据
例如“d 指针”无法访问。

任何帮助将不胜感激。

【问题讨论】:

    标签: qt4


    【解决方案1】:

    来自QPixmap的详细说明:

    QImage 专为 I/O 以及直接像素访问和操作而设计和优化,而 QPixmap 专为在屏幕上显示图像而设计和优化。

    所以我想缩放 QImage 并将其转换回 QPixmap 比缩放 QPixmap 更快

    【讨论】:

      【解决方案2】:

      一些可能有帮助的一般性观察。

      1. 如果您转换为 QImage 一次并保留对 QImage 的引用,这可能会提高一些性能。然后,您只需要在绘制事件中进行缩放和转换。
      2. 在调整大小事件中,标记图像需要重新缩放,但在绘制之前不要这样做。 Qt 将尽可能组合绘制事件,这样您就可以避免缩放,只是在绘制之前再次缩放。
      3. 如果您经常放大和缩小尺寸,请考虑找到“步骤”,并将缓存的图像保留在那里。尽可能显示这些步骤,并在不可能时选择一个可以很好地缩放(通常是 2 的倍数)当前大小的步骤。
      4. 考虑不要直接缩放图像,而是使用画家变换。这可能会将缩放工作从 CPU 转移到 GPU 转换,这通常会更快。在这种情况下,您总是希望绘制全尺寸图像,并让变换向上或向下。

      【讨论】:

        猜你喜欢
        • 2016-08-18
        • 2011-05-16
        • 2022-11-18
        • 1970-01-01
        • 1970-01-01
        • 2015-12-19
        • 2023-03-06
        • 2012-09-16
        • 2020-12-07
        相关资源
        最近更新 更多