在 WinRT 应用程序中使用矩形几何进行裁剪
Clipping Using Rectangle Geometry in WinRT application
我以前使用 WriteableBitmapEX 库在鼠标移动的任何地方裁剪图像。好像有点慢。
我想以任意随机像素裁剪图像,我想将该裁剪区域分配给另一个图像控件。
我的问题是当我使用剪辑 属性 时,我只剩下剪辑区域,整个图像都在运行。我希望图像完全在背景中,但应将裁剪区域分配给图像控件。
这是代码。
private void Image1_Tapped(object sender, TappedRoutedEventArgs e)
{
int CropArea = 50;
int PointShift = CropArea / 2;
var _rect = new RectangleGeometry();
Point pt;
pt = e.GetPosition(Image1);
_rect.Rect = new Rect(pt.X - PointShift, pt.Y - PointShift, 100, 100);
Image1.Clip = _rect;
MagnifyTip.Image1.Source=Image1.clip; //This is what I want to do . Its not happenning.
}
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Image x:Name="Image1" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" Tapped="Image1_Tapped" >
<Image.Source >
<BitmapImage UriSource="Assets/Jellyfish.png" />
</Image.Source>
</Image>
</Grid>
欢迎任何更好的解决方案,因为我必须继续在图像周围移动手指,并在我的用户控件的图像框中逐个像素地获取更新的像素裁剪图像
裁剪需要注意的几点
- 为图像的
Clip
属性 使用 RectangleGeometry
(您已经这样做了)
- 调整裁剪几何图形时 - 使用它的
Transform
属性 而不是每次要重新裁剪时都创建一个新的几何图形。
- 更新
WriteableBitmap
相当慢,因此您可以偶尔更新一次 - 例如当您提交裁剪矩形时,但不像每个 PointerMove
事件那样实时提交。
- 如果你想要实时更新,你可以
- 将另一个
Image
元素与另一个 RectangleGeometry
Clip
元素一起使用,其中一个变换是原始变换的缩放版本。您也可以使用原始变换的副本并缩放整个 Image
。
- 使用 DirectX 在
SwapChainPanel
中呈现转换后的输出。
- 对于最终的高分辨率输出,您可以使用任何方法,因为处理速度不是一个重要因素
- 您可以使用
RenderTargetBitmap.RenderAsync()
以屏幕分辨率呈现裁剪后的图像。您可能需要将剪裁后的图像包裹在另一个元素中,例如 Grid
.
- 您可以使用
WriteableBitmap
进行处理 - 我相信 CodePlex 上的 WriteableBitmapEx
project 有旋转和裁剪的方法。这是基于 CPU 的。
- 您可以使用 DirectX,但这可能有点矫枉过正。
- 您可以将 WIC 与
BitmapDecoder
一起使用,但旋转功能有限:How to resize Image in C# WinRT/winmd?
好吧,你不想在背景中剪裁你想要的图像,你想要两个单独的图像控件并且只剪裁你正在放大的图像,这是我如何使用 Canvas和两个图像控件。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="canvas">
<Image Canvas.ZIndex="0" x:Name="Image1" ImageOpened="Image1_Opened" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" Tapped="Image1_Tapped" >
<Image.Source>
<BitmapImage UriSource="Assets/JellyFish.png" />
</Image.Source>
</Image>
<Image Canvas.ZIndex="1" x:Name="MagnifyTip" Visibility="Collapsed">
<Image.Source >
<BitmapImage UriSource="Assets/JellyFish.png" />
</Image.Source>
</Image>
</Canvas>
</Grid>
加载背景图片后,您想要在 canvas 中设置图片的大小。
double _scaleX = 5;
double _scaleY = 5;
double _croppedImageWidth = 100;
double _croppedImageHeight = 100;
private void Image1_Opened(object sender, RoutedEventArgs e)
{
this.Image1.MaxHeight = this.canvas.ActualHeight;
this.Image1.MaxWidth = this.canvas.ActualWidth;
this.MagnifyTip.MaxHeight = this.canvas.ActualHeight;
this.MagnifyTip.MaxWidth = this.canvas.ActualWidth;
this.MagnifyTip.RenderTransform = new ScaleTransform()
{
ScaleX = _scaleX,
ScaleY = _scaleY
};
}
然后您可以在 Image1_Tapped 处理程序中设置放大图像的位置和比例。
private void Image1_Tapped(object sender, TappedRoutedEventArgs e)
{
Point pt = e.GetPosition(this.canvas);
this.MagnifyTip.Clip = new RectangleGeometry()
{
Rect = new Rect()
{
X = pt.X,
Y = pt.Y,
Width = _croppedImageWidth / _scaleX,
Height = _croppedImageHeight / _scaleY
}
};
Canvas.SetLeft(this.MagnifyTip, -pt.X * (_scaleX - 1));
Canvas.SetTop(this.MagnifyTip, -pt.Y * (_scaleY - 1));
this.MagnifyTip.Visibility = Visibility.Visible;
}
重点是
- 使用 Canvas Left, Top and ZIndex 属性将放大图像叠加在背景图像上。
- 根据点击点和比例大小计算放大图像的剪辑大小和位置。
- 使用ScaleTransform放大图像。
我以前使用 WriteableBitmapEX 库在鼠标移动的任何地方裁剪图像。好像有点慢。
我想以任意随机像素裁剪图像,我想将该裁剪区域分配给另一个图像控件。
我的问题是当我使用剪辑 属性 时,我只剩下剪辑区域,整个图像都在运行。我希望图像完全在背景中,但应将裁剪区域分配给图像控件。
这是代码。
private void Image1_Tapped(object sender, TappedRoutedEventArgs e)
{
int CropArea = 50;
int PointShift = CropArea / 2;
var _rect = new RectangleGeometry();
Point pt;
pt = e.GetPosition(Image1);
_rect.Rect = new Rect(pt.X - PointShift, pt.Y - PointShift, 100, 100);
Image1.Clip = _rect;
MagnifyTip.Image1.Source=Image1.clip; //This is what I want to do . Its not happenning.
}
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Image x:Name="Image1" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" Tapped="Image1_Tapped" >
<Image.Source >
<BitmapImage UriSource="Assets/Jellyfish.png" />
</Image.Source>
</Image>
</Grid>
欢迎任何更好的解决方案,因为我必须继续在图像周围移动手指,并在我的用户控件的图像框中逐个像素地获取更新的像素裁剪图像
裁剪需要注意的几点
- 为图像的
Clip
属性 使用RectangleGeometry
(您已经这样做了) - 调整裁剪几何图形时 - 使用它的
Transform
属性 而不是每次要重新裁剪时都创建一个新的几何图形。 - 更新
WriteableBitmap
相当慢,因此您可以偶尔更新一次 - 例如当您提交裁剪矩形时,但不像每个PointerMove
事件那样实时提交。 - 如果你想要实时更新,你可以
- 将另一个
Image
元素与另一个RectangleGeometry
Clip
元素一起使用,其中一个变换是原始变换的缩放版本。您也可以使用原始变换的副本并缩放整个Image
。 - 使用 DirectX 在
SwapChainPanel
中呈现转换后的输出。
- 将另一个
- 对于最终的高分辨率输出,您可以使用任何方法,因为处理速度不是一个重要因素
- 您可以使用
RenderTargetBitmap.RenderAsync()
以屏幕分辨率呈现裁剪后的图像。您可能需要将剪裁后的图像包裹在另一个元素中,例如Grid
. - 您可以使用
WriteableBitmap
进行处理 - 我相信 CodePlex 上的WriteableBitmapEx
project 有旋转和裁剪的方法。这是基于 CPU 的。 - 您可以使用 DirectX,但这可能有点矫枉过正。
- 您可以将 WIC 与
BitmapDecoder
一起使用,但旋转功能有限:How to resize Image in C# WinRT/winmd?
- 您可以使用
好吧,你不想在背景中剪裁你想要的图像,你想要两个单独的图像控件并且只剪裁你正在放大的图像,这是我如何使用 Canvas和两个图像控件。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="canvas">
<Image Canvas.ZIndex="0" x:Name="Image1" ImageOpened="Image1_Opened" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" Tapped="Image1_Tapped" >
<Image.Source>
<BitmapImage UriSource="Assets/JellyFish.png" />
</Image.Source>
</Image>
<Image Canvas.ZIndex="1" x:Name="MagnifyTip" Visibility="Collapsed">
<Image.Source >
<BitmapImage UriSource="Assets/JellyFish.png" />
</Image.Source>
</Image>
</Canvas>
</Grid>
加载背景图片后,您想要在 canvas 中设置图片的大小。
double _scaleX = 5;
double _scaleY = 5;
double _croppedImageWidth = 100;
double _croppedImageHeight = 100;
private void Image1_Opened(object sender, RoutedEventArgs e)
{
this.Image1.MaxHeight = this.canvas.ActualHeight;
this.Image1.MaxWidth = this.canvas.ActualWidth;
this.MagnifyTip.MaxHeight = this.canvas.ActualHeight;
this.MagnifyTip.MaxWidth = this.canvas.ActualWidth;
this.MagnifyTip.RenderTransform = new ScaleTransform()
{
ScaleX = _scaleX,
ScaleY = _scaleY
};
}
然后您可以在 Image1_Tapped 处理程序中设置放大图像的位置和比例。
private void Image1_Tapped(object sender, TappedRoutedEventArgs e)
{
Point pt = e.GetPosition(this.canvas);
this.MagnifyTip.Clip = new RectangleGeometry()
{
Rect = new Rect()
{
X = pt.X,
Y = pt.Y,
Width = _croppedImageWidth / _scaleX,
Height = _croppedImageHeight / _scaleY
}
};
Canvas.SetLeft(this.MagnifyTip, -pt.X * (_scaleX - 1));
Canvas.SetTop(this.MagnifyTip, -pt.Y * (_scaleY - 1));
this.MagnifyTip.Visibility = Visibility.Visible;
}
重点是
- 使用 Canvas Left, Top and ZIndex 属性将放大图像叠加在背景图像上。
- 根据点击点和比例大小计算放大图像的剪辑大小和位置。
- 使用ScaleTransform放大图像。