一、要求:
1.利用Qt和QPainter实现一个图像处理程序,有菜单栏、工具栏和状态栏
2.有图像选择对话框,以选择和读取图像
3.状态栏显示图像的像素,位深,导入图像的路径和鼠标所在点的像素点坐标
4.可以对图像缩放,旋转,水平和垂直翻转,显示原图和全屏
二、思路和过程:
首先利用QAction实现菜单栏和工具栏的动作,并将这些动作加入到各自的栏目当中,然后设置四个Label控件放置状态栏中,以显示要求,部分代码如下:
openAction = new QAction(QIcon(tr(":/imgs/openfile.jpg")),tr("&Open..."),this);
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
exitAction = new QAction(QIcon(tr(":/imgs/exit.png")),tr("E&xit"),this);
connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
zoominAction = new QAction(QIcon(tr(":/imgs/zoomin.png")),tr("Zoom In"),this);
connect(zoominAction, SIGNAL(triggered()),this , SLOT(zoomIn()));
zoomoutAction = new QAction(QIcon(tr(":/imgs/zoomout.jpg")),tr("Zoom out"), this);
connect(zoomoutAction, SIGNAL(triggered()), this,SLOT(zoomOut()));
......
fileMenu = menuBar()->addMenu("&File");
fileMenu->addAction(openAction);
fileMenu->addAction(exitAction);
zoomToolBar = addToolBar("rotate");
zoomToolBar->addAction(r_rotateAction);
zoomToolBar->addAction(l_rotateAction);
statusBar()->addWidget(addressLabel);
statusBar()->addWidget(depthLabel);
statusBar()->addWidget(pixLabel);
statusBar()->addWidget(locationLabel);
之后,利用QScrollArea()设置背景,然后将一个自定义的CameraImage类放置于QScrollArea中,用于显示图片和实现相关功能。其中比较重要的几个知识点是QPixmap、Qtransform、QPainter和信道间通信传值的过程。
QPixmap
在这里,利用了Qpixmap 的load()方法加载图片,transform()方法实现图片的变换,而size()方法用于获取当前图像的大小
Qtransform
Qtransform的主要功能是控制二维坐标的变换,是一个3*3的矩阵,包括实现位移、缩放、扭曲和旋转,在这里我们使用rotate()来实现旋转功能,而translate用于实现平移。为了实现图像的镜像变换,我们利用toImage()方法获取image类型的图像,并且利用mirrored()来实现镜像。map()方法则是用于设置逻辑坐标和物理坐标的转换比例。
QPainter
QPainter是用于画图的控件,其中的QPen用于画图像的边缘部分,这里我们可以用drawLine()来画网格线,利用它的settransform()来获取当前的坐标系。
知道这些之后,我们就可以设置相应的坐标系以及变换了。将当前的图像放入QPainter中,然后利用transform()进行坐标变换,确定位置坐标,代码如下:
QTransform old = painter.transform();
QTransform current;
current.scale(xscale,xscale);//设置当前尺寸
painter.setTransform(current);//设置坐标系
m_trs = painter.worldTransform();//世界变化
QPointF logicpos = current.inverted().map(QPoint(edgeDistance,edgeDistance));//确定逻辑原点
painter.drawPixmap(logicpos, currentpixmap);//物理坐标
DrawGrid(painter, current);//划线
painter.setTransform(old);//恢复默认
通过这,我们就能够建立好坐标系了,再利用一个mousemoveEvent()事件,算出当前鼠标位置的坐标,利用信道——槽,将其传入到状态栏中:
QPointF physicalpos = event->pos()-QPointF(edgeDistance,edgeDistance);//以图片的起点为位置原点
pos = m_trs.inverted().map(physicalpos);//物理坐标转化为逻辑坐标
pos-=QPoint(0.5, 0.5);//以像素点中心点为原点
// qDebug()<<pos.x()<<pos.y();
emit mouseMove(pos);//发送信号
大致的,整个项目就完成了。
三、结果
原图:
这一章是放大后并显示点线的图像:
水平镜像对称:
顺时针旋转90度: