C# 实现的图片盖章功能,支持拖拽、旋转、放缩、保存
实现图片盖章功能,在图片上点击,增加“图章”小图片,可以拖拽“图章”到任意位置,也可以点击图章右下角园框,令图片跟着鼠标旋转和放缩。
操作方法:1.点击增加“图章”2.选中移动图标3.点中右下角放缩旋转图章。
效果图:
实现代码如下:
1. 窗口xaml代码
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
title="imageeditwindow" height="300" width="300">
<grid>
<grid.rowdefinitions>
<rowdefinition height="20*"/>
<rowdefinition height="*"/>
</grid.rowdefinitions>
<canvas x:name="canvas"
background="yellow" />
<button content="保存成图片" click="button_click_1" grid.row="1" horizontalalignment="center" verticalalignment="center"/>
</grid>
</window>
2. 窗口后台代码:
using system.collections.generic;
using system.drawing;
using system.drawing.imaging;
using system.io;
using system.linq;
using system.text;
using system.threading.tasks;
using system.windows;
using system.windows.controls;
using system.windows.data;
using system.windows.documents;
using system.windows.input;
using system.windows.media;
using system.windows.media.imaging;
using system.windows.shapes;
using lenovo.yp.utils;
using microsoft.win32;
using point = system.windows.point;
namespace lenovo.yogapaster
{
/// <summary>
/// imageeditwindow.xaml 的交互逻辑
/// </summary>
public partial class imageeditwindow : window
{
public imageeditwindow()
{
initializecomponent();
this.loaded += (sender, e) =>
{
canvas.mouseleftbuttondown += canvas_mouseleftbuttondown;
};
}
private void canvas_mouseleftbuttondown(object sender, mousebuttoneventargs e)
{
photoedithelper.commommaxzindex++;
var image = new moveimage { containercanvas = canvas };
point point = e.getposition(canvas);
image.createimage(point);
}
/// <summary>
/// 保存方法
/// </summary>
public void savepicture()
{
//todo: openfile对话框
savefiledialog savefiledialog = new savefiledialog();
savefiledialog.filename = "图片"; // default file name
savefiledialog.defaultext = ".bmp"; // default file extension
savefiledialog.filter = "图片文件 (.bmp)|*.bmp"; // filter files by extension
// show save file dialog box
nullable<bool> result = savefiledialog.showdialog();
// process save file dialog box results
if (result == true)
{
// save document
string filename = savefiledialog.filename;
if (file.exists(filename))
{
file.delete(filename);
}
bitmapsource bitmapsource = picturemergehelper.createnotranderelementscreenshot(canvas, 1800, 1080);
bitmapencoder bitmapencoder = new bmpbitmapencoder();
bitmapencoder.frames.add(bitmapframe.create(bitmapsource));
filestream filestream = new filestream(filename, filemode.create);
bitmapencoder.save(filestream);
filestream.dispose();
}
}
private void button_click_1(object sender, routedeventargs e)
{
savepicture();
}
}
}
3. moveimage 类文件如下:
using system.collections.generic;
using system.linq;
using system.text;
using system.windows;
using system.windows.controls;
using system.windows.input;
using system.windows.media;
using system.windows.media.imaging;
namespace lenovo.yp.utils
{
/// <summary>
/// 添加一个image控件,并实现拖动效果
/// </summary>
public class moveimage
{
#region 字段
private int m_zindex;
/// <summary>
/// 当前图章的位置
/// </summary>
///
/// <summary>
/// 旋转图标的起始位置
/// </summary>
private point m_imageroundstartoffset;
/// <summary>
/// 旋转图标的当前位置
/// </summary>
private point m_imageroundoffset;
/// <summary>
/// 标识图章是否被拖拽
/// </summary>
private bool m_isdragging;
/// <summary>
/// 标识旋转图标是否被是否被拖拽
/// </summary>
private bool m_isimagerounddragging;
/// <summary>
/// 图章的父容器
/// </summary>
public canvas containercanvas { get; set; }
/// <summary>
/// 图章图片
/// </summary>
private image m_flogimage;
/// <summary>
/// 旋转按钮图片
/// </summary>
private image m_rotateimage;
/// <summary>
/// 图章和旋转图片的容器
/// </summary>
private grid m_moveimagegrid;
/// <summary>
/// 选转
/// </summary>
private rotatetransform m_imagerotate;
/// <summary>
/// 缩放
/// </summary>
private scaletransform m_imagescale;
/// <summary>
/// 上次位置
/// </summary>
private point m_oldpos;
#endregion
public moveimage()
{ }
/// <summary>
/// 创建一个图标
/// </summary>
/// <param name="position">图标的位置</param>
public void createimage(point position)
{
#region 设置布局
m_flogimage = new image
{
//width = 100,
//height = 100,
source = new bitmapimage(new uri("/images/shuzi.jpg", urikind.relativeorabsolute))
};
m_rotateimage = new image
{
width = 20,
height = 20,
source = new bitmapimage(new uri("/images/round.jpg", urikind.relativeorabsolute))
};
m_rotateimage.horizontalalignment = horizontalalignment.right;
m_rotateimage.verticalalignment = verticalalignment.bottom;
m_rotateimage.visibility = visibility.hidden;
m_moveimagegrid = new grid();
m_moveimagegrid.width = 110;
m_moveimagegrid.height = 110;
m_moveimagegrid.children.add(m_flogimage);
m_moveimagegrid.children.add(m_rotateimage);
m_moveimagegrid.mouseenter += rootgridmouseenter;
m_moveimagegrid.mouseleave += rootgridmouseleave;
m_rotateimage.mouseleftbuttondown += imageround_mouseleftbuttondown;
m_rotateimage.mousemove += imageround_mousemove;
m_rotateimage.mouseleftbuttonup += imageround_mouseleftbuttonup;
// image in den vordergrund bringen
canvas.setzindex(m_moveimagegrid, m_zindex++);
#endregion
// event handler für das image installieren
m_moveimagegrid.mouseleftbuttondown += rootgridmouseleftbuttondown;
m_moveimagegrid.mouseleftbuttonup += rootgridmouseleftbuttonup;
m_moveimagegrid.mousemove += rootgridmousemove;
// image leicht transparent machen
m_moveimagegrid.opacity = 0.8;
m_imagerotate = new rotatetransform(0, 0, 0);
m_imagescale = new scaletransform();
//m_imagescale.scalex = 1;
//m_imagescale.scaley = 1;
transformgroup transformgroup = new transformgroup();
transformgroup.children.add(m_imagerotate);
transformgroup.children.add(m_imagescale);
m_moveimagegrid.rendertransform = transformgroup;
//m_imagescale111 = new scaletransform();
//m_imagescale111.scalex = 0.5;
//m_imagescale111.scaley = 0.5;
//imageround.rendertransform = m_imagescale111;
m_moveimagegrid.rendertransformorigin = new point(0.5, 0.5);
// image positionieren
var pos = position;
canvas.setleft(m_moveimagegrid, pos.x - (m_moveimagegrid.width / 2));
canvas.settop(m_moveimagegrid, pos.y - (m_moveimagegrid.height / 2));
// image zum canvas hinzufügen
containercanvas.children.add(m_moveimagegrid);
}
/// <summary>
/// 控制旋转图标隐藏
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rootgridmouseleave(object sender, mouseeventargs e)
{
m_rotateimage.visibility = visibility.hidden;
}
/// <summary>
/// 控制选择图标显示
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rootgridmouseenter(object sender, mouseeventargs e)
{
m_rotateimage.visibility = visibility.visible;
}
#region 控制盖章的移动
private void rootgridmousemove(object sender, mouseeventargs e)
{
if (m_isdragging)
{
var pos = e.getposition(containercanvas);
canvas.setleft(m_moveimagegrid, canvas.getleft(m_moveimagegrid) + pos.x - m_oldpos.x);
canvas.settop(m_moveimagegrid, canvas.gettop(m_moveimagegrid) + pos.y - m_oldpos.y);
m_oldpos = pos;
}
}
private void rootgridmouseleftbuttonup(object sender, mousebuttoneventargs e)
{
var grid = sender as grid;
// canvas.setzindex(image, m_zindex++);
// bild wieder leicht transparent machen
grid.opacity = 0.8;
grid.releasemousecapture();
m_isdragging = false;
}
private void rootgridmouseleftbuttondown(object sender, mousebuttoneventargs e)
{
var grid = sender as grid;
// auf "nicht"-transparent setzen
grid.opacity = 1;
// position des pointers relativ zum bild speichern
m_oldpos = e.getposition(containercanvas);
// isdragging auf true setzen für mousemove
m_isdragging = true;
// image in den vordergrund bringen
canvas.setzindex(grid, photoedithelper.commommaxzindex++);
// den pointer einfangen. bei schnellen bewegungen kann der
// pointer aus dem image bewegt werden. damit die pointer-
// events weiterhin stattfinden, wird der pointer eingefangen.
grid.capturemouse();
// als behandelt markieren, damit nicht noch der
// pointerpressed-event handler des canvas aufgerufen wird.
e.handled = true;
}
#endregion
#region 控制图章的旋转
private void imageround_mouseleftbuttonup(object sender, mousebuttoneventargs e)
{
var image = sender as image;
m_moveimagegrid.opacity = 1;
image.releasemousecapture();
m_isimagerounddragging = false;
}
private void imageround_mousemove(object sender, mouseeventargs e)
{
if (m_isimagerounddragging)
{
//鼠标当前点的坐标
m_imageroundoffset = e.getposition(containercanvas);
m_imagescale.scalex =
m_imagescale.scaley = getlength(currcenter, m_imageroundstartoffset, m_imageroundoffset);
m_imagerotate.angle = getangle(currcenter, m_imageroundstartoffset, m_imageroundoffset) - 45;
}
}
private point currcenter;
private void imageround_mouseleftbuttondown(object sender, mousebuttoneventargs e)
{
var image = sender as image;
m_moveimagegrid.opacity = 1;
//中心点坐标
currcenter = new point(canvas.getleft(m_moveimagegrid) + m_moveimagegrid.width / 2, canvas.gettop(m_moveimagegrid) + m_moveimagegrid.height / 2);
m_imageroundstartoffset = new point(currcenter.x + m_moveimagegrid.width / 2, currcenter.y);
m_isimagerounddragging = true;
canvas.setzindex(m_moveimagegrid, photoedithelper.commommaxzindex++);
image.capturemouse();
e.handled = true;
}
/// 根据余弦定理求两个线段夹角
/// </summary>
/// <param name="origin">原点</param>
/// <param name="start">start点</param>
/// <param name="end">end点</param>
/// <returns></returns>
private double getangle(point origin, point start, point end)
{
double cosfi = 0, fi = 0, norm = 0;
double dsx = start.x - origin.x;
double dsy = start.y - origin.y;
double dex = end.x - origin.x;
double dey = end.y - origin.y;
cosfi = dsx * dex + dsy * dey;
norm = (dsx * dsx + dsy * dsy) * (dex * dex + dey * dey);
if (norm == 0) return 0; // origin和end坐标一样
cosfi /= math.sqrt(norm);
if (cosfi >= 1.0) return 0;
if (cosfi <= -1.0) return 180;
fi = math.acos(cosfi);
double angle = 180 * fi / math.pi;
if (dey > 0)
{
return angle;
}
return -angle;
}
private double getlength(point origin, point start, point end)
{
double dex = end.x - origin.x;
double dey = end.y - origin.y;
double dsx = start.x - origin.x;
double dsy = start.y - origin.y;
double startlength = math.sqrt(math.pow(dsx, 2) + math.pow(dsy, 2));
double endlength = math.sqrt(math.pow(dex, 2) + math.pow(dey, 2));
return endlength / startlength;
}
#endregion
}