QT 的QImage裁剪图像--原始大小变换
用QPainter画出图像,画出要取出的矩形位置
1、选择框选的矩形区域:
2、裁剪框选的矩形区域的图像
头文件源码如下:
CusImageCrop.h
点击查看代码
`#pragma once
#include <QObject>
#include <QPaintEvent>
#include <QLabel>
#include <QMutex>
#include <QTimer>
#pragma execution_character_set("utf-8")
class CusImageCrop : public QLabel
{
Q_OBJECT
signals:
// 【信】需要重绘;
void sigUpdate();
//发送矩形框信息
void sigRectInfo(double x, double y, double wid, double hei);
void sigCalaRect(QPoint, QPoint);
public:
CusImageCrop(QWidget*parent);
~CusImageCrop();
//裁剪
QImage cutImg(QImage img, QRect rect);
QImage getSelectedImage() const;
QRectF getEffectRect();
void setShowImage(const QImage& img);
void setIsDrawing(bool isDraw) ;
// 通知重绘;
void redrawEmit() { emit sigUpdate(); };
private:
QPoint mapImgPoint(QPoint& pt);
public slots:
// 【槽】需要重绘;
void onUpdateSlot();
void onCalaRect(QPoint start, QPoint end);
protected:
void fitWindow();
void resizeEvent(QResizeEvent* resievt);
void mousePressEvent(QMouseEvent* evt);
void mouseReleaseEvent(QMouseEvent* evt);
void mouseDoubleClickEvent(QMouseEvent* evt);
void mouseMoveEvent(QMouseEvent* evt);
void paintEvent(QPaintEvent* paintEvt);
void enterEvent(QEvent* evt);
void dragEnterEvent(QDragEnterEvent* event);
void leaveEvent(QEvent* evt);
private:
bool m_bLeftPressed;
double m_dScaleX;
double m_dScaleY;
double m_dOffsetX;
double m_dOffsetY;
QTimer m_timer; // 时间刷新定时器;
QMutex m_muxImg;//关于m_pixToDraw的信号量
QMutex m_mtPaint;//m_sceneImg的信号量
QImage m_showImg; //显示的图像
QPixmap m_pixToDraw;
QImage m_sceneImg; //整个窗口图像,包括背景
QLabel* textLabel = new QLabel(this);
bool m_isDrawing = false;
bool m_startRect = false;
bool m_finishRect = false;
QPoint m_startPoint = QPoint(-1, -1);
QPoint m_endPoint = QPoint(-1, -1);
QRect m_selectionRect;
};
`
源文件如下:
CusImageCrop.cpp
点击查看代码
`#include "CusImageCrop.h"
#include <QImage>
#include <QRect>
#include <QPainter>
#include <QMouseEvent>
#include <QPainter>
#include <qmath.h>
#include <QMenu>
#include <QAction>
#include <qDebug>
#include <QTime>
#include <QElapsedTimer>
#define myDebug qDebug()<<QDateTime::currentDateTime().toString("[yyyyMMdd_hh:mm:ss:zzz]------> ")<<__FILE__<<__LINE__<<"=> "
CusImageCrop::CusImageCrop(QWidget*parent)
: QLabel(parent)
{
m_bLeftPressed = false;
m_dScaleX = 1;
m_dScaleY = 1;
m_dOffsetX = 0;
m_dOffsetY = 0;
m_showImg = QImage(1000, 1000, QImage::Format_RGB32);
setAcceptDrops(true);
setMouseTracking(true);
setContextMenuPolicy(Qt::CustomContextMenu);
m_timer.setInterval(1000);
m_timer.setSingleShot(false);
m_timer.start();
connect(&m_timer, &QTimer::timeout, this, &CusImageCrop::onUpdateSlot);
connect(this, &CusImageCrop::sigUpdate, this, &CusImageCrop::onUpdateSlot, Qt::QueuedConnection);
textLabel->resize(150, 40);
textLabel->setStyleSheet({ "border:none;color:#00ff00;background-color:transparent;" });
connect(this, &CusImageCrop::sigCalaRect, this, &CusImageCrop::onCalaRect);
}
CusImageCrop::~CusImageCrop()
{
}
// 【槽】需要重绘;
void CusImageCrop::onUpdateSlot()
{
update();
}
QImage CusImageCrop::cutImg(QImage img, QRect rect)
{
// 创建一个QPainter对象用于在原图上绘制
QPainter painter(&img);
// 设置画笔颜色和宽度
painter.setPen(Qt::red);
painter.setBrush(Qt::NoBrush);
// 使用copy()方法根据矩形裁剪图像
QImage croppedImage = img.copy(rect);
return croppedImage;
}
QImage CusImageCrop::getSelectedImage() const
{
return m_showImg.copy(m_selectionRect);
}
void CusImageCrop::setIsDrawing(bool isDraw)
{
m_isDrawing = isDraw;
}
QPoint CusImageCrop::mapImgPoint(QPoint& pt)
{
QRectF imgRect = getEffectRect();
// validation data validity
qreal dTmpX = 0, dTmpY = 0;
if (pt.x() <= imgRect.left()) {
dTmpX = imgRect.left();
}
else if (pt.x() >= imgRect.right()) {
dTmpX = imgRect.right();
}
else {
dTmpX = pt.x();
}
if (pt.y() <= imgRect.top()) {
dTmpY = imgRect.top();
}
else if (pt.y() >= imgRect.bottom()) {
dTmpY = imgRect.bottom();
}
else {
dTmpY = pt.y();
}
return QPoint((dTmpX - imgRect.left()) / m_dScaleX, (dTmpY - imgRect.top()) / m_dScaleY);
}
void CusImageCrop::setShowImage(const QImage& img)
{
int w = m_showImg.width();
int h = m_showImg.height();
m_muxImg.lock();
m_showImg = img;
m_pixToDraw = QPixmap::fromImage(m_showImg).copy();
m_muxImg.unlock();
if (img.width() != w || img.height() != h) {
fitWindow();
}
}
QRectF CusImageCrop::getEffectRect()
{
QMatrix tmpMat;
tmpMat.translate(m_dOffsetX, m_dOffsetY);
tmpMat.scale(m_dScaleX, m_dScaleY);
return tmpMat.mapRect(QRectF(0, 0, m_showImg.width(), m_showImg.height()));
}
void CusImageCrop::onCalaRect(QPoint start, QPoint end)
{
QPoint firstP = start;
firstP = mapImgPoint(firstP);
QPoint lastP = end;
lastP = mapImgPoint(lastP);
int x = qMin(firstP.x(), lastP.x());
int y = qMin(firstP.y(), lastP.y());
int w = qAbs(firstP.x() - lastP.x());
int h = qAbs(firstP.y() - lastP.y());
m_selectionRect = QRect(x, y, w, h);
emit sigRectInfo(x, y, w, h);
}
void CusImageCrop::fitWindow()
{
double imgWid = m_showImg.width();
double imgHei = m_showImg.height();
double clientWid = width();
double clientHei = height();
//计算放大和偏移
float rate_Img = imgWid / imgHei;
float rate_Client = clientWid / clientHei;
if (rate_Client > rate_Img)
{
//Y方向长度大于X方向长度的图像,适应Y方向,
//imgWid比imgHei等于_clientWid比clientHei按比例算出应该显示的宽度
m_dScaleX = clientHei / imgHei;
m_dScaleY = clientHei / imgHei;
m_dOffsetX = (clientWid - clientHei * rate_Img) / 2;
m_dOffsetY = 0;
}
else
{
//X方向长度大于Y方向长度的图像,
m_dScaleX = clientWid / imgWid;
m_dScaleY = clientWid / imgWid;
m_dOffsetX = 0;
m_dOffsetY = (clientHei - clientWid / rate_Img) / 2;
}
redrawEmit();
}
void CusImageCrop::resizeEvent(QResizeEvent* resievt)
{
fitWindow();
QLabel::resizeEvent(resievt);
}
void CusImageCrop::mousePressEvent(QMouseEvent* evt)
{
if (evt->button() == Qt::LeftButton)
{
m_bLeftPressed = true;
m_startPoint = evt->pos();
}
if (evt->button() == Qt::RightButton)
{
//m_endPoint = QPoint(-1, -1);
m_startPoint = QPoint(-1, -1);
m_bLeftPressed = false;
m_startRect = false;
m_finishRect = false;
}
QLabel::mousePressEvent(evt);
}
void CusImageCrop::mouseReleaseEvent(QMouseEvent* evt)
{
if (evt->button() == Qt::LeftButton)
{
m_finishRect = false;
//m_bLeftPressed = false;
}
QLabel::mouseReleaseEvent(evt);
}
void CusImageCrop::mouseDoubleClickEvent(QMouseEvent* evt)
{
QLabel::mouseDoubleClickEvent(evt);
}
void CusImageCrop::mouseMoveEvent(QMouseEvent* evt)
{
QElapsedTimer tm;
tm.restart();
if (m_bLeftPressed && m_isDrawing)
{
m_startRect = true;
if (!m_finishRect)
{
m_endPoint = evt->pos();
emit sigCalaRect(m_startPoint, m_endPoint);
m_finishRect = true;
}
}
else
{
m_startRect = false;
}
myDebug << QString("***mouseMoveEvent****耗时:%1ms;").arg(tm.elapsed());
QLabel::mouseMoveEvent(evt);
}
void CusImageCrop::enterEvent(QEvent* evt)
{
setCursor(QCursor(Qt::CrossCursor));
}
void CusImageCrop::paintEvent(QPaintEvent* paintEvt)
{
QElapsedTimer tm;
tm.restart();
m_mtPaint.lock();
int clientHei = height();
int clientWid = width();
//创建缓存图像
QImage sceneImg(clientWid, clientHei, QImage::Format_RGB32);
m_sceneImg = sceneImg;
QPainter painter(&m_sceneImg);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);//双线性插值
QPen pen(Qt::black, 1);
painter.setPen(pen);
QBrush brush(Qt::black);
painter.setBrush(brush);
painter.fillRect(0, 0, clientWid - 1, clientHei - 1, Qt::SolidPattern);
brush.setStyle(Qt::NoBrush);
painter.setBrush(brush);
QRectF mapRect = getEffectRect();
m_muxImg.lock();
//绘制图像
if (!m_showImg.isNull()) {
painter.drawPixmap(mapRect, m_pixToDraw, QRectF(0, 0, -1, -1));
}
m_muxImg.unlock();
if (m_startRect)
{
if ((m_bLeftPressed | m_finishRect) && (m_endPoint != m_startPoint) && (m_endPoint != QPoint(-1, -1)))
{
pen.setColor(QColor(0, 255, 0));
painter.setPen(pen);
QRect tempRect(m_startPoint, m_endPoint);
painter.drawRect(tempRect);
}
}
//绘制图像外边框
pen.setColor(QColor(255, 127, 39));
pen.setWidth(2);
painter.setPen(pen);
painter.drawRect(mapRect.left() + 1, mapRect.top() + 1, mapRect.width() - 2, mapRect.height() - 2);
pen.setWidth(1);
QPainter wndPainter(this);
wndPainter.drawImage(QRect(0, 0, clientWid, clientHei), m_sceneImg, QRect(0, 0, -1, -1));
m_mtPaint.unlock();
//myDebug << QString("-------------------*******耗时:%1ms;").arg(tm.elapsed());
}
void CusImageCrop::dragEnterEvent(QDragEnterEvent* event)
{
event->acceptProposedAction();
}
void CusImageCrop::leaveEvent(QEvent* evt)
{
textLabel->hide();
}