如何像QLabel一样快速调整图像大小?

时间:2011-03-20 10:11:18

标签: qt4

我正在尝试编写一个显示和操作图像的基于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函数,看看它是如何显示pixmap的。
似乎pixmap一旦被转换为QImage并缩放到窗口大小,
然后再转换为QPixmap 我有点惊讶,因为在QPixmap和QImage之间进行转换是一项昂贵的操作 根据Qt参考手册,但我尝试重写我的小部件的paintEvent()来做同样的事情 作为QLabel :: paintEvent()。然后调整大小变得比预期慢得多。

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

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:1)

可能有所帮助的一些一般性意见。

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

答案 1 :(得分:0)

来自QPixmap详细说明:

  

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

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

答案 2 :(得分:0)

感谢您的回复。

但正如我上面所写,实现我的paintEvent()以缩放QImage并将其转换回QPixmap最终会导致更糟糕的性能。
所以我想在QLabel中使用了某种特殊的技术......