如何像 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 一样快速调整图像大小?的主要内容,如果未能解决你的问题,请参考以下文章
如何像 Interface Builder 一样调整 iOS UI 组件的大小