c# WinForm制作图片编辑工具(图像拖动、缩放、旋转、抠图)
闲暇之余,开发一个图片编辑小程序。程序主要特点就是可方便的对多个图像编辑,实现了一些基本的操作。本文主要介绍一下程序的功能、设计思路。
执行程序下载地址:
https://pan.baidu.com/s/1cszsgjKN9ecWZ9sm1hDAdQ
1功能介绍
程序主界面
点击打开图片,可选择多个图片文件。图片缩略图左侧显示,双击左侧图片,添加到编辑区。
图片编辑区分为:纸张区域和打印区域。图片只能在打印区编辑。当选中这两个区,可调整各个区的大小。
主要功能点:
1拖动:选中图片后,可以任意拖动图片。
2缩放:可对图片左右上下实现缩放。可以锁定显示比例缩放。
3旋转,可以选择旋转基点再旋转。如果不选择旋转基点,以对角为基点旋转。
4抠图
5其他一些操作
当有多个图片相互覆盖时,可以调整图层。
选中一个图片后,可以对图片的位置、大小、旋转角度调整。
选择保存,会将编辑的图片保存为文件。
2处理思路
图片编辑信息每个图像都有对应的变量记录该图像的详细,比如位置、尺寸、旋转角度、剪切区域。见下面代码:
publicclassImageProperty
{
publicstringName{get;set;}
publicImageEditImage{get;set;}//原始图片
publicintActualWidth=>EditImage.Width;//实际尺寸
publicintActualHeight=>EditImage.Height;
publicboolShowImageTip{get;set;}=true;
publicboolLockSizeRate{get;set;}//比例是否锁定
publicSizeDrawSize{get;set;}//显示尺寸
publicobjectTag{get;set;}
}
publicclassImageEditInfo
{
publicImagePropertyImageProperty{get;set;}
publicPointLocation{get;set;}=newPoint(0,0);//相对于打印区的位置
publicPointLocationTopRight=>newPoint(Location.X+Width,Location.Y);
publicPointLocationBottomRight=>newPoint(Location.X+Width,Location.Y+Height);
publicPointLocationBottomLeft=>newPoint(Location.X,Location.Y+Height);
publicintRightX=>Location.X+Width;
publicintButtomY=>Location.Y+Height;
publicSizeDrawSize
{
get{returnImageProperty.DrawSize;}
set{ImageProperty.DrawSize=value;}
}
publicImageImage=>ImageProperty.EditImage;
publicfloatRotateAngle{get;set;}=0;//旋转角度
publicboolIsSelect{get;set;}
publicboolLockSizeRate//显示比例是否锁定
{
get
{
returnImageProperty.LockSizeRate;
}
set
{
ImageProperty.LockSizeRate=value;
}
}
publicintWidth
{
get
{
returnDrawSize.Width;
}
set
{
ImageProperty.DrawSize=newSize(value,DrawSize.Height);
}
}
publicintHeight
{
get
{
returnDrawSize.Height;
}
set
{
ImageProperty.DrawSize=newSize(DrawSize.Width,value);
}
}
publicboolShowImageTip
{
get{returnImageProperty.ShowImageTip;}
set{ImageProperty.ShowImageTip=value;}
}
publicPoint?RotatioBasePoint{get;set;}//旋转基点
publicPointRotatioBasePointValue=>RotatioBasePoint.Value;
publicboolHasRotatioBasePoint=>(RotatioBasePoint!=null&&RotatioBasePoint.HasValue);
}
图片旋转
对正常的图片移动、缩放并不难。只要调整图像的长宽、位置就行,基本就是加法减法计算。如果图片有旋转,计算起来就麻烦。比如判断鼠标是否点击了图片、鼠标缩放等,实现这些操作都麻烦。
比如判断鼠标是否点击了图片,如果一个图片是斜的(旋转后的),如何处理?我的思路是旋转:将图片和鼠标所在的点都反向旋转;此后,判断逻辑就和常规方法一样了。旋转函数如下:
//////pointMove相对于removeAt,以一定角度旋转 /// ////// /// /// /// publicstaticPointRotationAt(PointpointMove,PointremoveAt,doublerotateAngle,boolclockwise) { if(rotateAngle==0) returnpointMove; lock(matrix) { matrix.Reset(); matrix.Rotate((float)(clockwise?rotateAngle:-rotateAngle)); Pointpt2=newPoint(pointMove.X-removeAt.X,pointMove.Y-removeAt.Y); Point[]pts=newPoint[]{newPoint(pt2.X,pt2.Y)}; matrix.TransformPoints(pts); Pointresult=newPoint(pts[0].X+removeAt.X,pts[0].Y+removeAt.Y); returnresult; } } internalEN_LinePartMouseMove_HitTest(Pointpt) { //鼠标位置反向旋转, pt=DrawHelper.RotationAt(pt,Location,RotateAngle,false); //下面就是和正常判断逻辑一样 EN_LinePartresult=MouseMove_HitTest_Corner(pt); if(result!=EN_LinePart.无) returnresult; }
画图:
对图片相关参数修改后,需要调用refresh,强制重画。调用GDI+。根据图片在列表的顺序调用(也就是根据图层)。调用时,根据设定显示区域,旋转角度等,做变换后再画。
voidDrawWithRotation(Graphicsg,boolsaveToFile)
{
//设置质量
ImageHelper.SetHighQuality(g);
//置背景色
if(!saveToFile)
g.Clear(BackgroundColor);
ImageEditInfoselectImage=null;
foreach(ImageEditInfoimageInfoinImageGroup.ListImageToDraw)
{
//画图片
if(imageInfo.IsSelect)
{
Debug.Assert(selectImage==null);
selectImage=imageInfo;
}
g.TranslateTransform(imageInfo.Location.X,imageInfo.Location.Y);
g.RotateTransform(imageInfo.RotateAngle);
//是否需要画抠图
ImageimageToDraw=imageInfo.Image;
if(imageInfo.CutStat==ImageCutStat.have_cut
&&imageInfo.CutPoints.Count>2)
{
Bitmapbitmap=imageToDrawasBitmap;
System.Windows.Point[]points=imageInfo.CutPoints.Select(o=>newSystem.Windows.Point(o.X,o.Y)).ToArray();
BitmapcutBitmap=ImageCutout.GetImage(bitmap,points);
imageToDraw=cutBitmap;
}
g.DrawImage(imageToDraw,
newRectangle(0,0,imageInfo.DrawSize.Width,imageInfo.DrawSize.Height),
newRectangle(0,0,imageInfo.Image.Width,imageInfo.Image.Height),
GraphicsUnit.Pixel);
//画旋转基点
if(!saveToFile&&imageInfo.HasRotatioBasePoint)
{
Pointpt=imageInfo.RotatioBasePointValue;
g.FillEllipse(RotatioBaseBrush,pt.X-RotatioBaseRadius,pt.Y-RotatioBaseRadius,RotatioBaseRadius*2,RotatioBaseRadius*2);
}
//显示信息
if(!saveToFile&&imageInfo.ShowImageTip)
{
ImagePropertyImageProperty=imageInfo.ImageProperty;
stringinfo=string.Format($"({imageInfo.Location.X},{imageInfo.Location.Y})({ImageProperty.ActualWidth}X{ImageProperty.ActualHeight}--{imageInfo.DrawSize.Width}X{imageInfo.DrawSize.Height})(∠{imageInfo.RotateAngle.ToString("0.00")})");
SizeFsizeF=g.MeasureString(info,_drawProperty.TxtFont);
g.FillRectangle(_drawProperty.TxtBackgroundBrush,
newRectangleF(newPoint(),sizeF));
g.DrawString(info,_drawProperty.TxtFont,_drawProperty.TxtBrush,newPoint());
}
//画抠图线
if(!saveToFile
&&imageInfo.CutStat==ImageCutStat.in_cuting
&&imageInfo.CutPoints.Count>1)
{
for(inti=1;i2)
{
g.DrawLine(SelectBorderPen,imageInfo.ToDestImage(imageInfo.CutPoints.First()),
imageInfo.ToDestImage(imageInfo.CutPoints.Last()));
}
}
g.ResetTransform();
}
//画选中状态
if(!saveToFile&&selectImage!=null)
{
DrawSelectImageWithRotation(g,selectImage);
}
}
后记:
一般来讲,图像的处理属于比较难的操作。需要有空间想象能力,相应的几何数学基础。不过,如果掌握好了图像操作,对了解控件原理很有帮助。当遇到难以实现的界面,gdi+就是最后的手段;winform也是微软过时的技术了,使用winform作图效率很难提高;为了响应的事件,不停重画,效率很低。WPF对图像的操作又进了一步,wpf属于“保持模型”,就是你告诉操作系统你要画什么就行了,只需要告诉一次。而对于winform,操作系统不停的告诉你,你需要重画了。这就导致winform画图效率比较低,但是省了内存。
以上就是c#WinForm制作图片编辑工具(图像拖动、缩放、旋转、抠图)的详细内容,更多关于c#WinForm图片编辑的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。