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

Posted

技术标签:

【中文标题】如何像 QLabel 一样快速调整图像大小?【英文标题】:How can I resize image as fast as QLabel does? 【发布时间】: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 指针”无法访问。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

来自QPixmap的详细说明:

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

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

【讨论】:

【参考方案2】:

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

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

【讨论】:

以上是关于如何像 QLabel 一样快速调整图像大小?的主要内容,如果未能解决你的问题,请参考以下文章

CSS如何使文本像图像一样缩放

qlabel居中

让多个 iframe 像常规窗口一样拖动、调整大小和最小化

如何像 Interface Builder 一样调整 iOS UI 组件的大小

tableview 单元格我们如何快速调整单元格的大小以及图像和标签

根据列表中图像的数量按比例调整动态图像列表的大小