Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: alexey11111 от Ноябрь 04, 2012, 21:49



Название: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 04, 2012, 21:49
Друзья, помогите еще разок)))
Сделал объект (не без помощи форума ;)) - потомок QGraphicsItem, который можно перемещать, вращать и изменять размеры. Объект представляет собой прямоугольник и нужен для того, чтобы выделять часть изображения и сохранять ее (обрезка изображения, короче говоря). Делаю так:
QPoint tl = mapToParent(boundingRect().topLeft()).toPoint();//Координаты верхнего левого угла объекта
QPoint br = mapToParent(boundingRect().bottomRight()).toPoint();//Координаты нижнего правого угла объекта
QRect rct(tl, br);
QImage img = photoImg.copy(rct);
MVNDW->PreviewImage->setPixmap(QPixmap::fromImage(img));

Все работает, но если выделяющий прямоугольник повернуть, то вырезанное изображение получается не так как хотелось - нужно, чтобы вырезалась область под ПОВЕРНУТЫМ прямоугольником. А в данном случае получается, что берется не повернутый, а обычный прямоугольник, но с другими координатами верхнего и нижнего угла. (см. картинку cropper.jpg)
Подскажите, как решить эту проблему с малой кровью, или придется пересчитывать все повороты?


Название: Re: Обрезка изображения
Отправлено: mutineer от Ноябрь 04, 2012, 21:59
Поверни всю конструкцию (изображение и прямоугольник) таким образом, чтобы стороны прямоугольника были параллельны сторонам окна. После этого вырежи


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 04, 2012, 22:18
Сделал так:
        QTransform myTransform;
        myTransform.rotate(_rotat);/поворот на угол _rotat     
        QImage rotated = photoImg.transformed(myTransform);//вращаем все изображение
        QPoint tl = mapToParent(boundingRect().topLeft()).toPoint();
        QPoint br = mapToParent(boundingRect().bottomRight()).toPoint();
        QRect rct(tl, br);
        QImage img = rotated.copy(rct);
        MVNDW->PreviewImage->setPixmap(QPixmap::fromImage(img));

        //Здесь вращаем сам прямоугольник
        setTransformOriginPoint(_height/2, _width/2);
        setRotation(_rotat);

Вроде что-то вращается, но все-равно не то получилось...


Название: Re: Обрезка изображения
Отправлено: mutineer от Ноябрь 04, 2012, 22:56
Изображение ты повернул, а как насчет прямоугольника? Его тоже надо повернуть на тот же угол и только потом вырезать.

Зачем ты поворачиваешь его уже после обрезки?

Ну и хотелось бы видеть в чем выражается это самое "не то"


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 04, 2012, 23:03
Вот пример "не того".
Попробовал вращать прямоугольник до обрезки - то же самое.


Название: Re: Обрезка изображения
Отправлено: mutineer от Ноябрь 04, 2012, 23:06
Как видишь обрезка получилась уже под углом, но повернутая не в ту сторону. Значит изображение нужно повернуть в другую сторону. Почему координаты неправильные получились не знаю, возможно ты вращаешь изображение и прямоугольник вокруг разных точек. Лучше всего попробуй отобразить на экране результаты вращения


Название: Re: Обрезка изображения
Отправлено: Igors от Ноябрь 05, 2012, 13:22
аттач


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 05, 2012, 18:18
аттач

То, что надо!!! Миллион благодарностей :D


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 05, 2012, 20:42
аттач

То, что надо!!! Миллион благодарностей :D

Немного покрутил - работает опять не так как надо(
Вставил код из аттача в проект, получилось следующее:
Код:
void Cropper::wheelEvent(QGraphicsSceneWheelEvent *event)
{
        event->setAccepted( true );
        //qDebug()<<"X: "<<tl.x()<<" Y: "<<tl.y()<<" botX: "<<br.x()<<" botY: "<<br.y();

        int numDegrees = event->delta() / 8;
        int numSteps = numDegrees / 15;
        _rotat += numSteps;
        if(_rotat>90) _rotat=90;
        else if(_rotat<-90) _rotat=-90;

        QTransform trans = QTransform().rotate(-_rotat );

        qreal w = MVNDW->photoImg.width();
        qreal h = MVNDW->photoImg.height();

        QPointF p[4];
        p[0] = QPoint(0, 0);
        p[1] = QPointF(w, 0);
        p[2] = QPointF(w, h);
        p[3] = QPointF(0, h);

        QPointF offs(0, 0);
        for (int i = 0; i < 4; ++i)
        {
            QPointF temp = trans.map(p[i]);
            offs.setX(qMin(offs.x(), temp.x()));
            offs.setY(qMin(offs.y(), temp.y()));
        }


        QPointF LT = mapMapToPar[img][/img]ent(boundingRect().topLeft()) - offs;
        int x = int(LT.x());
        int y = int(LT.y() );

        QImage rotated = MVNDW->photoImg.transformed(trans).copy(x, y,         boundingRect().width(), boundingRect().height());
        MVNDW->PreviewImage->setPixmap(QPixmap::fromImage(rotated));
     
     

        setRotation(_rotat);

}

Однако если вращать, то получается следующее (картинка).


Название: Re: Обрезка изображения
Отправлено: Igors от Ноябрь 05, 2012, 20:57
Код:
        QPointF LT = mapMapToPar[img][/img]ent(boundingRect().topLeft()) - offs;
Уточните эту строку. У меня все по-народному, в координатах имеджа. (0, 0) верхний левый угол. Привлекать др. трансформы нельзя


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 05, 2012, 21:06
Igors,
В твоем примере куда бы мы не поместили прямоугольник всегда все правильно вырезается. Строчка QPointF LT = trans.map(boundingRect().topLeft()) - offs у тебя работает корректно. В моем же случае, если я оставлю эту строчку в этом же виде, то получаю такую штуку (картинка). Т.е. куда бы не перемещался выделитель, координата его левого правого угла всегда будет началом координат QGraphicsScene (где расположена картинка). Поэтому я сделал:
QPointF LT = mapToParent(boundingRect().topLeft()) - offs
но легче не стало. Не понятно как правильно выбирать центр вращения в относительных координатах (что куда проецировать).


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 05, 2012, 21:26
Короче говоря, получается так.
Если я оставляю строчку  QPointF LT = trans.map(boundingRect().topLeft()) - offs;
то все обрезается корректно, если прямоугольник находится в точке (0,0) в координатах QGraphicsScene. Если же я его мышкой передвину в другое место и начинаю вращать, то он как будто бы остался на месте.


Название: Re: Обрезка изображения
Отправлено: Igors от Ноябрь 05, 2012, 21:27
Поэтому я сделал:
QPointF LT = mapToParent(boundingRect().topLeft()) - offs
Ну Вы же boundingRect задавали в каких-то координатах (не знаю в каких). Вот в тех же координатах найдите верхний левый угол картинки и отнимите его oт topLeft - вот и получите нужную точку. По-любому Вам надо соскочить в систему координат имеджа, т.к. вырезка из него. Или подгоните проект - быстрее дело будет  


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 05, 2012, 21:41
В аттаче проект.
В коде много всякого хлама - не обращайте внимания. Класс signaller вообще не задействован. См. на класс Cropper. Вращение происходит колесиком - переопределен wheelEvent - при наведении мышки на квадрат. Если курсор вне квадрата, то ctrl+колесик - zoom (wheelEvent в классе photocontainer).
После запуска приложения выберите в поле sourcefolder папку, где есть файлы с изображениями (желательно, чтобы файлов других типов там не было).


Название: Re: Обрезка изображения
Отправлено: Igors от Ноябрь 05, 2012, 23:27
Для того как у Вас написано перевод такой
QPointF LT = mapToScene(QPointF(_drawingOrigenX, _drawingOrigenY)) - offs;
Код
C++ (Qt)
QPointF LT = trans.map(mapToScene(QPointF(_drawingOrigenX, _drawingOrigenY))) - offs;
 


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 06, 2012, 00:01
Для того как у Вас написано перевод такой
Код
C++ (Qt)
QPointF LT = mapToScene(QPointF(_drawingOrigenX, _drawingOrigenY)) - offs;
 

Все, разобрался. Правильно будет так:
Код:
 QPointF LT = trans.map(mapToScene(boundingRect().topLeft())) - offs;
Igors, еще раз большое спасибо за помощь!


Название: Re: Обрезка изображения
Отправлено: Igors от Ноябрь 06, 2012, 00:35
Код:
 QPointF LT = trans.map(mapToScene(boundingRect().topLeft())) - offs;
Совершенно верно, это я забыл trans. Не знаю зачем Вы крутите не за уголок в с заступом по 20 - ну навеерно так надо  :)

Дв, и вместо "\\" лучше QDir::separator(), а то я сначала никаких имеджей не наблюдал (не Вындоуз)


Название: Re: Обрезка изображения
Отправлено: alexey11111 от Ноябрь 06, 2012, 00:42
Да я просто на скорую руку пишу проект - срочно  нужен "обрезатель" для подготовки обучающей выборки, поэтому особо не заморачиваюсь на удобствах)))