在WinRT应用程序中使用矩形几何进行剪切

时间:2015-03-12 12:07:12

标签: c# winrt-xaml rectangles windows-rt

当我的鼠标移动时,我正在使用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>

欢迎任何更好的解决方案,因为我必须继续在图像周围移动手指,并在我的用户控件中的图像框中获取像素裁剪图像的更新

2 个答案:

答案 0 :(得分:1)

嗯,你不想在背景中剪辑你想要的图像,你想要两个单独的图像控件,只剪辑你正在放大的图像,这是我如何使用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>

加载背景图像后,您需要在画布中设置图像的大小。

    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 LeftTopZIndex属性将放大的图像叠加在背景图像上。
  • 根据刻度的点击点和大小计算放大图像的剪辑大小和位置。
  • 使用ScaleTransform放大图像。

答案 1 :(得分:0)

有关裁剪的一些注意事项

  1. 使用RectangleGeometry获取图片的Clip属性(您已经这样做了)
  2. 调整裁剪几何图形时 - 使用其Transform属性,而不是每次要重新创建时都创建新几何图形。
  3. 更新WriteableBitmap的速度相当慢,因此您可能偶尔会这样做 - 例如提交裁剪矩形时,但不是像每个PointerMove事件那样实时。
  4. 如果您想要实时更新,您也可以
    • 将另一个Image元素与另一个RectangleGeometry Clip一起使用,其转换是原始转换的缩放版本。您也可以使用原始转换的副本,然后缩放整个Image
    • 使用DirectX在SwapChainPanel
    • 中呈现转换后的输出
  5. 对于最终的高分辨率输出,您可以使用任何方法,因为处理速度不是一个因素
    • 您可以使用RenderTargetBitmap.RenderAsync()以屏幕分辨率渲染裁剪后的图像。您可能需要将剪切的图像包装在另一个元素中,如Grid
    • 您可以使用WriteableBitmap进行处理 - 我相信CodePlex上的WriteableBitmapEx project具有旋转和裁剪的方法。这是基于CPU的。
    • 您可以使用DirectX,但这可能是一种过度杀伤。
    • 您可以将WIC与BitmapDecoder一起使用,但轮播功能有限:How to resize Image in C# WinRT/winmd?