2016-10-20 27 views
1

我想在QImage應用某些轉變 - 而且由於性能的限制,我想在如果可能的話渲染的時間來應用這些轉換。在QPainter的應用QTransform - 如何找到翻譯

的變換我需要 - 旋轉90度,180,270度,和垂直反射鏡。

我渲染QGraphicsSceneQImage
我希望將結果旋轉(0/90/180/270)或垂直鏡像。

我原來的代碼很簡單:

QImage image = QImage(wOutput, hOutput, QImage::Format_Mono); 
image.fill(QColor(Qt::white).rgb()); 
QPainter painter; 
painter.begin(&image); 
outputScene->render(&painter); 
painter.end(); 

要旋轉,我認爲這將是有效的噴漆前的旋轉QPainter - 這樣我就不必執行額外的轉換後的過程。 (我計劃的設備具有非常有限的內存和速度,Qt4.8)

它應該工作...但除了旋轉我還必須添加一個翻譯,我想不出有多少。

沒有翻譯我只是得到空白圖像。

此外,旋轉到90/-90,我得到較小的圖像。所以我需要擴大...多少?

我的代碼,試圖變換(旋轉和鏡像)圖像:

#include <QApplication> 
#include <QGraphicsScene> 
#include <QImage> 
#include <QPainter> 
#include <QTransform> 

QImage processScene(QGraphicsScene *s, int orientation, bool mirror); 
QImage otherProcessScene(QGraphicsScene *s, int orientation, bool mirror); 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    QGraphicsScene* s = new QGraphicsScene(-20, -100, 800, 600); 
    s->addText("abcd", QFont("Arial", 20)); 
    s->setBackgroundBrush(Qt::red); 

    // orientation = -90, 0, 90, 180; 
    int orientation = -90; 
    // vertical mirror true/false 
    bool mirror = true; 

    // what I am trying to do 
    QImage im = processScene(s, orientation, mirror); 
    im.save("test.bmp"); 

    // what I would like to come out like (Qt version) 
    QImage im1 = otherProcessScene(s, orientation, mirror); 
    im1.save("test1.bmp"); 

    a.exit(); 
    return 0; 
} 

QImage processScene(QGraphicsScene* s, int orientation, bool mirror) 
{ 
    int wOutput = s->width(), hOutput = s->height(); 

    // translation 
    int wTr = wOutput, hTr = hOutput; 
    // coefficients of transformation matrix 
    qreal m11 = 1, m12 = 0, m21 = 0, m22 = 1, m31 = 0, m32 = 0; 
    switch(orientation) 
    { 
    //case 0: break; 
    case -90: wTr = hOutput; hTr = wOutput; m11 = 0; m12 = -1; m21 = 1; m22 = 0; 
       m31 = x?; m32 = x?; break; 
    case 180: wTr = wOutput; hTr = hOutput; m11 = -1, m22 = -1; 
      m31 = x?; m32 = x?; break; 
    case 90: wTr = hOutput; hTr = wOutput; m11 = 0; m12 = 1; m21 = -1; m22 = 0; 
       m31 = x?; m32 = x?; break; 
    } 

    QImage image = QImage(wTr, hTr, QImage::Format_ARGB32_Premultiplied); 
    image.fill(QColor(Qt::white).rgb()); 

    QPainter painter; 
    painter.begin(&image); 

    QTransform painterTransform; 
    if(mirror) 
    { 
     // I have seen that negative scaling actually flips 
     m22 *= -1; 
     // I am guessing on shifts... 
     switch(orientation) 
     { 
     case 0: m31 = x?; m32 = x?; break; 
     case 180: m31 = x?; m32 = x?; break; 
     case 90: m31 = x?; m32 = x?; break; 
     case -90: m31 = x?; m32 = x?; break; 
     } 
    } 

    painterTransform.setMatrix(m11, m12, 0, m21, m22, 0, m31, m32, 1); 

    painter.setTransform(painterTransform); 
    s->render(&painter); 
    painter.end(); 

    return image; 
} 

QImage otherProcessScene(QGraphicsScene *s, int orientation, bool mirror) 
{ 
    int wOutput = s->width(), hOutput = s->height(); 

    QImage image = QImage(wOutput, hOutput, QImage::Format_ARGB32_Premultiplied); 
    image.fill(QColor(Qt::white).rgb()); 

    QPainter painter; 
    painter.begin(&image); 
    s->render(&painter); 
    painter.end(); 

    if(mirror) 
     image = image.mirrored(0, 1); 
    image = image.transformed(QMatrix().rotate(orientation)); 

    return image; 
} 

在上面的代碼註釋 - 我有2個功能:
- 什麼,我試圖做的,通過旋轉QPainter在渲染之前
- 一個會Qt「變換」 - 通過圖像像素迭代並在圖像已經渲染之後移動它們 - 以及非常大的圖像上,在內存和CPU受限設備上非常慢;正如我在代碼中所說的那樣,它是不可接受的。

旋轉180°/ 90°/ -90°時,我無法找出平移和縮放的公式(因爲90/-90似乎結果更小)。

至於鏡子,我希望通過我的作品-1調整的想法 - 但我確定轉移的同樣的問題。

如果換檔不正確,我只會看到一張白色圖像。當我得到這個工作時,90/-90旋轉看起來會導致一個較小的圖像(適合較大的尺寸進入較小的尺寸比例)。

請幫我弄清楚如何執行這些轉換。我會喜歡一個矩陣,它可以根據角度來確定翻譯(以及將圖像重置爲相同大小的縮放比例),而不僅僅是這些角度。

+0

可能是一個愚蠢的問題,但不能在第二個函數渲染之前轉換圖像嗎? – ymoreau

+0

@ymoreau - 渲染前我沒有圖像;我不想轉換圖像,我不想使用第二個函數。這就是整個點 - 圖像變換遍歷每個像素。對於需要很長時間的超大圖像和小型內存/ CPU設備。我想要沒有工作的結果。 – Thalia

回答

1

我發佈的函數執行旋轉和鏡像,通過旋轉QPainter

我無法得到一個實際的公式 - 大多數是反覆試驗和重複繪製一個對象與它的旋轉。

一旦我找出係數是什麼,它變得有點合乎邏輯。

對於調整大小問題 - 解決方案是將「目標」保留在原始渲染矩形中。

QImage processScene(QGraphicsScene* s, int orientation, bool mirror) 
{ 
    int wOutput = s->width(), hOutput = s->height(); 
    QRect target(0, 0, wOutput, hOutput); 

    // translation 
    int wTr = wOutput, hTr = hOutput; 

    // coefficients of transformation matrix 
    qreal m11 = 1, m12 = 0, m21 = 0, m22 = 1, m31 = 0, m32 = 0; 
    switch(orientation) 
    { 
    //case 0: break; 
    case -90: wTr = hOutput; hTr = wOutput; m11 = 0; m12 = -1; m21 = 1; m22 = 0; 
     m32 = wOutput; break; 
    case 180: wTr = wOutput; hTr = hOutput; m11 = -1, m22 = -1; 
     m31 = wOutput; m32 = hOutput; break; 
    case 90: wTr = hOutput; hTr = wOutput; m11 = 0; m12 = 1; m21 = -1; m22 = 0; 
     m31 = hOutput; break; 
    } 

    if(mirror) 
    { 
     switch(orientation) 
     { 
     case 0: m22 = -1; m32 = hOutput; break; 
     case 180: m22 = 1; m32 = 0; break; 
     case 90: m21 = 1; m31 = 0; break; 
     case -90: m21 = -1; m31 = hOutput; break; 
     } 
    } 

    QTransform painterTransform; 
    painterTransform.setMatrix(m11, m12, 0, m21, m22, 0, m31, m32, 1); 

    QImage image = QImage(wTr, hTr, QImage::Format_Mono); 
    image.fill(QColor(Qt::white).rgb()); 

    QPainter painter; 
    painter.begin(&image); 
    painter.setTransform(painterTransform); 
    s->render(&painter, target); 
    painter.end(); 

    return image; 
}