【问题标题】:Clipping Using Rectangle Geometry in WinRT application在 WinRT 应用程序中使用矩形几何进行裁剪
【发布时间】:2015-03-15 09:33:46
【问题描述】:

我以前使用 WriteableBitmapEX 库在鼠标移动的任何地方裁剪图像。好像有点慢。

我想在任何随机像素处裁剪图像,并且我想将该裁剪区域分配给另一个图像控件。

我的问题是,当我使用 clip 属性时,我只得到了被剪裁的区域,而整个图像正在运行。我希望图像完全位于背景中,但应将裁剪区域分配给图像控件。

这是代码。

 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>

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

【问题讨论】:

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


    【解决方案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;
        }
    

    重点是

    • 使用CanvasLeftTopZIndex 属性将放大的图像覆盖在背景图像上。
    • 根据点击点和比例尺大小计算放大图像的剪辑大小和位置。
    • 使用ScaleTransform 放大图片。

    【讨论】:

    • 它将如何与我的用户控件一起使用,因为控件内有一个图像框。我想在父图像上点击我的手指,我的用户控件出现在我手指周围的裁剪区域,现在我继续在图像周围移动手指,无论我的手指在哪里,我的用户控件都会更新为新的裁剪图像!目前我想放弃放大的想法。
    • 用户控件的移动是很有必要的。他 用户 控件 可以 用 手指 上下 左右 移动 . 所以 有时 我 的 手指 会 在 用户 控件 上 向上 移动 .检查这个stackoverflow.com/questions/28740086/…
    • 有什么原因你不能把你的用户控件也放在画布上吗?
    • 没有具体原因!但是你真的认为它会像我想要的那样高效吗?我的 WriteableBitmap 很烂。以及如何将我的用户控件的图像框动态分配给图像?检查我的用户控件 XAML 。 stackoverflow.com/questions/28988606/…
    • 本质上不是在 InkCanvas_PointerMoved 中更新图像本身,您只想设置转换属性 ex。 MagnifyTip.image1.Transform = new ScaleTransform() { CenterX = xValue1/4, CenterY = yValue1/4, ScaleX = 2, ScaleY = 2 };
    【解决方案2】:

    裁剪的一些注意事项

    1. 为图片的Clip 属性使用RectangleGeometry(您已经这样做了)
    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?

    【讨论】:

    • 我知道所有这些理论,我想要一些对我的问题实用的东西。你能帮我解决我上面的代码吗?我使用 WriteableBitmapEx 库进行裁剪,但对于较大的图像它很烂。你能展示一些 4 分和 5 分的演示吗?我需要继续裁剪pointermove并继续在imagecontrol中显示更新的图像
    • 我想了解性能?我需要出色的性能。它应该用我的手指移动和剪辑。没有滞后!哪种方法最快?
    • 转换剪辑几何体应该感觉足够快,但如果你想要最快 - 你应该走 DirectX 路线。虽然工作量很大。
    • directX 剪辑的任何样本.. 我有具体的问题,请您帮帮我吗?我需要完全像视频中显示的那样。我正在开发 Windows 8.1 应用程序 youtube.com/watch?v=0Ie1Z-vk4aE&feature=youtu.be
    • 我的应用程序代码在 C# 中,想在鼠标移动时将免费上的图像裁剪到我的用户控件中。所以它会为每个移动的像素裁剪!有什么帮助吗?
    猜你喜欢
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    相关资源
    最近更新 更多