wpf 裁剪图片并保存

xaml :

<Window.Resources>
<Style x:Key="DragHandleThumbStyle" TargetType="Thumb">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid>
<Ellipse x:Name="InnerCircle" Fill="#FFFFFFFF" Stroke="#FF6A6A6A" StrokeThickness="0.5" Width="6" Height="6"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!-- 工具栏 -->
<ToolBar Grid.Row="0">
<Button x:Name="btnLoad" Content="加载图片" Click="BtnLoad_Click"/>
<Separator/>
<Button x:Name="btnZoomIn" Content="放大" Click="BtnZoomIn_Click"/>
<Button x:Name="btnZoomOut" Content="缩小" Click="BtnZoomOut_Click"/>
<Separator/>
<Button x:Name="btnRotateLeft" Content="左旋转" Click="BtnRotateLeft_Click"/>
<Button x:Name="btnRotateRight" Content="右旋转" Click="BtnRotateRight_Click"/>
<Separator/>
<Button x:Name="btnCrop" Content="裁剪" Click="BtnCrop_Click"/>
<Button x:Name="btnSave" Content="保存" Click="BtnSave_Click"/>
</ToolBar>

<!-- 图片显示区域 -->
<Grid Grid.Row="1">

<Viewbox x:Name="viewbox">
<Grid x:Name="imageContainer" MouseWheel="imageContainer_MouseWheel" MouseLeftButtonDown="imageContainer_MouseLeftButtonDown"
MouseLeftButtonUp="imageContainer_MouseLeftButtonUp" MouseMove="imageContainer_MouseMove" ClipToBounds="True" Background="LightGray">
<Border BorderBrush="Black" BorderThickness="1">
<Image x:Name="displayImage" Stretch="Uniform" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="scaleTransform"/>
<TranslateTransform x:Name="xyTransform"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
<Canvas x:Name="cropCanvas" Background="Transparent" Visibility="Collapsed">
<Thumb x:Name="cropThumb" Width="100" Height="100" Canvas.Left="20" Canvas.Top="20" DragDelta="CropThumb_DragDelta" Cursor="SizeAll">
<Thumb.Template>
<ControlTemplate>
<Border BorderBrush="Red" BorderThickness="0.3" Background="#4008F411">
<Canvas>
<Thumb x:Name="topLeft" DragDelta="topLeft_DragDelta" Style="{StaticResource DragHandleThumbStyle}" Cursor="SizeNWSE" Canvas.Left="-3" Canvas.Top="-3"/>
<Thumb x:Name="topRight" DragDelta="topRight_DragDelta" Style="{StaticResource DragHandleThumbStyle}" Cursor="SizeNESW" Canvas.Right="-3" Canvas.Top="-3"/>
<Thumb x:Name="bottomLeft" DragDelta="bottomLeft_DragDelta" Style="{StaticResource DragHandleThumbStyle}" Cursor="SizeNESW" Canvas.Left="-3" Canvas.Bottom="-3"/>
<Thumb x:Name="bottomRight" DragDelta="bottomRight_DragDelta" Style="{StaticResource DragHandleThumbStyle}" Cursor="SizeNWSE" Canvas.Right="-3" Canvas.Bottom="-3"/>
</Canvas>
</Border>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Canvas>
</Grid>
</Viewbox>
</Grid>
</Grid>

back code:

public partial class MainWindow : Window
{
private BitmapImage originalImage;
private double currentScale = 1.0;
public MainWindow()
{
InitializeComponent();
}

private void topLeft_DragDelta(object sender, DragDeltaEventArgs e)
{
ResizeCropThumb(sender, e, "TopLeft");
}
private void topRight_DragDelta(object sender, DragDeltaEventArgs e)
{
ResizeCropThumb(sender, e, "TopRight");
}

private void bottomLeft_DragDelta(object sender, DragDeltaEventArgs e)
{
ResizeCropThumb(sender, e, "BottomLeft");
}

private void bottomRight_DragDelta(object sender, DragDeltaEventArgs e)
{
ResizeCropThumb(sender, e, "BottomRight");
}

// 加载图片
private void BtnLoad_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|所有文件|*.*"
};

if (openFileDialog.ShowDialog() == true)
{
try
{
originalImage = new BitmapImage(new Uri(openFileDialog.FileName));
displayImage.Source = originalImage;
currentScale = 1.0;
UpdateTransform();
}
catch (Exception ex)
{
MessageBox.Show($"加载图片失败: {ex.Message}");
}
}
}

// 放大图片
private void BtnZoomIn_Click(object sender, RoutedEventArgs e)
{
currentScale *= 1.2;
UpdateTransform();
}

// 缩小图片
private void BtnZoomOut_Click(object sender, RoutedEventArgs e)
{
currentScale /= 1.2;
if (currentScale < 0.1) currentScale = 0.1;
UpdateTransform();
}

// 左旋转
private void BtnRotateLeft_Click(object sender, RoutedEventArgs e)
{
displayImage.Source = RotateBitmapImage(displayImage.Source as BitmapImage, -90);
}

// 右旋转
private void BtnRotateRight_Click(object sender, RoutedEventArgs e)
{
displayImage.Source = RotateBitmapImage(displayImage.Source as BitmapImage, 90);
}
public BitmapImage RotateBitmapImage(BitmapImage source, double angle)
{
// 创建旋转变换
var transform = new RotateTransform(angle);

// 创建TransformedBitmap
var transformedBitmap = new TransformedBitmap(source, transform);

// 转换为BitmapImage
var bitmapImage = new BitmapImage();
using (var memoryStream = new MemoryStream())
{
// 将TransformedBitmap编码为PNG
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(transformedBitmap));
encoder.Save(memoryStream);

// 创建新的BitmapImage
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
bitmapImage.Freeze(); // 可选:冻结以提高性能
}

return bitmapImage;
}
// 更新变换
private void UpdateTransform()
{
scaleTransform.ScaleX = currentScale;
scaleTransform.ScaleY = currentScale;
}

// 开始裁剪
private void BtnCrop_Click(object sender, RoutedEventArgs e)
{
if (displayImage.Source == null)
{
MessageBox.Show("请先加载图片");
return;
}
cropThumb.Width = 50;
cropThumb.Height = 50;
Canvas.SetLeft(cropThumb, 0);
Canvas.SetTop(cropThumb, 0);
cropCanvas.Visibility = Visibility.Visible;
}

// 拖动裁剪框
private void CropThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
double newLeft = Canvas.GetLeft(cropThumb) + e.HorizontalChange;
double newTop = Canvas.GetTop(cropThumb) + e.VerticalChange;

// 限制裁剪框不超出图片范围
if (newLeft < 0) newLeft = 0;
if (newTop < 0) newTop = 0;
if (newLeft + cropThumb.Width > imageContainer.ActualWidth)
newLeft = imageContainer.ActualWidth - cropThumb.Width;
if (newTop + cropThumb.Height > imageContainer.ActualHeight)
newTop = imageContainer.ActualHeight - cropThumb.Height;
Canvas.SetLeft(cropThumb, newLeft);
Canvas.SetTop(cropThumb, newTop);
}

// 调整裁剪框大小
private void ResizeCropThumb(object sender, DragDeltaEventArgs e, string corner)
{
double deltaHorizontal = e.HorizontalChange;
double deltaVertical = e.VerticalChange;
double newWidth = cropThumb.Width;
double newHeight = cropThumb.Height;
double newLeft = Canvas.GetLeft(cropThumb);
double newTop = Canvas.GetTop(cropThumb);

switch (corner)
{
case "TopLeft":
newWidth -= deltaHorizontal;
newHeight -= deltaVertical;
newLeft += deltaHorizontal;
newTop += deltaVertical;
break;
case "TopRight":
newWidth += deltaHorizontal;
newHeight -= deltaVertical;
newTop += deltaVertical;
break;
case "BottomLeft":
newWidth -= deltaHorizontal;
newHeight += deltaVertical;
newLeft += deltaHorizontal;
break;
case "BottomRight":
newWidth += deltaHorizontal;
newHeight += deltaVertical;
break;
}


// 限制最小尺寸
if (newWidth < 10) newWidth = 10;
if (newHeight < 10) newHeight = 10;

// 限制不超出边界
if (newLeft < 0)
{
newWidth += newLeft;
newLeft = 0;
}
if (newTop < 0)
{
newHeight += newTop;
newTop = 0;
}
if (newLeft + newWidth > imageContainer.ActualWidth)
newWidth = imageContainer.ActualWidth - newLeft;
if (newTop + newHeight > imageContainer.ActualHeight)
newHeight = imageContainer.ActualHeight - newTop;
cropThumb.Width = newWidth;
cropThumb.Height = newHeight;
Canvas.SetLeft(cropThumb, newLeft);
Canvas.SetTop(cropThumb, newTop);
e.Handled = true;
}

// 保存图片
private void BtnSave_Click(object sender, RoutedEventArgs e)
{
if (displayImage.Source == null) return;

if (cropCanvas.Visibility == Visibility.Visible)
{
CropAndSave();
}
else
{
SaveCurrentImage();
}
}
// 裁剪并保存
private void CropAndSave()
{
try
{
// 计算裁剪区域(考虑缩放和旋转)
double scale = currentScale;
var leftreduce = displayImage.ActualWidth * (1 - scale) / 2;
var topreduce = displayImage.ActualHeight * (1 - scale) / 2;
// 获取裁剪框相对于图片的位置
double left = (Canvas.GetLeft(cropThumb) - leftreduce - xyTransform.X) / scale;
double top = (Canvas.GetTop(cropThumb) - topreduce - xyTransform.Y) / scale;
double width = cropThumb.Width / scale;
double height = cropThumb.Height / scale;
if (left < 0 || top < 0 || width > displayImage.ActualWidth || height > displayImage.ActualHeight)
{
throw new Exception("裁剪区域错误!");
}

// 创建裁剪后的图片
CroppedBitmap croppedBitmap = new CroppedBitmap((BitmapSource)displayImage.Source, new Int32Rect((int)left, (int)top, (int)width, (int)height));
// 保存对话框
SaveFileDialog saveDialog = new SaveFileDialog
{
Filter = "JPEG 图片|*.jpg|PNG 图片|*.png|BMP 图片|*.bmp"
};

if (saveDialog.ShowDialog() == true)
{
string filename = saveDialog.FileName;
string extension = System.IO.Path.GetExtension(filename).ToLower();
BitmapEncoder encoder;
switch (extension)
{
case ".jpg": encoder = new JpegBitmapEncoder(); break;
case ".jpeg": encoder = new JpegBitmapEncoder(); break;
case ".bmp": encoder = new BmpBitmapEncoder(); break;
default: encoder = new PngBitmapEncoder(); break;
}
encoder.Frames.Add(BitmapFrame.Create(croppedBitmap));

using (FileStream stream = new FileStream(filename, FileMode.Create))
{
encoder.Save(stream);
}

MessageBox.Show("图片保存成功!");
}
}
catch (Exception ex)
{
MessageBox.Show($"保存失败: {ex.Message}");
}
}

// 保存当前图片
private void SaveCurrentImage()
{
if (!(displayImage.Source is BitmapSource)) return;
BitmapSource source = displayImage.Source as BitmapSource;
SaveFileDialog saveDialog = new SaveFileDialog
{
Filter = "PNG 图片|*.png|JPEG 图片|*.jpg|BMP 图片|*.bmp"
};

if (saveDialog.ShowDialog() == true)
{
string extension = System.IO.Path.GetExtension(saveDialog.FileName).ToLower();
BitmapEncoder encoder;

switch (extension)
{
case ".jpg": encoder = new JpegBitmapEncoder(); break;
case ".jpeg": encoder = new JpegBitmapEncoder(); break;
case ".bmp": encoder = new BmpBitmapEncoder(); break;
default: encoder = new PngBitmapEncoder(); break;
}

encoder.Frames.Add(BitmapFrame.Create(source));

using (FileStream stream = new FileStream(saveDialog.FileName, FileMode.Create))
{
encoder.Save(stream);
}

MessageBox.Show("图片保存成功!");
}
}

private void imageContainer_MouseWheel(object sender, MouseWheelEventArgs e)
{
currentScale *= e.Delta > 0 ? 1.05 : 0.95;
UpdateTransform();
}

#region 拖拽
private bool moving = false;
private bool getStart = false;
private double startX = 0;
private double startY = 0;
private void imageContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
moving = true;
getStart = false;
imageContainer.CaptureMouse();
}

private void imageContainer_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
moving = false;
imageContainer.ReleaseMouseCapture();
}

private void imageContainer_MouseMove(object sender, MouseEventArgs e)
{
if (!moving) return;
var current = e.GetPosition(imageContainer);
if (!getStart)
{
startX = current.X;
startY = current.Y;
getStart = true;
return;
}
xyTransform.X += (current.X - startX);
xyTransform.Y += (current.Y - startY);
startX = current.X;
startY = current.Y;
}
#endregion
}

 

posted @ 2025-12-11 11:01  echo三毛  阅读(6)  评论(0)    收藏  举报