在 QPainter 上应用 QTransform - 如何找到翻译
Applying QTransform on QPainter - how to find translations
我想在 QImage
上应用某些转换 - 由于性能限制,我想尽可能在渲染时应用这些转换。
我需要的变换 - 旋转 90、180、270 度和垂直镜像。
我正在将 QGraphicsScene
渲染为 QImage
。
我希望结果旋转 (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
会很有效 - 这样我就不必执行额外的转换 post 过程。 (我正在计划一个内存和速度非常有限的设备,以及 Qt4.8)
应该可以...但是除了旋转我还必须添加翻译,我不知道有多少。
没有翻译我只得到空白图像。
此外,旋转到 90/-90 我得到的图像更小。所以我需要扩展...多少?
我尝试转换(旋转和镜像)图像的代码:
#include <QApplication>
#include <QGraphicsScene>
#include <QImage>
#include <QPainter>
#include <QTransform>
QImage badProcessScene(QGraphicsScene *s, int orientation, bool mirror);
QImage wantProcessScene(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 = wantProcessScene(s, orientation, mirror);
im.save("test.bmp");
// what I would like to come out like (Qt version)
QImage im1 = badProcessScene(s, orientation, mirror);
im1.save("test1.bmp");
a.exit();
return 0;
}
// Bad version, though functional - typical approach, of rotating images after being rendered
QImage badProcessScene(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;
}
// Desired but needs adjustments
QImage wantProcessScene(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;
}
注意上面的代码 - 我有 2 个函数:
- 我想做的是在渲染前旋转
QPainter
(wantProcessScene
)
- 一个执行 Qt“转换”的方法——遍历图像像素并在图像已经渲染后移动它们——在非常大的图像、内存和 CPU 有限的设备上非常慢;它按照我在代码中所说的那样工作,这是不可接受的。 (
badProcessScene
)
我无法找出在旋转 180/90/-90 时的平移和缩放公式(因为对于 90/-90,结果似乎更小)。
至于镜像,我希望我按 -1 调整大小的想法能奏效 - 但我也有确定偏移的相同问题。
如果移位不正确,我只能看到白色图像。当我让它工作时,90/-90 度旋转似乎会产生较小的图像(将较大的尺寸适合较小的尺寸,保持纵横比)。
请帮我弄清楚如何执行这些转换。我想要一个基于角度确定平移(并缩放以将图像重置回相同大小)的矩阵 - 而不是这些奇怪的角度。
我正在发布通过旋转 QPainter
执行旋转和镜像的功能。
我无法得到实际的公式 - 大多数是反复试验和一遍又一遍地重新绘制一个对象及其旋转。
一旦我弄清楚系数是什么,它就变得有点合乎逻辑了。
对于调整大小的问题 - 解决方案是将 "target" 保留为原始渲染矩形。
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;
}
我想在 QImage
上应用某些转换 - 由于性能限制,我想尽可能在渲染时应用这些转换。
我需要的变换 - 旋转 90、180、270 度和垂直镜像。
我正在将 QGraphicsScene
渲染为 QImage
。
我希望结果旋转 (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
会很有效 - 这样我就不必执行额外的转换 post 过程。 (我正在计划一个内存和速度非常有限的设备,以及 Qt4.8)
应该可以...但是除了旋转我还必须添加翻译,我不知道有多少。
没有翻译我只得到空白图像。
此外,旋转到 90/-90 我得到的图像更小。所以我需要扩展...多少?
我尝试转换(旋转和镜像)图像的代码:
#include <QApplication>
#include <QGraphicsScene>
#include <QImage>
#include <QPainter>
#include <QTransform>
QImage badProcessScene(QGraphicsScene *s, int orientation, bool mirror);
QImage wantProcessScene(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 = wantProcessScene(s, orientation, mirror);
im.save("test.bmp");
// what I would like to come out like (Qt version)
QImage im1 = badProcessScene(s, orientation, mirror);
im1.save("test1.bmp");
a.exit();
return 0;
}
// Bad version, though functional - typical approach, of rotating images after being rendered
QImage badProcessScene(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;
}
// Desired but needs adjustments
QImage wantProcessScene(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;
}
注意上面的代码 - 我有 2 个函数:
- 我想做的是在渲染前旋转
QPainter
(wantProcessScene
) - 一个执行 Qt“转换”的方法——遍历图像像素并在图像已经渲染后移动它们——在非常大的图像、内存和 CPU 有限的设备上非常慢;它按照我在代码中所说的那样工作,这是不可接受的。 (
badProcessScene
)
我无法找出在旋转 180/90/-90 时的平移和缩放公式(因为对于 90/-90,结果似乎更小)。
至于镜像,我希望我按 -1 调整大小的想法能奏效 - 但我也有确定偏移的相同问题。
如果移位不正确,我只能看到白色图像。当我让它工作时,90/-90 度旋转似乎会产生较小的图像(将较大的尺寸适合较小的尺寸,保持纵横比)。
请帮我弄清楚如何执行这些转换。我想要一个基于角度确定平移(并缩放以将图像重置回相同大小)的矩阵 - 而不是这些奇怪的角度。
我正在发布通过旋转 QPainter
执行旋转和镜像的功能。
我无法得到实际的公式 - 大多数是反复试验和一遍又一遍地重新绘制一个对象及其旋转。
一旦我弄清楚系数是什么,它就变得有点合乎逻辑了。
对于调整大小的问题 - 解决方案是将 "target" 保留为原始渲染矩形。
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;
}