首页 > 其他分享 >裁剪图像--原始大小变换

裁剪图像--原始大小变换

时间:2024-08-12 13:39:17浏览次数:4  
标签:CusImageCrop -- void 裁剪 QPoint 图像 include evt QImage

用QPainter画出图像,画出要取出的矩形位置
头文件源码如下:
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();
}


标签:CusImageCrop,--,void,裁剪,QPoint,图像,include,evt,QImage
From: https://www.cnblogs.com/alisa5270/p/18354787

相关文章

  • 创业者教练:八个步骤指南
    如何成为一名创业者教练:八个步骤指南创业者教练是商业世界中一个日益重要的角色,他们帮助企业家和创业者实现目标,克服挑战,并发展他们的业务。如果您有兴趣成为一名创业者教练,以下是您需要遵循的八个步骤:第一步:了解创业者教练的角色创业者教练是专业人士,他们使用各种技术和策略来......
  • centos7 编译 Qt5.11.3
    默认环境gcc4.8.520150623qt5.9.7kernel3.10.0GNUlibc2.17更换系统源,在2024年6月30后停止更新维护,默认源不可用mvCentOS-Base.repoCentOS-Base.repo.backupwget-OCentOS-Base.repohttp://mirrors.cloud.tencent.com/repo/centos7_base.repowget-Oepel.repo......
  • 咪咕视频m3u8地址解析及ddCalcu参数加密逆向
    咪咕视频m3u8地址解析及ddCalcu参数加密逆向概述本文主要讲述咪咕视频m3u8地址的解析以及使用Wasm对视频的m3u8地址进行加密得到ddCalcu参数的方法。使用视频ID获取未加密的视频URL对咪咕视频进行抓包发现,通过接口https://webapi.miguvideo.com/gateway/playurl/v3/play/pla......
  • Vs+Qt添加ui子页面
    在Qt项目中,如果要实现一个弹出子界面并包含返回按钮的功能,最合适的选择是使用QtDialogFormFile来创建子界面。QtDialogFormFile与QtWidgetFormFile的区别QtDialogFormFile(ButtonBottom)和QtDialogFormFile(ButtonRight):这两种文件类型用于创建对话......
  • 【题解】P3356 火星探险问题
    \(\large\mathfrak{1st.\Preamble|}\)前言这都什么年代了网络流24题居然还能写题解!个人认为这篇题解讲的还是比较详细的。\(\large\mathfrak{2nd.\Solution|}\)题解看到题目的第一眼,我的反应是这样的:这不跟深海机器人问题差不多吗?Ctrl-CCtrl-V秒了。不过我还是讲讲怎......
  • 从字节到文件下载:揭秘 Spring 中 MultipartFile 的转换与浏览器端自动下载实现
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、下载功能核心Java代码二、代码解析1.设置Content-Disposition响应头2.设置Content-Type响应头3.写入文件内容到响应输出流4.文件写入到本地磁盘5.文件写入到Mnio中5.1主方法5.2实现......
  • k8s技术总结(一)
    在学习完docker之后,也很有必要再学习k8s的一些理论和技术。一、基础概念kubernetes(k8s)和docker在容器管理领域具有不同的侧重点和优势。当前docker主要关注单个容器的构建、运行和管理,而k8s则专注于大规模的容器编排和管理。k8s在以下几个特性中,更具有优势。特性1:自动化部署和......
  • 【顾邦小讲堂】第四期 带你深入理解功率MOSFET规格书中参数和图表(3)
    【由于网站编辑问题,文章中存在些许缩写及角标问题,还请大家见谅!如稍微介意,可转战我们的公众号阅读哦!(文章下方扫码关注)】        上一期我们学习了MOSFET RDS_ON的特性以及测试条件,就今天我们来看一下MOSFET另外两个重要的技术参数,热阻以及ID。        为何将......
  • 【顾邦小讲堂】第五期 带你深入理解功率MOSFET规格书中参数和图表(4)
    【由于网站编辑问题,文章中存在些许缩写及角标问题,还请大家见谅!如稍微介意,可转战我们的公众号阅读哦!(文章下方扫码关注)】        说到SOA,大部分工程师对这个图表是既陌生又熟悉。大家常用这个曲线簇来评判MOSFET(电源)工作于一些极限工况下时是否满足要求还能不炸管,但是......
  • SciTech-BigDataAIML-Machine Learning Tutorials
    MachineLearningTutorialsMachineLearningTutorialsThispagelistsallofthemachinelearningtutorialsavailableonStatology.IntroductiontoMachineLearningSupervisedvs.UnsupervisedLearningRegressionvs.ClassificationAlgorithmsTheBias-Var......