Я хотел бы применить определенные преобразования на QImage
- и из-за ограничений производительности я хотел бы применить эти преобразования во время рендеринга, если это возможно.Применение QTransform на QPainter - как найти переводы
Необходимые преобразования - поворот 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
перед покраской - это способ, которым я не должен выполнять дополнительные преобразования размещать процесс. (Я планирую устройство с очень ограниченной памятью и скоростью и 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 «преобразует» - который перебирает пиксели изображения и перемещает их после того, как изображение уже было обработано, - и на очень больших изображениях на устройствах с ограниченным объемом памяти и на процессорах очень медленно; Он работает, как я сказал в коде, и это неприемлемо.
Я не смог найти формулу для перевода и масштабирования (потому что для 90/-90 результат кажется меньшим) при вращении 180/90/-90.
Что касается зеркала, я надеюсь, что моя идея изменения размера на -1 работает, но у меня такая же проблема определения сдвигов.
С неправильными сдвигами я просто вижу белое изображение. По мере того как я получаю это, чтобы работать, повороты 90/-90, кажется, приводят к меньшему изображению (которое приспосабливает больший размер к меньшему, сохраняя пропорции).
Пожалуйста, помогите мне выяснить, как выполнить эти преобразования. Мне бы понравилась матрица, которая определяет переводы (и масштабирование для возврата изображений назад к одному и тому же размеру) на основе угла - а не странные углы именно этих.
Может быть, это глупый вопрос, но разве вы не можете просто преобразовать изображение перед рендерингом во второй функции? – ymoreau
@ymoreau - у меня нет изображения, до рендеринга; и я не хочу преобразовывать изображение, я не хочу использовать вторую функцию. В этом весь смысл - преобразования изображений проходят через каждый пиксель. Для чрезвычайно больших изображений и небольших устройств памяти/процессора, которые занимают очень много времени. Я хочу получить результат без работы. – Thalia