- 项目类型:WPF
- 项目语言:c#
- 项目框架:.Net5
1.主界面Xaml
<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel LastChildFill="True">
<Grid DockPanel.Dock="Left" Width="200">
<StackPanel>
<Button Content="选择图片" Click="Button_Click_1" Height="30" Margin="5" />
<Button Content="绘制路径" Height="30" Margin="5" Click="Button_Click_2" />
<Button Content="清空路径" Height="30" Margin="5" Click="Button_Click_5" />
<Button Content="保存路径" Height="30" Margin="5" Click="Button_Click_3" />
<Button Content="加载路径" Height="30" Margin="5" Click="Button_Click_4" />
<!--<Button Content="确定范围" Height="30" Margin="5" Click="Button_Click_6" />-->
<Button Content="栽剪" Click="Button_Click" Height="30" Margin="5"/>
</StackPanel>
</Grid>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="文件路径"/>
<TextBox Grid.Column="1" x:Name="ui_filepath" IsReadOnly="True"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="保存路径"/>
<TextBox Grid.Column="1" x:Name="ui_savepath" IsReadOnly="True"/>
</Grid>
</StackPanel>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" >
<Grid>
<Image Grid.Column="0" x:Name="ui_image_01"/>
<InkCanvas Grid.Column="0" x:Name="inkCanvas1" HorizontalAlignment="Stretch"
MinWidth="100" MinHeight="100"
Width="{Binding ElementName=ui_image_01,Path=ActualWidth}"
Height="{Binding ElementName=ui_image_01,Path=ActualHeight}"
Background="Transparent">
</InkCanvas>
</Grid>
</Border>
<Image Grid.Column="1" x:Name="ui_image_02"/>
</Grid>
</Grid>
</DockPanel>
</Window>
2.主界面代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Reflection;
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.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using Point = System.Drawing.Point;
namespace WpfApp4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
//声明一个 DrawingAttributes 类型的变量
DrawingAttributes drawingAttributes;
public MainWindow()
{
InitializeComponent();
inkCanvas1.EditingMode = InkCanvasEditingMode.None;
drawingAttributes = new DrawingAttributes();
inkCanvas1.DefaultDrawingAttributes = drawingAttributes;
//设置 DrawingAttributes 的 Color 属性设置颜色
drawingAttributes.Color = Colors.Red;
var _dir = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
this.ui_filepath.Text = _dir;
this.ui_savepath.Text = _dir;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
GraphicsPath path = new GraphicsPath();
if (this.inkCanvas1.Strokes.Count != 0)
{
var _xRate = (this.ui_image_01.Source as BitmapImage).PixelWidth / this.inkCanvas1.Width;
var _yRate = (this.ui_image_01.Source as BitmapImage).PixelHeight / this.inkCanvas1.Height;
var _list = new List<Point>();
var _lastpoint = new Point(0, 0);
foreach (var _stroke in this.inkCanvas1.Strokes)
{
foreach (var _point in _stroke.StylusPoints)
{
var _newpoint = new Point((int)(_point.X * _xRate), (int)(_point.Y * _yRate));
if (Math.Abs(_newpoint.X - _lastpoint.X) < 5 && Math.Abs(_newpoint.Y - _lastpoint.Y) < 5) { continue; }
_lastpoint = _newpoint;
_list.Add(_newpoint);
}
}
path.AddLines(_list.ToArray());
}
if (path.PointCount < 1) { return; }
if (string.IsNullOrWhiteSpace(this.ui_filepath.Text)) { return; }
Bitmap bit = (Bitmap)Bitmap.FromFile(this.ui_filepath.Text, false);
BitmapCrop2(bit, path, out Bitmap newBit);
newBit.Save(this.ui_savepath.Text);
this.ui_image_02.Source = ByteArrayToBitmapImage(File.ReadAllBytes(this.ui_savepath.Text));
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
InitialDirectory = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
Filter = @"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|所有合适文件(*.bmp,*.jpg)|*.bmp;*.jpg",
FilterIndex = 3,
RestoreDirectory = true
};
var _result = openFileDialog.ShowDialog();
if (!_result.HasValue) { return; }
if (_result == true)
{
var _filename = openFileDialog.FileName;
this.ui_filepath.Text = _filename;
var _name = System.IO.Path.GetFileNameWithoutExtension(_filename);
var _dir = System.IO.Path.GetDirectoryName(_filename);
this.ui_savepath.Text = System.IO.Path.Combine(_dir, $"{_name}({DateTime.Now.ToString("yyyyMMddHHmmss")}).jpg");
this.ui_image_01.Source = ByteArrayToBitmapImage(File.ReadAllBytes(this.ui_filepath.Text));
this.ui_image_02.Source = null;
}
else
{
this.ui_filepath.Text = "";
this.ui_savepath.Text = "";
this.ui_image_01.Source = null;
this.ui_image_02.Source = null;
}
}
/// <summary>
/// 图片截图
/// </summary>
/// <param name="bitmap">原图</param>
/// <param name="path">裁剪路径</param>
/// <param name="outputBitmap">输出图</param>
/// <returns></returns>
public static Bitmap BitmapCrop2(Bitmap bitmap, GraphicsPath path, out Bitmap outputBitmap)
{
RectangleF rect = path.GetBounds();
int left = (int)rect.Left;
int top = (int)rect.Top;
int width = (int)rect.Width;
int height = (int)rect.Height;
Bitmap image = (Bitmap)bitmap.Clone();
outputBitmap = new Bitmap(width, height);
for (int i = left; i < left + width; i++)
{
for (int j = top; j < top + height; j++)
{
//判断坐标是否在路径中
if (path.IsVisible(i, j))
{
//复制原图区域的像素到输出图片
outputBitmap.SetPixel(i - left, j - top, image.GetPixel(i, j));
}
}
}
bitmap.Dispose();
return image;
}
public static BitmapImage ByteArrayToBitmapImage(byte[] byteArray)
{
BitmapImage bmp = null;
try
{
bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = new MemoryStream(byteArray);
bmp.EndInit();
}
catch
{
bmp = null;
}
return bmp;
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
//绘制墨迹
inkCanvas1.EditingMode = InkCanvasEditingMode.Ink;
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
if (this.inkCanvas1.Strokes.Count != 0)
{
SaveFileDialog save = new SaveFileDialog
{
InitialDirectory = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
FileName = $"路径{DateTime.Now.ToString("yyyyMMddHHmmss")}.isf",
Filter = "文件|*.isf"
};
if (save.ShowDialog() == true)
{
FileStream f = File.Open(save.FileName, FileMode.Create, FileAccess.Write);
this.inkCanvas1.Strokes.Save(f);
f.Close();
}
}
this.inkCanvas1.Strokes = new System.Windows.Ink.StrokeCollection();
}
private void Button_Click_4(object sender, RoutedEventArgs e)
{
if (this.inkCanvas1.Strokes.Count != 0)
{
MessageBoxResult Message = MessageBox.Show("已修改是否保存?", "是否保存", MessageBoxButton.YesNo);
//保存,新建
if (Message == MessageBoxResult.Yes)
{
this.Button_Click_3(sender, e);
return;
}
}
OpenFileDialog open = new OpenFileDialog
{
InitialDirectory = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
Title = "选择文件",
Filter = "文件|*.isf"
};
if (open.ShowDialog() == true)
{
FileStream f = File.Open(open.FileName, FileMode.Open, FileAccess.Read);
this.inkCanvas1.Strokes = new System.Windows.Ink.StrokeCollection(f);
f.Close();
}
}
private void Button_Click_5(object sender, RoutedEventArgs e)
{
this.inkCanvas1.Strokes.Clear();
this.inkCanvas1.Strokes = new System.Windows.Ink.StrokeCollection();
}
}
}
3.效果图
3.1.启动
3.2.选择图片
3.3.绘制路径
3.4.剪切图片