qt QPainter 实现图片的缩放和平移

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWidget>
#include <QtGui>
#include <QLabel>
#include <QPushButton>
#include <QComboBox>
#include <opencv2/opencv.hpp>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    enum  Type {
        None          = 0,
        Amplification ,
        Shrink,
        Lift,
        Right,
        Up,
        Down,
        Move
    };


public:

    cv::Mat img;
    cv::Mat imgchance;
    cv::Mat scalingImg(cv::Mat& mat, int INPUT_H, int INPUT_W);
    QImage matToImage(const cv::Mat& mat);
    QImage imgDst;

private:
    Ui::MainWindow *ui;
//    QPixmap  *pix;
    int action;          //动作(放大,缩小,移动...)
    int pixW;            //图片宽
    int pixH;            //图片高

    int lableW;      //lable 宽
    int lableH;      //lable 高

    QRect PaintRect;         //绘画区域
    QLabel label;

    float ratio;                //比例
    QPoint offset;              //一次的图片偏移值
    QPoint Alloffset;           //总偏移

    void AddComboItem(QComboBox* cmbo);
    bool event(QEvent * event);
    void wheelEvent(QWheelEvent* e);     //鼠标滑轮事件
private slots:
    void paintEvent(QPaintEvent *event);
};

#endif // MAINWINDOW_H

CPP

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLabel>
#include <QPushButton>
#include <QApplication>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    Alloffset(0,0)
{
    ui->setupUi(this);
    ratio= 1.0;             //初始化图片缩放比例
    action = MainWindow::None;
    lableW = pixW = 500;
    lableH = pixH = 900;
    QString path = "D:/Vscode_Project/Img/H_w.jpg";
    img = cv::imread(path.toStdString());
    imgchance = scalingImg(img,pixH,pixW);
    pixW = imgchance.cols;
    pixH = imgchance.rows;
    imgDst = matToImage(imgchance);
    PaintRect.setRect(ui->label->x()-1,ui->label->y()-1,lableW,lableH);

}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::event(QEvent * event)
{
    static bool press=false;
    static QPoint PreDot;

    if(event->type() == QEvent::MouseButtonPress )
    {
        QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);

        //判断鼠标是否是左键按下,且鼠标位置是否在绘画区域
        if(mouse->button()==Qt::LeftButton &&PaintRect.contains(mouse->pos()))
        {
            press=true;
            QApplication::setOverrideCursor(Qt::OpenHandCursor); //设置鼠标样式

            PreDot = mouse->pos();
        }

    }
    else if(event->type() == QEvent::MouseButtonRelease)
    {
        QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);

        //判断鼠标是否是左键释放,且之前是在绘画区域
        if(mouse->button()==Qt::LeftButton && press )
        {
            QApplication::setOverrideCursor(Qt::ArrowCursor); //改回鼠标样式
            press=false;
        }
    }

    if(event->type() == QEvent::MouseMove)              //移动图片
    {
        if(press)
        {
            QMouseEvent *mouse = dynamic_cast<QMouseEvent* >(event);

            offset.setX(mouse->x() - PreDot.x());
            offset.setY(mouse->y() - PreDot.y());
            PreDot = mouse->pos();
            action = MainWindow::Move;
            this->update();
        }
    }
    return QWidget::event(event);
}

void MainWindow::wheelEvent(QWheelEvent* event)     //鼠标滑轮事件
{
    if (event->delta()>0) {      //上滑,缩小

        action=MainWindow::Shrink;
        this->update();

    } else {                    //下滑,放大
        action=MainWindow::Amplification;
        this->update();
    }

    event->accept();
}



void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    int NowW = ratio *pixW;
    int NowH = ratio *pixH;

    if(action==MainWindow::Amplification)           //缩小
    {
        ratio-=0.1*ratio;
        if(ratio<0.18)
            ratio = 0.1;


    }
    else  if(action==MainWindow::Shrink)           //放大
    {

        ratio+=0.1*ratio;
        if(ratio>4.5)
            ratio = 5.000;


    }
    if(action==MainWindow::Amplification || action==MainWindow::Shrink)      //更新图片
    {
        NowW = ratio *pixW;
        NowH = ratio *pixH;
        action=MainWindow::None;
        imgchance = scalingImg(img,NowH,NowW);
        imgDst = matToImage(imgchance);

    }

    if(action==MainWindow::Move)                    //移动
    {
        int offsetx=Alloffset.x()+offset.x();
        Alloffset.setX(offsetx);

        int offsety=Alloffset.y()+offset.y();
        Alloffset.setY(offsety);
        action=MainWindow::None;
    }

    if(abs(Alloffset.x())>=(lableW/2 + NowW/2 -10))    //限制X偏移值
    {
        if(Alloffset.x()>0)
            Alloffset.setX(lableW/2 + NowW/2 -10);
        else
            Alloffset.setX(-lableW/2 + -NowW/2 +10);
    }
    if(abs(Alloffset.y())>=(lableH/2 + NowH/2 -10))    //限制Y偏移值
    {
        if(Alloffset.y()>0)
            Alloffset.setY(lableH/2 + NowH/2 -10);
        else
            Alloffset.setY(-lableH/2 + -NowH/2 +10);

    }

    int x = lableW/2 + Alloffset.x() -NowW/2;
    if(x<0)
        x=0;


    int y = lableH/2 + Alloffset.y() -NowH/2;
    if(y<0)
        y=0;

    int  sx = NowW/2 - lableW/2 - Alloffset.x();
    if(sx<0)
        sx=0;

    int  sy = NowH/2 - lableH/2 - Alloffset.y();
    if(sy<0)
        sy=0;


    int w =(NowW - sx)>lableW? lableW : (NowW - sx);
    if(w>(lableW-x))
        w = lableW-x;

    int h =(NowH - sy)>lableH? lableH : (NowH - sy);
    if(h>(lableH-y))
        h = lableH-y;
    qDebug()<<"start w "<<w;
    qDebug()<<"start h "<<h;

    NowW = ratio *pixW;
    NowH = ratio *pixH;
    action=MainWindow::None;
    imgchance = scalingImg(img,NowH,NowW);
    imgDst = matToImage(imgchance);

    painter.drawRect(ui->label->x()-1,ui->label->y()-1,lableW,lableH); //画框

    painter.drawTiledPixmap(x+ui->label->x(),y+ui->label->y(),w,h,QPixmap::fromImage(imgDst),sx,sy);
    qDebug()<<"       ";
    qDebug()<<"drawTiledPixmap w "<<w;
    qDebug()<<"drawTiledPixmap h "<<h;
//    qDebug()<<"imgchance w "<<imgchance.cols;
//    qDebug()<<"imgchance h "<<imgchance.rows;




}


cv::Mat MainWindow::scalingImg(cv::Mat& mat, int INPUT_H, int INPUT_W)
{

    int nh = mat.rows;
    int nw = mat.cols;
    double divisor;
    double m_nh = nh / 1.0 / INPUT_H;
    double m_nw = nw / 1.0 / INPUT_W;
    divisor = (m_nh > m_nw ? m_nh : m_nw);
    cv::Mat image = mat.clone();
    cv::Mat image_resize; // 等比例缩放图
    //图片要缩:INTER_AREA  图片要放:INTER_CUBIC
    if (nh > INPUT_H || nw > INPUT_W)
    {
        cv::resize(image, image_resize, cv::Size(nw / divisor, nh / divisor), cv::INTER_AREA);
    }
    else
    {
        cv::resize(image, image_resize, cv::Size(nw / divisor, nh / divisor), cv::INTER_CUBIC);
    }
    return image_resize;
}

QImage MainWindow::matToImage(const cv::Mat& mat)
{
    if (mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        image.setColorCount(256);
        for (int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        uchar* pSrc = mat.data;
        for (int row = 0; row < mat.rows; row++)
        {
            uchar* pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    else if (mat.type() == CV_8UC3)
    {

        const uchar* pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_BGR888);
        return image.rgbSwapped();
    }
    else if (mat.type() == CV_8UC4)
    {
        cv::cvtColor(mat, mat, cv::COLOR_BGRA2RGBA);
        const uchar* pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image;

    }
    else
    {
        return QImage();
    }
}

lable 不是必要的,设置好关键的2个值最重要

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我可以给你提供一个简单的示例程序,演示如何在Qt实现四张图片环视全景拼接。请注意,这是一个简单的示例程序,仅供参考。你需要根据自己的实际需求进行修改和完善。 ```cpp #include <QApplication> #include <QGraphicsScene> #include <QGraphicsView> #include <QPixmap> #include <QPainter> #include <QTransform> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 加载四张图片 QPixmap img1(":/images/img1.jpg"); QPixmap img2(":/images/img2.jpg"); QPixmap img3(":/images/img3.jpg"); QPixmap img4(":/images/img4.jpg"); // 计算全景图的大小 int w = img1.width() + img2.width() + img3.width() + img4.width(); int h = qMax(qMax(img1.height(), img2.height()), qMax(img3.height(), img4.height())); // 创建全景图的Pixmap对象 QPixmap panorama(w, h); panorama.fill(Qt::black); // 绘制四张图片到全景图中 QPainter painter(&panorama); painter.drawPixmap(0, 0, img1); painter.drawPixmap(img1.width(), 0, img2); painter.drawPixmap(img1.width() + img2.width(), 0, img3); painter.drawPixmap(img1.width() + img2.width() + img3.width(), 0, img4); // 创建Graphics View和Scene,显示全景图 QGraphicsScene scene; QGraphicsPixmapItem item(panorama); scene.addItem(&item); QGraphicsView view(&scene); view.show(); // 设置Graphics View的属性,使其支持拖拽和缩放 view.setDragMode(QGraphicsView::ScrollHandDrag); view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); view.setRenderHint(QPainter::SmoothPixmapTransform); view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse); view.setResizeAnchor(QGraphicsView::AnchorUnderMouse); view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setInteractive(true); view.setDragMode(QGraphicsView::ScrollHandDrag); view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, true); // 设置全景图的初始旋转角度和平移距离 item.setRotation(-90); item.setPos(-w / 2, -h / 2); return a.exec(); } ``` 在这个示例程序中,我们首先加载了四张图片,然后计算出全景图的大小。接下来,我们创建了一个QPixmap对象,将四张图片绘制到这个QPixmap对象中。然后,我们创建了一个QGraphicsScene对象,并将这个QPixmap对象添加到这个场景中。最后,我们创建了一个QGraphicsView对象,将这个场景显示到这个视图中,并设置了一些属性,使其支持拖拽和缩放。我们还设置了全景图的初始旋转角度和平移距离,以实现环视全景图的效果。 请注意,这个示例程序仅供参考。你需要根据自己的实际需求进行修改和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值