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();
}


posted @ 2024-08-12 13:36  力能扛鼎的5270  阅读(104)  评论(0编辑  收藏  举报