2010-04-26 90 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來說,它很容易對其進行優化;儘管您現在開始進入每平臺優化。