首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RenderTargetBitmap图像滑动

RenderTargetBitmap图像滑动
EN

Stack Overflow用户
提问于 2019-04-06 03:52:01
回答 2查看 905关注 0票数 4

每当我呈现画布并清除它的子元素,并将呈现的位图设置为画布的背景时,RenderTargetBitmap就会出现问题,它将滑向右下角。

在10个声誉之前不能插入图像:(

WPF:

代码语言:javascript
复制
<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="500" Width="700"
        KeyDown="Window_KeyDown">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="50"/>
        </Grid.ColumnDefinitions>
        <Border BorderBrush="Black" BorderThickness="1" Grid.Row="1" Grid.Column="1">
            <Canvas x:Name="Pad">
                <Rectangle Height="100" Width="100" Fill="Red" Canvas.Left="10" Canvas.Top="10"></Rectangle>
        </Canvas>
        </Border>
    </Grid>
</Window>

c#代码:

代码语言:javascript
复制
namespace WpfApp1
{
    public partial class MainWindow : Window
    {

         public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            RenderTargetBitmap rendrer = new RenderTargetBitmap(Convert.ToInt32(Pad.ActualWidth),                                                    Convert.ToInt32(Pad.ActualHeight), 96, 96, PixelFormats.Pbgra32);
            rendrer.Render(Pad);
            Pad.Background = new ImageBrush(rendrer);
            Pad.Children.Clear();
        }

    }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-06 06:21:22

您的主要问题源于这样一个事实:由于Canvas周围有一个像素的边框,它的VisualOffset向量是(1,1)。因此,任何视觉效果,如背景刷,将应用在该偏移量。当您将视觉呈现到位图中时,它会捕获当前的外观,然后将位图设置为画笔,则会将其移动。

具有讽刺意味的是,解决这个问题的最简单方法之一是在XAML中插入另一个<Border/>元素:

代码语言:javascript
复制
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="1" Grid.Column="1">
  <Border>
    <Canvas x:Name="Pad">
      <Rectangle Height="100" Width="100" Fill="Red" Canvas.Left="10" Canvas.Top="10"/>
    </Canvas>
  </Border>
</Border>

然后,由外部<Border/>元素引起的偏移将由新的<Border/>元素的转换来处理,而不是应用于<Canvas/>元素。

仅仅这些更改几乎就可以完全修复您的代码。然而,还有一个你可能还会注意到的小工件:每次你渲染视觉时,它都会变得模糊一些。这是因为Brush对象的Stretch属性的默认值是Stretch.Fill,而且由于<Canvas/>元素不是积分宽度或高度,在呈现时位图(它必须具有积分宽度和高度)只会被拉伸。随着每一次迭代,这变得越来越明显。

您可以通过将Stretch属性设置为Stretch.None来修复此问题。同时,您还需要将画笔的对齐设置为LeftTop

代码语言:javascript
复制
private void Window_KeyDown(object sender, KeyEventArgs e)
{
    RenderTargetBitmap renderer = new RenderTargetBitmap(
        Convert.ToInt32(Pad.ActualWidth), Convert.ToInt32(Pad.ActualHeight), 96, 96, PixelFormats.Pbgra32);
    renderer.Render(Pad);
    ImageBrush brush = new ImageBrush(renderer);
    brush.AlignmentX = AlignmentX.Left;
    brush.AlignmentY = AlignmentY.Top;
    brush.Stretch = Stretch.None;
    Pad.Background = brush;
    Pad.Children.Clear();
}

缺省值是Center,这再次导致舍入错误,并将导致图像在过程反复迭代后的移动和模糊。

通过以上的更改,我发现了一个完全稳定的映像,不管迭代的次数是多少。

“包装在边界”的想法来自于这里:https://blogs.msdn.microsoft.com/jaimer/2009/07/03/rendertargetbitmap-tips/

在该页面上,您将找到一个更通用的解决方案,它不需要修改实际的XAML。在上面的示例中,“在边界中包装”方法似乎是一种合理的解决方法,但它显然不像强迫您可以在其中呈现可视化的朴素上下文那样干净,如该博客页面所示。

票数 3
EN

Stack Overflow用户

发布于 2019-04-06 07:12:54

若要避免将Visual绘制到RenderTargetBitmap时出现任何偏移量问题,可以使用中间DrawingVisual:

代码语言:javascript
复制
var rect = new Rect(Pad.RenderSize);
var visual = new DrawingVisual();

using (var dc = visual.RenderOpen())
{
    dc.DrawRectangle(new VisualBrush(Pad), null, rect);
}

var bitmap = new RenderTargetBitmap(
    (int)rect.Width, (int)rect.Height, 96, 96, PixelFormats.Default);
bitmap.Render(visual);

Pad.Background = new ImageBrush(bitmap);
Pad.Children.Clear();

注意,在不设置ImageBrush的任何进一步属性的情况下(例如,它的Viewport),它将填充矩形的整个区域。有关详细信息,请参阅TileBrush概述

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55545728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档