欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# 实现的图片盖章功能,支持拖拽、旋转、放缩、保存

程序员文章站 2024-02-23 12:42:10
实现图片盖章功能,在图片上点击,增加“图章”小图片,可以拖拽“图章”到任意位置,也可以点击图章右下角园框,令图片跟着鼠标旋转和放缩。 操作方法:1.点击增加“图章”2.选...

实现图片盖章功能,在图片上点击,增加“图章”小图片,可以拖拽“图章”到任意位置,也可以点击图章右下角园框,令图片跟着鼠标旋转和放缩。

操作方法:1.点击增加“图章”2.选中移动图标3.点中右下角放缩旋转图章。

效果图:

C# 实现的图片盖章功能,支持拖拽、旋转、放缩、保存

实现代码如下:

1.  窗口xaml代码

复制代码 代码如下:
<window x:class="lenovo.yogapaster.imageeditwindow"
    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;
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;
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
  }