2010-04-26 68 views
1

我已经使用Qt4实现了一个选取框文本控件。我首先将文本内容绘制到像素图上。然后通过调用painter.drawTiledPixmap(offsetX,offsetY,myPixmap)将这个像素图的一部分绘制到绘图设备上。我想象的是,Qt将用myPixmap中的内容填充整个字幕文本矩形。如何在Qt4中高效地转换像素图的像素

是否有更快的方法,将所有现有内容左移1px,然后用myPixmap中的内容填充新暴露的1px宽和N-px高区域?

回答

1

好吧。这是我以前用较慢的硬件做的一个技巧。基本上,图像缓冲区被分配两倍于所需的宽度,并在开始处添加一行。将图像构建到缓冲区的左侧。然后重复绘制图像,缓冲区中缓冲区每次前进1个像素。

int w = 200; 
int h = 100; 
int rowBytes = w * sizeof(QRgb) * 2; // line buffer is twice as the width 
QByteArray buffer(rowBytes * (h + 1), 0xFF); // 1 more line than the height 
uchar * p = (uchar*)buffer.data() + rowBytes; // start drawing the image content at 2nd line 
QImage image(p, w, h, rowBytes, QImage::Format_RGB32); // 1st line is used as the padding at the start of scroll 
image.fill(qRgb(255, 0, 0)); // well. do something to the image 

p = image.bits() - rowBytes/2; // start scrolling at the middle of the 1st (blank) line 
for(int i=0;i<w;++i, p+=sizeof(QRgb)) { 
    QImage scroll(p, w, h, rowBytes, QImage::Format_RGB32); // scrool 1 pixel at a time 
    scroll.save(QString("%1.png").arg(i)); 
} 

我不确定这会比改变图像的偏移和绘制海峡更快。今天的硬件非常强大,这使得许多旧技巧无用。但玩晦涩难懂的技巧很有趣。 :)

1

问候,

一个可能实现这一目标将是:

  1. 创建QGraphicsScene +查看并把该像素图的两倍(如QGraphicsPixmapItem),所以他们紧挨着对方。
  2. 调整视图的大小以适合(一个)像素图的大小。
  3. 然后,您不必重新绘制像素图,而只需重新定位视图的视口,从一个像素图移动到下一个。
  4. 跳回到最后创建循环。

这可能会也可能不会更快(就性能而言) - 我还没有测试过它。但如果仅仅是为了实验,可能值得一试。

+0

谢谢。但QGraphicsScene是基于浮点协调的,而不是基于整数的。这种方法更快吗? – stanleyxu2005 2010-04-27 19:53:44

+0

我认为,重要的不是qreal与int的用法,而是如何在内部处理图纸。我的猜测是移动视图的视口比实际为每个单帧重复绘制像素映射要优化得多。但正如我所说:我没有做任何测试或基准与此。如果你尝试它,请告诉我你的结果,是吗? – Robin 2010-04-29 10:36:50

1

您的方法可能是您使用底层绘画方法以来速度最快的方法之一。您可以实现低级绘画和QGraphicsScene选项之间的中间方法:使用包含标签的滚动区域。

以下是创建包含文本标签的新滚动区域的代码示例。您可以使用QTimer自动滚动标签以触发滚动效果,这会给您一个不错的选取框小部件。

QScrollArea *scrollArea = new QScrollArea(); 

// ensure that scroll bars never show 
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 

QLabel *label = new QLabel("your scrolling text"); 

// resize the scroll area : 50px length and an height equals to its content height. 
scrollArea->resize(50, label->size().height()); 
scrollArea->setWidget(label); 
label->show(); // optionnal if the scroll area is not yet visible 

滚动区域内的文本标签可以从一个像素使用QScrollArea::scrollContentsBy(int dx, int dy)dx参数等于-1从左到右移动。

0

为什么不只是在逐个像素的基础上做?由于高速缓存的工作原理,在完成之前将像素写入一个像素,直到完成。然后,您可以通过阅读您的其他图像填写最后一栏。

对于SIMD来说,它很容易对其进行优化;尽管您现在开始进入每平台优化。