在QPainter上绘制QImage,它具有反转的y轴

时间:2014-04-07 12:32:21

标签: qt graphics

我有一个倒y轴的场景。除了QImages之外,所有内容都被正确绘制。

我使用drawIage()作为:

QRectF aWorldRect = ...
QRectF anImageRect = QRectF(0, 0, theQImage.width(), theQImage.height())
thePainter->drawImage(aWorldRect, theQImage, anImageRect;

我在应该显示图像的外部(到顶部)获得未定义的图形。这是正常的,因为y轴是反转的。所以我期望这样的事情可以解决这个问题:

QRectF anImageRect = QRectF(0, 0, imgWidth, -imgHeight)

它具有相同的效果。如果我在调用aWorldRect = aWorldRect.noralized()之前drawImage(),我会将图片放入正确的矩形,但是镜像,所以我做了aQImage = aQImage.mirrored()。现在图像正确显示在正确的矩形

我认为这是一种我不喜欢的解决方法。那么,有人可以告诉我应该怎样做以正确的方式显示图像吗?

更新 在这里,我提出了一个可以编译的问题的最小样本:

更新2014-04-09 10:05 EET 使用解决方法

更新了示例代码以使其真正有效
#include <QtGui>

const int WIDTH = 640;
const int HEIGHT = 480;

class View : public QGraphicsView
{
protected:
    void drawBackground(QPainter *p, const QRectF & rect)
    {
        QImage img = QImage("/usr/share/backgrounds/images/stone_bird.jpg"); // or any other

        /* The next three lines makes everything displayed correctly but
           should be considered a workaround */
        /* I ignore the rect that is passed to the function on purpose  */
        QRectF imageRect = QRectF(QPointF(0, 0), QPointF(img.width(), img.height()));
        QRectF theSceneRect = sceneRect().normalized();
        p->drawImage(theSceneRect, img.mirrored(), imageRect);

    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    View w;

    /* I don't want to change the code below */
    w.setScene(new QGraphicsScene(QRectF(QPointF(0, HEIGHT), QPointF(WIDTH, 0))));
    w.scale(1, -1);
    w.scene()->addLine(0, HEIGHT, WIDTH, 0);
    w.showMaximized();

    return a.exec();
}

2 个答案:

答案 0 :(得分:2)

反转Y坐标值的方法是正确的,但实施是错误的。

QRectF的文档显示它需要(x,y,width,height)。将高度视为负面是没有意义的。而是尝试使用 topLeft bottomRight 的其他构造函数。

QRectF anImageRect(QPointF(0.0f, -imgHeight), QPointF(imageWidth, 0.0f));

修改

看起来像线,弧等唯一的图形会受到您在视图上设置的比例(1,-1)变换的影响。由于比例设定,drawImage继续呈现倒置。简单的解决方法是将比例设置回(1,-1)。这是更新后的代码:

void drawBackground(QPainter *p, const QRectF & rect)
{
    QImage img = QImage("/usr/share/backgrounds/images/stone_bird.jpg");

    // backup the current transform set (which has the earlier scale of (1, -1))
    const QTransform oldTransform = p->transform();

    // set the transform back to identity to make the Y axis go from top to bottom
    p->setTransform(QTransform());
    // draw
    QRectF theSceneRect = sceneRect().normalized();
    p->drawImage(theSceneRect, img);

    // revert back to the earlier transform
    p->setTransform(oldTransform);
}

答案 1 :(得分:1)

更新于2014-04-14 14:35 EET

我最终可以通过替换两行来解决问题

QRectF theSceneRect = sceneRect().normalized();
p->drawImage(theSceneRect, img.mirrored(), imageRect);

我的问题

QRectF theSceneRect = sceneRect(); // Not normalized. It is no more workaround :)

qreal x = theSceneRect.x();
qreal y = theSceneRect.y();
qreal w = theSceneRect.width();
qreal h = theSceneRect.height();
qreal sx = imageRect.x();
qreal sy = imageRect.y();
qreal sw = imageRect.width();
qreal sh = imageRect.height();

p->translate(x, y);
p->scale(w / sw, h / sh);
p->setBackgroundMode(Qt::TransparentMode);
p->setRenderHint(QPainter::Antialiasing, p->renderHints() &
    QPainter::SmoothPixmapTransform);
QBrush brush(img);
p->setBrush(brush);
p->setPen(Qt::NoPen);
p->setBrushOrigin(QPointF(-sx, -sy));
p->drawRect(QRectF(0, 0, sw, sh));

p->restore();

这受到QPainter::drawImage()的实现的启发,由于许多 if 语句处理宽度或高度为负值的矩形,因此在这种情况下不可靠。

如果我在另一个函数中创建解决方案会更好,但我保持这种方式与我的问题中的代码更兼容。