zoukankan      html  css  js  c++  java
  • C# 图片盖章功能实现,支持拖拽-旋转-放缩-保存

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

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

    实现代码如下:

    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
        }

    效果图:

  • 相关阅读:
    时尚生活小秘方[转载]
    武侠片上的99个公式镜头
    SQL语句优化技术分析
    LoadRunner监视的性能计数器
    圣诞收到最搞笑的短信两则
    loadrunner 运行状态描述
    ORACLE 常用脚本[转载]
    关于内存泄漏检测问题,和大家一起分享
    小笑话
    [转贴] ++ 一个北大女孩给男友的道歉信(爆笑!!!)相当经典
  • 原文地址:https://www.cnblogs.com/shanranlei/p/3635412.html
Copyright © 2011-2022 走看看