Ai
3 Star 30 Fork 15

haumingl/OptiKinetiq-Platform

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
HaumDisplayWindow.cs 71.62 KB
一键复制 编辑 原始数据 按行查看 历史
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OptikinetiqControls
{
/// <summary>
/// 显示模式
/// </summary>
enum DisplayMode
{
/// <summary>
/// 像素级
/// </summary>
Pixel,
/// <summary>
/// 高质量
/// </summary>
HighQuality
}
/// <summary>
/// 操作模式
/// </summary>
enum DrawMode
{
/// <summary>
/// 点
/// </summary>
Point,
/// <summary>
/// 线
/// </summary>
Line,
/// <summary>
/// 矩形
/// </summary>
Rectangle,
/// <summary>
/// 旋转矩形
/// </summary>
RotateRect,
/// <summary>
/// 椭圆
/// </summary>
Ellipse,
/// <summary>
/// 圆
/// </summary>
Circle,
/// <summary>
/// 多边形
/// </summary>
Polygon,
/// <summary>
/// 无操作
/// </summary>
None
}
enum DrawState
{
/// <summary>
/// 开始
/// </summary>
Start,
/// <summary>
/// 绘制中
/// </summary>
Drawing,
/// <summary>
/// 完成
/// </summary>
Finish,
/// <summary>
/// 移动中
/// </summary>
Moving,
/// <summary>
/// 绘制线起点拖动
/// </summary>
StartDraging,
/// <summary>
/// 绘制线终点拖动
/// </summary>
EndDraging,
/// <summary>
/// 圆形缩放拖动
/// </summary>
ScaleDraging,
/// <summary>
/// 矩形上边拖动
/// </summary>
TopDraging,
/// <summary>
/// 矩形下边拖动
/// </summary>
BottomDraging,
/// <summary>
/// 矩形左边拖动
/// </summary>
LeftDraging,
/// <summary>
/// 矩形右边拖动
/// </summary>
RightDraging,
/// <summary>
/// 矩形右下角拖动
/// </summary>
BrDraging,
/// <summary>
/// 旋转
/// </summary>
Rotate,
Done,
}
public partial class HaumDisplayWindow : UserControl
{
private Bitmap cloneBmp;
/// <summary>
/// 显示图像
/// </summary>
public Bitmap imageBmp;
/// <summary>
/// 图片文件路径
/// </summary>
public string imageFilePath;
/// <summary>
/// 缩放比例
/// </summary>
private float scaleF = 1.0f;
/// <summary>
/// 开始移动时鼠标位置
/// </summary>
private Point startMovePosition = Point.Empty;
/// <summary>
/// 当前图像基于原图偏移量
/// </summary>
private PointF offset = Point.Empty;
/// <summary>
/// 图像显示模式 : 高质量(平滑处理锯齿不失真), 像素级(能够清晰显示每一个像素,锯齿边缘明显,适合查看像素坐标与rgb值)
/// </summary>
private DisplayMode viewMode = DisplayMode.Pixel;
/// <summary>
/// 操作模式:记录操作模式或当前绘制图型类型
/// </summary>
private DrawMode operatorMode = DrawMode.None;
/// <summary>
/// 绘制状态标志位
/// </summary>
private DrawState drawState = DrawState.Done;
/// <summary>
/// 画笔粗细
/// </summary>
private int penSize = 1;
/// <summary>
/// 画笔颜色
/// </summary>
private Color penColor = Color.Green;
/// <summary>
/// 绘制点对象
/// </summary>
private DrawPoint drawPoint;
/// <summary>
/// 绘制线对象
/// </summary>
private DrawLine drawLine;
/// <summary>
/// 绘制矩形对象
/// </summary>
private DrawRectangle drawRectangle;
/// <summary>
/// 绘制椭圆
/// </summary>
private DrawEllipse drawEllipse;
/// <summary>
/// 绘制圆对象
/// </summary>
private DrawCircle drawCircle;
/// <summary>
/// 绘制多边形对象
/// </summary>
private DrawPolygon drawPolygon;
/// <summary>
/// 绘制可旋转矩形
/// </summary>
private DrawRotateRect drawRotateRect;
/// <summary>
/// 旋转光标
/// </summary>
private Cursor rotateCursor;
/// <summary>
/// 计时器
/// </summary>
private Stopwatch sw = new Stopwatch();
/// <summary>
/// 灰度直方器
/// </summary>
public IGrayscaleHistogram grayscaleHistogram;
/// <summary>
/// 初始化控件
/// </summary>
public HaumDisplayWindow()
{
InitializeComponent();
//绑定显示控件鼠标滑动事件 进行缩放
mainView.MouseWheel += mainView_MouseWheel;
// 启用控件双缓冲 防止控件重绘闪烁
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
//初始化旋转弧形鼠标样式
// 加载自定义光标文件,这里假设你有一个名为 custom_cursor.cur 的光标文件在项目目录下
using (MemoryStream ms = new MemoryStream(Properties.Resources.弧线))
{
rotateCursor = new Cursor(ms);
}
}
/// <summary>
/// 显示图片
/// </summary>
/// <param name="image">图片</param>
public void ShowImage(Bitmap image)
{
imageBmp = image;
cloneBmp = image;
this.Fit();
int width = image.Width;
int height = image.Height;
this.toolStripLabel1.Text = $"{width},{height}";
}
/// <summary>
/// 图像自适应
/// </summary>
public void Fit()
{
if (imageBmp == null) { return; }
//计算控件与图像的宽高比例
float scaleX = (float)(mainView.Width - 2) / imageBmp.Width;
float scaleY = (float)(mainView.Height - 2) / imageBmp.Height;
//获取较小的一边比例作为缩放比例
scaleF = Math.Min(scaleX, scaleY);
//计算缩放后的图像宽高值
int newWidth = (int)(imageBmp.Width * scaleF);
int newHeight = (int)(imageBmp.Height * scaleF);
//计算图像居中显示的位置
offset.X = (mainView.Width - newWidth) / 2;
offset.Y = (mainView.Height - newHeight) / 2;
//触发自身的Point方法进行控件重绘
mainView.Invalidate();
}
/// <summary>
/// 导入图片
/// </summary>
private void ImportImage()
{
//打开文件对话框进行选择图片并触发显示控件重绘
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Filter = "图像文件(*.bmp;*.png;*.jpg;*.jpeg;*.tiff)|*.bmp;*.png;*.jpg;*.jpeg;*.tiff|所有文件(*.*)|*.*";
ofd.Title = "选择导入并显示图片";
if (ofd.ShowDialog() == DialogResult.OK)
{
this.ShowImage(new Bitmap(ofd.FileName));
imageFilePath = ofd.FileName;
this.Fit();
}
}
}
/// <summary>
/// 移除图片
/// </summary>
private void RemoveImage()
{
if (imageBmp == null)
{
return;
}
imageBmp = null;
//cloneBmp = null;
mainView.Invalidate();
}
/// <summary>
/// 保存图片
/// </summary>
private bool SaveImage()
{
if (imageBmp == null)
{
return false;
}
//打开保存文件对话框保存图片
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Title = "保存图片到:";
sfd.DefaultExt = "bmp";
sfd.CheckPathExists = true;
sfd.Filter = "BMP|*.bmp|PNG|*.png|JPG|*.jpg|JPEG|*.jpeg|TIFF|*.tiff";
if (sfd.ShowDialog() == DialogResult.OK)
{
try
{
string extension = Path.GetExtension(sfd.FileName);
switch (extension.ToLower())
{
case ".bmp":
imageBmp.Save(sfd.FileName, ImageFormat.Bmp);
break;
case ".png":
imageBmp.Save(sfd.FileName, ImageFormat.Png);
break;
case ".jpg":
case ".jpeg":
imageBmp.Save(sfd.FileName, ImageFormat.Jpeg);
break;
case ".tiff":
imageBmp.Save(sfd.FileName, ImageFormat.Tiff);
break;
default:
break;
}
}
catch (Exception ex) {
return false;
}
}
}
return true;
}
private void ImageSaveByExtension(Image image, string Extension)
{
}
/// <summary>
/// 保存图片
/// </summary>
/// <param name="dir">文件夹路径</param>
/// <param name="name">文件名(带后缀)</param>
/// <param name="quality">压缩质量:当文件后缀名为jpg或jpeg时自动启用 取值范围(最差)0-100(最优)</param>
private void Save(string dir, string name, byte quality = 100)
{
string extension = Path.GetExtension(name);
//如果图像不存在或文件后缀不合理直接返回
if (imageBmp == null || extension == null || extension == string.Empty)
{
return;
}
//判断文件夹是否存在,如果不存在先创建文件夹
Directory.CreateDirectory(dir);
//组合保存全路径
string fullPath = Path.Combine(dir, name);
//将文件后缀名转小写
extension = extension.Trim().ToLower();
//判断文件后缀是否需要保存压缩
if (extension.Equals(".jpg") || extension.Equals(".jpeg"))
{
// 获取 JPEG 编码器
ImageCodecInfo jpegCodecInfo = GetEncoderInfo("image/jpeg");
// 创建 EncoderParameters 对象,设置压缩质量
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
imageBmp.Save(fullPath, jpegCodecInfo, encoderParameters);
}
//不进行压缩
else
{
imageBmp.Save(fullPath);
}
}
/// <summary>
/// 检索图像编码器与解码器
/// </summary>
/// <param name="mimeType">"image/jpeg"</param>
/// <returns>ImageCodecInfo / None</returns>
private ImageCodecInfo GetEncoderInfo(string mimeType)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
for (int i = 0; i < codecs.Length; i++)
{
if (codecs[i].MimeType == mimeType)
{
return codecs[i];
}
}
return null;
}
/// <summary>
/// 判断鼠标是否在某一个控件上方
/// </summary>
/// <param name="e"></param>
/// <param name="control"></param>
/// <returns></returns>
private bool IsMouseOnCtrl(MouseEventArgs e, Control control)
{
int lx = 0;
int ly = 0;
int width = control.Width;
int height = control.Height;
if (e.X >= lx && e.X < width && e.Y >= ly && e.Y < height)
{
return true;
}
else
{
return false;
}
}
private void mainView_MouseMove(object sender, MouseEventArgs e)
{
if (imageBmp == null) { return; }
//实时计算拖动图片后的鼠标位置并重绘
if (mainView.Cursor == Cursors.Hand && e.Button == MouseButtons.Left && operatorMode == DrawMode.None)
{
Console.WriteLine("拖动图片中...");
int dx = e.X - startMovePosition.X;
int dy = e.Y - startMovePosition.Y;
if (Math.Abs(dx) > 1 || Math.Abs(dy) > 1)
{
offset.X += dx;
offset.Y += dy;
startMovePosition = e.Location;
}
}
//按住Ctrl键实时计算当前鼠标位置的像素值并显示
if (Control.ModifierKeys == Keys.Control && IsMouseOnCtrl(e, mainView))
{
Console.WriteLine($"正在按住Ctrl... X:{e.X} Y:{e.Y}");
//默认提示信息
string info = $"X:-- Y:-- \n\rR:-- G:-- B--";
// 计算鼠标在原始图片上的位置
PointF imagePoint = ScreenTransImagePointF(e.Location);
// 检查相对位置是否在图片范围内
if (imagePoint.X >= 0 && imagePoint.X < imageBmp.Width &&
imagePoint.Y >= 0 && imagePoint.Y < imageBmp.Height)
{
//获取图像上位置的RGB值
Color pixelColor = imageBmp.GetPixel((int)imagePoint.X, (int)imagePoint.Y);
//组合提示信息
info = $"X:{(int)imagePoint.X} Y:{(int)imagePoint.Y} \n\rR:{pixelColor.R} G:{pixelColor.G} B:{pixelColor.B}";
}
//显示提示
toolTip.Show(info, mainView, e.Location.X + 10, e.Location.Y + 15);
}
else
{
toolTip.Hide(mainView);
}
switch (operatorMode)
{
case DrawMode.Point:
DrawPoint(e);
break;
case DrawMode.Line:
DrawLine(e);
break;
case DrawMode.Rectangle:
DrawRectangle(e);
break;
case DrawMode.Circle:
DrawCircle(e);
break;
case DrawMode.RotateRect:
DrawRotateRect(e);
break;
case DrawMode.Polygon:
DrawPolygon(e);
break;
}
mainView.Invalidate();
}
private bool IsMouseOnImage(Point mouseLocation)
{
PointF imageLoca = ScreenTransImagePointF(mouseLocation);
if (imageLoca.X >= 0 && imageLoca.X < imageBmp.Width && imageLoca.Y >= 0 && imageLoca.Y < imageBmp.Height)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 鼠标滚轮滚动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void mainView_MouseWheel(object sender, MouseEventArgs e)
{
if (imageBmp != null)
{
float zoomFactor = e.Delta > 0 ? 1.1f : 0.9f;
float oldScale = scaleF;
scaleF *= zoomFactor;
// 限制缩放范围
if (scaleF < 0.01f) scaleF = 0.01f;
if (scaleF > 100.0f) scaleF = 100.0f;
// 根据鼠标位置调整偏移量
float dx = (float)e.X - offset.X;
float dy = (float)e.Y - offset.Y;
offset.X -= dx * (scaleF / oldScale - 1);
offset.Y -= dy * (scaleF / oldScale - 1);
mainView.Invalidate();
}
}
/// <summary>
/// 将控件坐标点转为图像坐标点
/// </summary>
/// <param name="screenPoint">一个控件坐标点</param>
/// <returns>图像坐标</returns>
private PointF ScreenTransImagePointF(Point screenPoint)
{
// 计算鼠标在原始图片上的相对位置
float relativeX = (screenPoint.X - offset.X) / scaleF;
float relativeY = (screenPoint.Y - offset.Y) / scaleF;
return new PointF(relativeX, relativeY);
}
/// <summary>
/// 将图像坐标点转为控件坐标点
/// </summary>
/// <param name="imagePoint">一个图像坐标点</param>
/// <returns>控件坐标</returns>
private Point ImageTransScreenPoint(Point imagePoint)
{
float relativeX = imagePoint.X * scaleF + offset.X;
float relativeY = imagePoint.Y * scaleF + offset.Y;
return new Point((int)relativeX, (int)relativeY);
}
/// <summary>
/// 将图像坐标点转为控件坐标点
/// </summary>
/// <param name="imagePoint">一个图像坐标点</param>
/// <returns>控件坐标</returns>
private PointF ImageTransScreenPointF(PointF imagePoint)
{
float relativeX = imagePoint.X * scaleF + offset.X;
float relativeY = imagePoint.Y * scaleF + offset.Y;
return new PointF(relativeX, relativeY);
}
/// <summary>
/// 将图像坐标点集转为控件坐标点集
/// </summary>
/// <param name="imagePoint">一个图像坐标点</param>
/// <returns>控件坐标</returns>
private List<PointF> ImageTransScreenPointF(List<PointF> imagePoints)
{
List<PointF> ps = new List<PointF>();
for (int i = 0; i < imagePoints.Count; i++)
{
PointF p = ImageTransScreenPointF(imagePoints[i]);
ps.Add(p);
}
return ps;
}
private void PaintPoint(PaintEventArgs e)
{
using (Pen pen = new Pen(drawPoint.penColor, drawPoint.penSize))
{
PointF controlPoint = ImageTransScreenPointF(drawPoint.point);
float length = 5 * scaleF;
// 绘制垂直的线(中心点上下各 5 像素)
e.Graphics.DrawLine(pen, controlPoint.X, controlPoint.Y - length, controlPoint.X, controlPoint.Y + length);
// 绘制水平的线(中心点左右各 5 像素)
e.Graphics.DrawLine(pen, controlPoint.X - length, controlPoint.Y, controlPoint.X + length, controlPoint.Y);
}
}
private void PaintLine(PaintEventArgs e)
{
using (Pen pen = new Pen(drawLine.penColor, drawLine.penSize))
{
using (Pen selectPen = new Pen(drawLine.isSelect ? drawLine.selectColor : drawLine.penColor, drawLine.penSize + 1))
{
//绘制起点中点终点
PointF start = ImageTransScreenPointF(drawLine.startPoint);
PointF center = ImageTransScreenPointF(drawLine.GetCenter());
PointF end = ImageTransScreenPointF(drawLine.endPoint);
e.Graphics.DrawEllipse(selectPen, start.X - 1, start.Y - 1, 2, 2);
e.Graphics.DrawEllipse(selectPen, center.X - 1, center.Y - 1, 2, 2);
e.Graphics.DrawEllipse(selectPen, end.X - 1, end.Y - 1, 2, 2);
// 箭头长度
float arrowLength = 10 * scaleF;
// 箭头角度(V 型开口角度)
float arrowAngle = 30;
// 箭头朝向角度(相对于水平向右为 0 度)
float orientationAngle = drawLine.GetRotate();
// 将角度转换为弧度
float arrowAngleRadians = arrowAngle * (float)Math.PI / 180;
float orientationAngleRadians = orientationAngle * (float)Math.PI / 180;
// 尖角点位置
PointF tipPoint = center;
// 计算 V 型箭头的另外两个点
float halfAngle = arrowAngleRadians / 2;
PointF point1 = new PointF(
tipPoint.X - arrowLength * (float)Math.Cos(orientationAngleRadians - halfAngle),
tipPoint.Y - arrowLength * (float)Math.Sin(orientationAngleRadians - halfAngle)
);
PointF point2 = new PointF(
tipPoint.X - arrowLength * (float)Math.Cos(orientationAngleRadians + halfAngle),
tipPoint.Y - arrowLength * (float)Math.Sin(orientationAngleRadians + halfAngle)
);
//绘制尖角两条线形成指向箭头
e.Graphics.DrawLine(pen, tipPoint, point1);
e.Graphics.DrawLine(pen, tipPoint, point2);
}
PointF lineStart = ImageTransScreenPointF(drawLine.startPoint);
PointF lineEnd = ImageTransScreenPointF(drawLine.endPoint);
e.Graphics.DrawLine(pen, lineStart, lineEnd);
}
}
private void PaintRectangle(PaintEventArgs e)
{
using (Pen pen = new Pen(drawRectangle.penColor, drawRectangle.penSize))
{
using (Pen selectPen = new Pen(drawRectangle.isSelect ? drawRectangle.selectColor : drawRectangle.penColor, drawRectangle.penSize + 1))
{
//获取圆心像素坐标 转换成控件坐标
PointF center = ImageTransScreenPointF(drawRectangle.GetCenter());
//根据中心坐标拟合两条垂直线
// 绘制垂直的线(中心点上下各 3 像素)
e.Graphics.DrawLine(selectPen, center.X, center.Y - drawRectangle.GetCenterSize() * scaleF, center.X, center.Y + drawRectangle.GetCenterSize() * scaleF);
// 绘制水平的线(中心点左右各 3 像素)
e.Graphics.DrawLine(selectPen, center.X - drawRectangle.GetCenterSize() * scaleF, center.Y, center.X + drawRectangle.GetCenterSize() * scaleF, center.Y);
PointF br = ImageTransScreenPointF(drawRectangle.GetBR());
e.Graphics.DrawEllipse(selectPen, br.X - 1, br.Y - 1, 2, 2);
}
PointF rectTlLoca = ImageTransScreenPointF(drawRectangle.GetTL());
PointF rectBrLoca = ImageTransScreenPointF(drawRectangle.GetBR());
e.Graphics.DrawRectangle(pen, rectTlLoca.X, rectTlLoca.Y, rectBrLoca.X - rectTlLoca.X, rectBrLoca.Y - rectTlLoca.Y);
}
}
private void PaintCircle(PaintEventArgs e)
{
using (Pen pen = new Pen(drawCircle.penColor, drawCircle.penSize))
{
using (Pen selectPen = new Pen(drawCircle.isSelect ? drawCircle.selectColor : drawCircle.penColor, drawCircle.penSize + 1))
{
//绘制圆心小十字
//获取圆心像素坐标 转换成控件坐标
PointF center = ImageTransScreenPointF(drawCircle.center);
//根据中心坐标拟合两条垂直线
// 绘制垂直的线(中心点上下各 3 像素)
e.Graphics.DrawLine(selectPen, center.X, center.Y - drawCircle.GetCenterSize() * scaleF, center.X, center.Y + drawCircle.GetCenterSize() * scaleF);
// 绘制水平的线(中心点左右各 3 像素)
e.Graphics.DrawLine(selectPen, center.X - drawCircle.GetCenterSize() * scaleF, center.Y, center.X + drawCircle.GetCenterSize() * scaleF, center.Y);
PointF rightPoint = ImageTransScreenPointF(drawCircle.GetScalePoint());
//绘制拖动缩放点
e.Graphics.DrawEllipse(selectPen, rightPoint.X - 1, rightPoint.Y - 1, 2, 2);
}
//圆的中心坐标转控件坐标
PointF rectTL = ImageTransScreenPointF(drawCircle.GetRectTL());
PointF rectBR = ImageTransScreenPointF(drawCircle.GetRectBR());
SizeF size = new SizeF(rectBR.X - rectTL.X, rectBR.Y - rectTL.Y);
e.Graphics.DrawEllipse(pen, new RectangleF(rectTL, size));
}
}
private void PaintRotateRect(PaintEventArgs e)
{
using (Pen pen = new Pen(drawRotateRect.penColor, drawRotateRect.penSize))
{
//绘制矩形
PointF[] corners = drawRotateRect.GetCorners();
List<PointF> cornersScr = new List<PointF>();
for (int i = 0; i < corners.Length; i++)
{
cornersScr.Add(ImageTransScreenPointF(corners[i]));
}
e.Graphics.DrawPolygon(pen, cornersScr.ToArray());
using (Pen selectPen = new Pen(drawRotateRect.isSelect ? drawRotateRect.selectColor : drawRotateRect.penColor, drawRotateRect.penSize + 1))
{
//绘制圆心小十字
//获取圆心像素坐标 转换成控件坐标
PointF center = ImageTransScreenPointF(drawRotateRect.center);
//根据中心坐标拟合两条垂直线
// 绘制垂直的线(中心点上下各 3 像素)
e.Graphics.DrawLine(selectPen, center.X, center.Y - drawRotateRect.GetCenterSize() * scaleF, center.X, center.Y + drawRotateRect.GetCenterSize() * scaleF);
// 绘制水平的线(中心点左右各 3 像素)
e.Graphics.DrawLine(selectPen, center.X - drawRotateRect.GetCenterSize() * scaleF, center.Y, center.X + drawRotateRect.GetCenterSize() * scaleF, center.Y);
PointF tr = ImageTransScreenPointF(drawRotateRect.tr);
e.Graphics.DrawEllipse(selectPen, tr.X - 1, tr.Y - 1, 2, 2);
PointF rc = ImageTransScreenPointF(drawRotateRect.GetRightCenter());
e.Graphics.DrawEllipse(selectPen, rc.X - 1, rc.Y - 1, 2, 2);
PointF bc = ImageTransScreenPointF(drawRotateRect.GetBottomCenter());
e.Graphics.DrawEllipse(selectPen, bc.X - 1, bc.Y - 1, 2, 2);
}
}
}
private void PaintPolygon(PaintEventArgs e)
{
using (Pen pen = new Pen(penColor, penSize))
{
//绘制路径
List<PointF> ps = ImageTransScreenPointF(drawPolygon.polygonPath);
if (drawPolygon.polygonPath.Count >= 2)
{
e.Graphics.DrawLines(pen, ps.ToArray());
}
using (Pen selectPen = new Pen(drawPolygon.isSelect ? drawPolygon.selectColor : drawPolygon.penColor, drawPolygon.penSize + 1))
{
//绘制中心小十字
//获取圆心像素坐标 转换成控件坐标
PointF center = ImageTransScreenPointF(drawPolygon.GetCenter());
//根据中心坐标拟合两条垂直线
// 绘制垂直的线(中心点上下各 3 像素)
e.Graphics.DrawLine(selectPen, center.X, center.Y - drawPolygon.GetCenterSize() * scaleF, center.X, center.Y + drawPolygon.GetCenterSize() * scaleF);
// 绘制水平的线(中心点左右各 3 像素)
e.Graphics.DrawLine(selectPen, center.X - drawPolygon.GetCenterSize() * scaleF, center.Y, center.X + drawPolygon.GetCenterSize() * scaleF, center.Y);
foreach (PointF p in ps)
{
//绘制拖动缩放点
e.Graphics.DrawEllipse(selectPen, p.X - 1, p.Y - 1, 2, 2);
}
}
}
}
/// <summary>
/// 控件重绘
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void mainView_Paint(object sender, PaintEventArgs e)
{
sw.Restart();
if (imageBmp != null)
{
// 计算缩放后的图片大小
int newWidth = (int)(imageBmp.Width * scaleF);
int newHeight = (int)(imageBmp.Height * scaleF);
// 判断显示模式设置绘制质量
if (viewMode == DisplayMode.Pixel)
{
e.Graphics.SmoothingMode = SmoothingMode.None;
e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
}
else
{
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
}
// 绘制缩放后的图片
e.Graphics.DrawImage(imageBmp, offset.X, offset.Y, newWidth, newHeight);
//更新缩放率
toolStripSplitButton_scale.Text = $"{(scaleF * 100).ToString("0")}%";
if (drawPoint != null)
{
PaintPoint(e);
}
if (drawLine != null)
{
PaintLine(e);
}
if (drawCircle != null)
{
PaintCircle(e);
}
if (drawEllipse != null)
{
}
if (drawRectangle != null)
{
PaintRectangle(e);
}
if (drawRotateRect != null)
{
PaintRotateRect(e);
}
if (drawPolygon != null && drawPolygon.polygonPath.Count > 0)
{
PaintPolygon(e);
}
}
sw.Stop();
if (sw.ElapsedMilliseconds > 0)
{
Console.WriteLine("重绘耗时ms:" + sw.ElapsedMilliseconds + " fps:" + 1000 / sw.ElapsedMilliseconds);
}
}
private void mainView_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && mainView.Cursor == Cursors.Hand)
{
startMovePosition = e.Location;
}
if (e.Button == MouseButtons.Right && operatorMode == DrawMode.None && drawState == DrawState.Done)
{
contextMenuStrip_menu.Show(mainView, e.Location);
Point testPoint = ImageTransScreenPoint(new Point(0, 0));
Console.WriteLine($" Sx:{testPoint.X} Sy:{testPoint.Y}");
}
switch (operatorMode)
{
case DrawMode.Point:
DrawPoint(e);
break;
case DrawMode.Line:
DrawLine(e);
break;
case DrawMode.Rectangle:
DrawRectangle(e);
break;
case DrawMode.RotateRect:
DrawRotateRect(e);
break;
case DrawMode.Circle:
DrawCircle(e);
break;
case DrawMode.Polygon:
DrawPolygon(e);
break;
}
mainView.Invalidate();
}
private bool IsCanSelect(PointF center, Point mouse, float relative)
{
PointF screenCenter = ImageTransScreenPointF(center);
if (Math.Abs(mouse.X - screenCenter.X) <= relative && Math.Abs(mouse.Y - screenCenter.Y) <= relative)
{
return true;
}
else
{
return false;
}
}
private void contextMenuStrip_menu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
this.contextMenuStrip_menu.Close();
string clickedItemText = e.ClickedItem.Text;
Console.WriteLine(clickedItemText);
switch (clickedItemText)
{
case "导入图像":
this.ImportImage();
break;
case "自适应":
this.Fit();
break;
case "水平翻转":
this.FlipX();
break;
case "垂直翻转":
this.FlipY();
break;
case "顺时针旋转":
this.RightRotate();
break;
case "逆时针旋转":
this.LeftRotate();
break;
case "恢复":
this.Restore();
break;
case "像素级":
viewMode = DisplayMode.Pixel;
mainView.Invalidate();
break;
case "高质量":
viewMode = DisplayMode.HighQuality;
mainView.Invalidate();
break;
case "Point":
Console.WriteLine("画一个点");
StartDrawPoint();
break;
case "Line":
Console.WriteLine("画一条线");
StartDrawLine();
break;
case "Rectangle":
Console.WriteLine("画一个矩形");
StartDrawRectangle();
break;
case "RotateRect":
Console.WriteLine("画一个旋转矩形");
StartDrawRotateRect();
break;
case "Circle":
Console.WriteLine("画一个圆形");
StartDrawCircle();
break;
case "Eclipse":
Console.WriteLine("画一个椭圆");
break;
case "Polygon":
Console.WriteLine("画多边形");
StartDrawPolygon();
break;
case "1":
Console.WriteLine("设置宽度1");
penSize = 1;
break;
case "2":
Console.WriteLine("设置宽度2");
penSize = 2;
break;
case "3":
Console.WriteLine("设置宽度3");
penSize = 3;
break;
case "4":
Console.WriteLine("设置宽度4");
penSize = 4;
break;
case "5":
Console.WriteLine("设置宽度5");
penSize = 5;
break;
case "Black":
Console.WriteLine("设置黑色");
penColor = Color.Black;
break;
case "White":
Console.WriteLine("设置白色");
penColor = Color.White;
break;
case "Red":
Console.WriteLine("设置红色");
penColor = Color.Red;
break;
case "Green":
Console.WriteLine("设置绿色");
penColor = Color.Green;
break;
case "Blue":
Console.WriteLine("设置蓝色");
penColor = Color.Blue;
break;
case "Yellow":
Console.WriteLine("设置黄色");
penColor = Color.Yellow;
break;
case "移除图像":
Console.WriteLine("移除图像");
this.RemoveImage();
break;
case "保存图像":
Console.WriteLine("保存图像");
this.SaveImage();
break;
default:
break;
}
}
private void mainView_Resize(object sender, EventArgs e)
{
if (imageBmp != null)
{
// 计算初始的缩放比例和偏移量
}
}
#region 操作封装
private void ClearDraw()
{
if (operatorMode == DrawMode.None && drawState == DrawState.Done)
{
drawPoint = null;
drawLine = null;
drawRectangle = null;
drawRotateRect = null;
drawCircle = null;
drawPolygon = null;
mainView.Invalidate();
}
}
private void StartDrawPoint()
{
if (imageBmp != null)
{
drawPoint = new DrawPoint();
drawPoint.penColor = penColor;
drawPoint.penSize = penSize;
operatorMode = DrawMode.Point;
drawState = DrawState.Start;
mainView.Cursor = Cursors.Cross;
}
}
private void DrawPoint(MouseEventArgs e)
{
switch (drawState)
{
case DrawState.Start:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawPoint.point = ScreenTransImagePointF(e.Location);
drawState = DrawState.Drawing;
}
break;
case DrawState.Drawing:
//更新点的位置
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawPoint.point = ScreenTransImagePointF(e.Location);
}
break;
}
}
private void StartDrawLine()
{
if (imageBmp != null)
{
drawLine = new DrawLine();
drawLine.penColor = penColor;
drawLine.penSize = penSize;
operatorMode = DrawMode.Line;
drawState = DrawState.Start;
mainView.Cursor = Cursors.Cross;
}
}
private void DrawLine(MouseEventArgs e)
{
switch (drawState)
{
case DrawState.Start:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawLine.startPoint = ScreenTransImagePointF(e.Location);
drawLine.endPoint = ScreenTransImagePointF(e.Location);
drawState = DrawState.Drawing;
}
break;
case DrawState.Drawing:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawLine.endPoint = ScreenTransImagePointF(e.Location);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.Finish:
if (IsMouseOnImage(e.Location) && IsCanSelect(drawLine.GetCenter(), e.Location, 5) ||
IsCanSelect(drawLine.startPoint, e.Location, 5) || IsCanSelect(drawLine.endPoint, e.Location, 5))
{
mainView.Cursor = Cursors.SizeAll;
drawLine.isSelect = true;
}
else
{
mainView.Cursor = Cursors.Cross;
drawLine.isSelect = false;
}
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawLine.GetCenter(), e.Location, 5))
{
drawState = DrawState.Moving;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawLine.startPoint, e.Location, 5))
{
drawState = DrawState.StartDraging;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawLine.endPoint, e.Location, 5))
{
drawState = DrawState.EndDraging;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && !IsCanSelect(drawLine.GetCenter(), e.Location, 5))
{
drawState = DrawState.Start;
}
break;
case DrawState.Moving:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
float relativeX = ScreenTransImagePointF(e.Location).X - drawLine.GetCenter().X;
float relativeY = ScreenTransImagePointF(e.Location).Y - drawLine.GetCenter().Y;
//更新坐标
drawLine.startPoint.X += relativeX;
drawLine.startPoint.Y += relativeY;
drawLine.endPoint.X += relativeX;
drawLine.endPoint.Y += relativeY;
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.StartDraging:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新起点坐标
drawLine.startPoint = ScreenTransImagePointF(e.Location);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.EndDraging:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新终点坐标
drawLine.endPoint = ScreenTransImagePointF(e.Location);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
}
}
private void StartDrawRectangle()
{
if (imageBmp != null)
{
drawRectangle = new DrawRectangle();
drawRectangle.penColor = penColor;
drawRectangle.penSize = penSize;
operatorMode = DrawMode.Rectangle;
drawState = DrawState.Start;
mainView.Cursor = Cursors.Cross;
}
}
private void DrawRectangle(MouseEventArgs e)
{
switch (drawState)
{
case DrawState.Start:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawRectangle.rect.Location = ScreenTransImagePointF(e.Location);
drawState = DrawState.Drawing;
}
break;
case DrawState.Drawing:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
PointF rbLoca = ScreenTransImagePointF(e.Location);
drawRectangle.rect.Width = Math.Abs(rbLoca.X - drawRectangle.rect.X);
drawRectangle.rect.Height = Math.Abs(rbLoca.Y - drawRectangle.rect.Y);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.Finish:
//显示
if (IsMouseOnImage(e.Location) && IsCanSelect(drawRectangle.GetCenter(), e.Location, 5))
{
mainView.Cursor = Cursors.SizeAll;
drawRectangle.isSelect = true;
}
else if (IsMouseOnImage(e.Location) && IsCanSelect(drawRectangle.GetBR(), e.Location, 5))
{
mainView.Cursor = Cursors.SizeNWSE;
drawRectangle.isSelect = true;
}
else
{
mainView.Cursor = Cursors.Cross;
drawRectangle.isSelect = false;
}
//操作
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawRectangle.GetCenter(), e.Location, 5))
{
drawState = DrawState.Moving;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawRectangle.GetBR(), e.Location, 5))
{
drawState = DrawState.BrDraging;
}
else if (e.Button == MouseButtons.Left && !IsCanSelect(drawRectangle.GetCenter(), e.Location, 5) && !IsCanSelect(drawRectangle.GetBR(), e.Location, 5))
{
drawState = DrawState.Start;
}
break;
case DrawState.Moving:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新坐标
drawRectangle.rect.X = ScreenTransImagePointF(e.Location).X - drawRectangle.rect.Width / 2;
drawRectangle.rect.Y = ScreenTransImagePointF(e.Location).Y - drawRectangle.rect.Height / 2;
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.BrDraging:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新宽高
PointF mouse = ScreenTransImagePointF(e.Location);
drawRectangle.rect.Width = Math.Abs(mouse.X - drawRectangle.rect.X);
drawRectangle.rect.Height = Math.Abs(mouse.Y - drawRectangle.rect.Y);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
}
}
private void StartDrawEllipse()
{
if (imageBmp != null)
{
drawEllipse = new DrawEllipse();
drawEllipse.penColor = penColor;
drawEllipse.penSize = penSize;
operatorMode = DrawMode.Ellipse;
drawState = DrawState.Start;
mainView.Cursor = Cursors.Cross;
}
}
private void DrawEllipse(MouseEventArgs e)
{
switch (drawState)
{
case DrawState.Start:
break;
case DrawState.Drawing:
break;
case DrawState.Finish:
break;
case DrawState.Moving:
break;
}
}
/// <summary>
/// 开始绘制圆
/// </summary>
private void StartDrawCircle()
{
if (imageBmp != null)
{
drawCircle = new DrawCircle();
drawCircle.penColor = penColor;
drawCircle.penSize = penSize;
operatorMode = DrawMode.Circle;
drawState = DrawState.Start;
mainView.Cursor = Cursors.Cross;
}
}
private void DrawCircle(MouseEventArgs e)
{
switch (drawState)
{
case DrawState.Start:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawCircle.center = ScreenTransImagePointF(e.Location);
drawState = DrawState.Drawing;
}
break;
case DrawState.Drawing:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
PointF movePoint = ScreenTransImagePointF(e.Location);
//计算圆半径
drawCircle.radius = (float)Math.Sqrt(Math.Pow(Math.Abs(movePoint.X - drawCircle.center.X), 2) + Math.Pow(Math.Abs(movePoint.Y - drawCircle.center.Y), 2));
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.Finish:
if (IsMouseOnImage(e.Location) && IsCanSelect(drawCircle.center, e.Location, 5))
{
mainView.Cursor = Cursors.SizeAll;
drawCircle.isSelect = true;
}
else if (IsMouseOnImage(e.Location) && IsCanSelect(drawCircle.GetScalePoint(), e.Location, 5))
{
mainView.Cursor = Cursors.SizeWE;
drawCircle.isSelect = true;
}
else
{
mainView.Cursor = Cursors.Cross;
drawCircle.isSelect = false;
}
//更新
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawCircle.center, e.Location, 5))
{
drawState = DrawState.Moving;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawCircle.GetScalePoint(), e.Location, 5))
{
drawState = DrawState.ScaleDraging;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && !IsCanSelect(drawCircle.center, e.Location, 5))
{
drawState = DrawState.Start;
}
break;
case DrawState.Moving:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新坐标
drawCircle.center = ScreenTransImagePointF(e.Location);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.ScaleDraging:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新半径
drawCircle.radius = ScreenTransImagePointF(e.Location).X - drawCircle.center.X;
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
}
}
private void StartDrawRotateRect()
{
if (imageBmp != null)
{
drawRotateRect = new DrawRotateRect();
drawRotateRect.penColor = penColor;
drawRotateRect.penSize = penSize;
operatorMode = DrawMode.RotateRect;
drawState = DrawState.Start;
mainView.Cursor = Cursors.Cross;
}
}
private void DrawRotateRect(MouseEventArgs e)
{
switch (drawState)
{
case DrawState.Start:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawRotateRect.center = ScreenTransImagePointF(e.Location);
drawState = DrawState.Drawing;
}
break;
case DrawState.Drawing:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
float w = ScreenTransImagePointF(e.Location).X - drawRotateRect.center.X;
float h = ScreenTransImagePointF(e.Location).Y - drawRotateRect.center.Y;
drawRotateRect.widthHalf = w;
drawRotateRect.heightHalf = h;
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.Finish:
//显示
if (IsMouseOnImage(e.Location) && IsCanSelect(drawRotateRect.center, e.Location, 5))
{
mainView.Cursor = Cursors.SizeAll;
drawRotateRect.isSelect = true;
}
else if (IsMouseOnImage(e.Location) && IsCanSelect(drawRotateRect.tr, e.Location, 10))
{
mainView.Cursor = rotateCursor;
drawRotateRect.isSelect = true;
}
else if (IsMouseOnImage(e.Location) && IsCanSelect(drawRotateRect.GetRightCenter(), e.Location, 5))
{
mainView.Cursor = Cursors.SizeWE;
drawRotateRect.isSelect = true;
}
else if (IsMouseOnImage(e.Location) && IsCanSelect(drawRotateRect.GetBottomCenter(), e.Location, 5))
{
mainView.Cursor = Cursors.SizeNS;
drawRotateRect.isSelect = true;
}
else
{
mainView.Cursor = Cursors.Cross;
drawRotateRect.isSelect = false;
}
//操作
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawRotateRect.center, e.Location, 5))
{
drawState = DrawState.Moving;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawRotateRect.tr, e.Location, 10))
{
drawState = DrawState.Rotate;
}
else if (e.Button == MouseButtons.Left && IsCanSelect(drawRotateRect.GetRightCenter(), e.Location, 5))
{
drawState = DrawState.RightDraging;
}
else if (e.Button == MouseButtons.Left && IsCanSelect(drawRotateRect.GetBottomCenter(), e.Location, 5))
{
drawState = DrawState.BottomDraging;
}
else if (e.Button == MouseButtons.Left && !IsCanSelect(drawRotateRect.center, e.Location, 5) && !IsCanSelect(drawRotateRect.tr, e.Location, 5))
{
drawState = DrawState.Start;
}
break;
case DrawState.Moving:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新坐标
PointF newP = ScreenTransImagePointF(e.Location);
drawRotateRect.MoveCenrer(newP);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.Rotate:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//计算角度
PointF mouse = ScreenTransImagePointF(e.Location);
//计算中心与右上角角度
double r = ShapeTools.GetRotate(drawRotateRect.center, drawRotateRect.tr);
//计算鼠标与中心的角度
double mr = ShapeTools.GetRotate(drawRotateRect.center, mouse);
//角点旋转
drawRotateRect.Rotate(mr - r);
//获取左边与右边中点 计算矩形当前角度
drawRotateRect.rotate = ShapeTools.GetRotate(drawRotateRect.GetLeftCenter(), drawRotateRect.GetRightCenter());
if (Math.Abs(drawRotateRect.rotate) > 0 && Math.Abs(drawRotateRect.rotate) < 1)
{
drawRotateRect.Rotate(0 - drawRotateRect.rotate);
drawRotateRect.rotate += 0 - drawRotateRect.rotate;
}
Console.WriteLine(drawRotateRect.rotate);
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.RightDraging:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
float w = ScreenTransImagePointF(e.Location).X - drawRotateRect.center.X;
drawRotateRect.widthHalf = w;
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
case DrawState.BottomDraging:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
float h = ScreenTransImagePointF(e.Location).Y - drawRotateRect.center.Y;
drawRotateRect.heightHalf = h;
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
}
}
/// <summary>
/// 开始绘制多边形
/// </summary>
private void StartDrawPolygon()
{
if (imageBmp != null)
{
drawPolygon = new DrawPolygon();
drawPolygon.penColor = penColor;
drawPolygon.penSize = penSize;
operatorMode = DrawMode.Polygon;
drawState = DrawState.Start;
mainView.Cursor = Cursors.Cross;
}
}
/// <summary>
/// 绘制多边形
/// </summary>
/// <param name="e"></param>
private void DrawPolygon(MouseEventArgs e)
{
switch (drawState)
{
case DrawState.Start:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
if (drawPolygon.polygonPath.Count > 1)
{
drawPolygon.polygonPath.Clear();
}
//添加起点
drawPolygon.polygonPath.Add(ScreenTransImagePointF(e.Location));
drawState = DrawState.Drawing;
}
break;
case DrawState.Drawing:
if (IsMouseOnImage(e.Location) && IsCanSelect(drawPolygon.polygonPath[0], e.Location, 5))
{
mainView.Cursor = Cursors.Hand;
}
else
{
mainView.Cursor = Cursors.Cross;
}
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && !IsCanSelect(drawPolygon.polygonPath[0], e.Location, 5))
{
//添加路径
drawPolygon.polygonPath.Add(ScreenTransImagePointF(e.Location));
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawPolygon.GetCenter(), e.Location, 5))
{
drawState = DrawState.Moving;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawPolygon.polygonPath[0], e.Location, 5))
{
PointF start = drawPolygon.polygonPath[0];
drawPolygon.polygonPath.Add(start);
drawState = DrawState.Finish;
}
break;
case DrawState.Finish:
if (IsMouseOnImage(e.Location) && IsCanSelect(drawPolygon.GetCenter(), e.Location, 5))
{
mainView.Cursor = Cursors.SizeAll;
drawPolygon.isSelect = true;
}
else
{
mainView.Cursor = Cursors.Cross;
drawPolygon.isSelect = false;
}
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && IsCanSelect(drawPolygon.GetCenter(), e.Location, 5))
{
drawState = DrawState.Moving;
}
else if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location) && !IsCanSelect(drawPolygon.polygonPath[0], e.Location, 5))
{
drawState = DrawState.Start;
}
break;
case DrawState.Moving:
if (e.Button == MouseButtons.Left && IsMouseOnImage(e.Location))
{
//更新坐标
drawPolygon.ChangeAllPath(ScreenTransImagePointF(e.Location));
}
else if (e.Button != MouseButtons.Left && IsMouseOnImage(e.Location))
{
drawState = DrawState.Finish;
}
break;
}
}
/// <summary>
/// 结束绘制
/// </summary>
private void DrawEnd()
{
operatorMode = DrawMode.None;
drawState = DrawState.Done;
mainView.Cursor = Cursors.Default;
}
private void FlipX()
{
if (imageBmp != null)
{
imageBmp.RotateFlip(RotateFlipType.RotateNoneFlipX);
this.Fit();
}
}
private void FlipY()
{
if (imageBmp != null)
{
imageBmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
this.Fit();
}
}
private void LeftRotate()
{
if (imageBmp != null)
{
imageBmp.RotateFlip(RotateFlipType.Rotate270FlipNone);
this.Fit();
}
}
private void RightRotate()
{
if (imageBmp != null)
{
imageBmp.RotateFlip(RotateFlipType.Rotate90FlipNone);
this.Fit();
}
}
private void Restore()
{
if (cloneBmp != null)
{
imageBmp = cloneBmp.Clone() as Bitmap;
this.Fit();
}
}
#endregion
private void toolStripButton_clear_Click(object sender, EventArgs e)
{
this.ClearDraw();
}
/// <summary>
/// 鼠标样式切换到箭头
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolStripButton_arrow_Click(object sender, EventArgs e)
{
if (operatorMode == DrawMode.None)
{
mainView.Cursor = Cursors.Arrow;
}
}
/// <summary>
/// 鼠标样式切换到抓手
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolStripButton_hand_Click(object sender, EventArgs e)
{
if (operatorMode == DrawMode.None)
{
mainView.Cursor = Cursors.Hand;
}
}
/// <summary>
/// 自适应显示
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolStripButton_fit_Click(object sender, EventArgs e)
{
this.Fit();
}
/// <summary>
/// 缩放选项点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolStripSplitButton_scale_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
if (imageBmp == null) { return; }
float oldScale = scaleF;
switch (e.ClickedItem.Text)
{
case "50%":
scaleF = 0.5f;
break;
case "100%":
scaleF = 1f;
break;
case "150%":
scaleF = 1.5f;
break;
case "200%":
scaleF = 2f;
break;
}
float dx = mainView.Width / 2 - offset.X;
float dy = mainView.Height / 2 - offset.Y;
offset.X -= dx * (scaleF / oldScale - 1);
offset.Y -= dy * (scaleF / oldScale - 1);
mainView.Invalidate();
}
private void toolStripButton_leftRotate_Click(object sender, EventArgs e)
{
LeftRotate();
}
private void toolStripButton_rightRotate_Click(object sender, EventArgs e)
{
RightRotate();
}
private void toolStripMenuItem_point_Click(object sender, EventArgs e)
{
StartDrawPoint();
}
private void toolStripMenuItem_line_Click(object sender, EventArgs e)
{
StartDrawLine();
}
private void toolStripMenuItem_rectangle_Click(object sender, EventArgs e)
{
StartDrawRectangle();
}
private void toolStripMenuItem_circle_Click(object sender, EventArgs e)
{
StartDrawCircle();
}
private void mainView_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && drawState != DrawState.Done)
{
switch (operatorMode)
{
case DrawMode.Point:
drawPoint.isSelect = false;
Console.WriteLine($"Point X:{(int)drawPoint.point.X} Y:{(int)drawPoint.point.Y}");
break;
case DrawMode.Line:
drawLine.isSelect = false;
Console.WriteLine($"Line sX:{drawLine.startPoint.X} sY:{drawLine.startPoint.Y} --- eX:{drawLine.endPoint.X} eY:{drawLine.endPoint.Y}");
break;
case DrawMode.Circle:
drawCircle.isSelect = false;
// 计算在图片上的位置
Console.WriteLine($"Circle X:{drawCircle.center.X} Y:{drawCircle.center.Y} --- R:{drawCircle.radius}");
break;
case DrawMode.Rectangle:
drawRectangle.isSelect = false;
Console.WriteLine($"Rectangle X:{drawRectangle.rect.X} Y:{drawRectangle.rect.Y} --- width:{drawRectangle.GetSize().Width} height:{drawRectangle.GetSize().Height}");
break;
case DrawMode.RotateRect:
drawRotateRect.isSelect = false;
Console.WriteLine($"RotateRect cX:{drawRotateRect.center.X} cY:{drawRotateRect.center.Y} --- width:{drawRotateRect.widthHalf} height:{drawRotateRect.heightHalf} rotate:{drawRotateRect.rotate}");
break;
case DrawMode.Polygon:
drawPolygon.isSelect = false;
break;
}
this.DrawEnd();
}
}
private void toolStripMenuItem_polygon_Click(object sender, EventArgs e)
{
StartDrawPolygon();
}
private void toolStripMenuItem_rotateRect_Click(object sender, EventArgs e)
{
StartDrawRotateRect();
}
public DrawPoint GetDrawPoint()
{
return drawPoint;
}
public DrawLine GetDrawLine()
{
return drawLine;
}
public DrawCircle GetDrawCircle()
{
return drawCircle;
}
public DrawRectangle GetDrawRectangle()
{
return drawRectangle;
}
public DrawRotateRect GetRotateRect()
{
return drawRotateRect;
}
public DrawPolygon GetDrawPolygon()
{
return drawPolygon;
}
private void mainView_SizeChanged(object sender, EventArgs e)
{
this.Fit();
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/haumingl/opti-kinetiq-platform.git
git@gitee.com:haumingl/opti-kinetiq-platform.git
haumingl
opti-kinetiq-platform
OptiKinetiq-Platform
master

搜索帮助