2016-10-20 15 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

愚かな質問かもしれませんが、2番目の関数でレンダリングする前に画像を変換することはできませんか? – ymoreau

+0

@ymoreau - レンダリングの前に画像がありません。私は画像を変換したくないので、私は第2の関数を使いたくありません。つまり、ポイント全体の画像変換が各ピクセルを反復処理します。非常に大きな画像と小さなメモリ/ 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; 
} 
関連する問題