1

我正在尝试优化一些代码,因为我必须多次将相同的 QPixmap 绘制到更大的 QPixmap 上。由于在我自己的方法中按值传递 QPixmap 会在每次调用时创建副本,我想我可以通过使用指向 QPixmaps 的指针来节省一些时间。然而,我的工作似乎一直在进行。我认为这是因为调用 QPainter::drawPixmap(..., const QPixmap&, ...) 会创建它的副本。

QPixmap *pixmap = new QPixmap(10,10);
painter.drawPixmap(0,0, *pixmap);

此示例中是否正在创建副本?

如果是这样,我该如何优化将许多图像绘制到另一个图像上?

我已经在这里阅读了这个 Q/A:取消引用指针会复制它吗?但是对于我的具体情况,我没有明确的答案。

4

2 回答 2

4

不,该函数引用了drawPixmap,因此没有复制。这是 QPainter 成员函数的原型:constpixmap

  void  drawPixmap ( int x, int y, const QPixmap & pixmap )
于 2013-03-05T03:18:25.560 回答
0

根据QPixmap 类参考

QPixmap 对象可以通过值传递,因为 QPixmap 类使用隐式数据共享。有关详细信息,请参阅隐式数据共享文档。

QPixmap 实现:

QPixmap::QPixmap(const QPixmap &pixmap)
    : QPaintDevice()
{
    if (!qt_pixmap_thread_test()) {
        init(0, 0, QPixmapData::PixmapType);
        return;
    }
    if (pixmap.paintingActive()) {                // make a deep copy
        operator=(pixmap.copy());
    } else {
        data = pixmap.data;
    }
}

只有当像素图处于活动状态时,您才需要深拷贝,否则新像素图只需要复制原始数据指针。

对于 const 引用和指针的区别:

QPixmap largeMap(1000, 1000);
QPainter p(&largeMap);

int count = 100000;
qint64 time1, time2;
QPixmap *pSmallMap = new QPixmap("e:/test.png");
QPixmap smallMap = QPixmap("e:/test.png");

time1 =  QDateTime::currentMSecsSinceEpoch();
for (int i = 0; i < count; ++i) {
    p.drawPixmap(0, 0, *pSmallMap);
}
time2 =  QDateTime::currentMSecsSinceEpoch();;
qDebug("def time = %d\n", time2 - time1);

time1 =  QDateTime::currentMSecsSinceEpoch();
for (int i = 0; i < count; ++i) {
    p.drawPixmap(0, 0, smallMap);
}
time2 =  QDateTime::currentMSecsSinceEpoch();;
qDebug("normal time = %d\n", time2 - time1);

在 Visual Studio 2010调试配置下编译将产生以下程序集:

    28:         p.drawPixmap(0, 0, *pSmallMap);
003B1647 8B 55 C4             mov         edx,dword ptr [ebp-3Ch]  //the pixmap pointer
003B164A 52                   push        edx  
003B164B 6A 00                push        0  //x
003B164D 6A 00                push        0  //y
003B164F 8D 4D F0             lea         ecx,[ebp-10h]  //the qpainter pointer
003B1652 FF 15 9C D7 3B 00    call        dword ptr [__imp_QPainter::drawPixmap (3BD79Ch)]

    35:         p.drawPixmap(0, 0, smallMap);
003B16A8 8D 4D E0             lea         ecx,[ebp-20h]  //the pixmap pointer
003B16AB 51                   push        ecx            
003B16AC 6A 00                push        0              //x
003B16AE 6A 00                push        0              //y
003B16B0 8D 4D F0             lea         ecx,[ebp-10h]  //the qpainter pointer
003B16B3 FF 15 9C D7 3B 00    call        dword ptr [__imp_QPainter::drawPixmap (3BD79Ch)]  

这两者之间应该没有区别,因为编译器将生成相同的汇编代码:将指针传递给 drawPixmap 函数。

QDateTime::currentMSecsSinceEpoch() 在我的盒子上几乎显示了相同的结果。

于 2013-03-05T03:20:36.167 回答