我正在使用Silverlight 4,而且无法正确生成UIElements
中已应用投影的位图。
在我的特定情况下,我使用WriteableBitmap
类来捕获Image
控件的位图,该控件已应用Matrix3DProjection
。该投影表示非仿射变换,其用于将图像变换为任意四边形。然后保存生成的位图以供以后使用。
不幸的是,当WriteableBitmap
抓住UIElement
时,似乎会忽略预测。对于可能附加的任何RenderTransform,情况似乎也是如此,尽管可以通过在接受WriteableBitmap
的{{1}}构造函数上使用重载来解决此问题。似乎没有对预测做出这样的考虑。
以下设计的代码示例说明了这一点。它会转换Transform
而不是Button
组件,但效果是相同的。
XAML:
Image
背后的代码:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="button" Grid.Column="0" Width="100" Height="50" Click="button_Click">Render me</Button>
<Image x:Name="image" Grid.Column="1" Width="200" Height="200" Stretch="Uniform"/>
</Grid>
运行时,您会发现按钮的图像会渲染到public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
button.Projection = new Matrix3DProjection()
{
ProjectionMatrix = new Matrix3D()
{
M11 = 0.825, M12 = -0.513, M13 = 0, M14 = 0.001,
M21 = 0.023, M22 = 0.986, M23 = 0, M24 = -0.002,
M31 = 0, M32 = 0, M33 = 1, M34 = 0,
OffsetX = 0, OffsetY = 0, OffsetZ = 0, M44 = 1
}
};
}
private void button_Click(object sender, RoutedEventArgs e)
{
// Render the button as a bitmap and display
WriteableBitmap bitmap = new WriteableBitmap(button, null);
image.Source = bitmap;
}
}
组件中,但没有原始按钮本身明显的扭曲。
我已尝试在Image
上使用构造函数和Render
方法,并且所有各种重载都没有成功。我还尝试将源WriteableBitmap
嵌套在其他元素中,并在不同级别的树上应用投影,以查看UIElement
是否会在更大的复合结构中作为投影时正确渲染投影。那里也没有运气。
希望我在这里错过了一些简单的东西,但我怀疑在当前版本的Silverlight中这可能是不可能的。
如果这确实是一个死胡同,那么一个可行的替代方案是能够直接将矩阵变换应用于位图,完全绕过整个WriteableBitmap
银光。但是,在获取源位图,通过这样的转换输入像素并收集结果输出时,我真的不知道从哪里开始。变换是非仿射的事实告诉我,将涉及一定程度的插值,并且这种解决方案的数学要求可能很重要。
非常感谢任何帮助或建议。
答案 0 :(得分:0)
尝试使用Silverlight Control Toolkit中的LayoutTransformer
(System.Windows.Controls.Layout.Toolkit程序集)
<UserControl x:Class="SilverlightApplication1.MainPage"
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"
mc:Ignorable="d"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
d:DesignHeight="300" d:DesignWidth="400">
<Canvas x:Name="LayoutRoot" Background="White">
<toolkit:LayoutTransformer x:Name="lt" >
<Button x:Name="button" Click="Button_Click">Click me</Button>
</toolkit:LayoutTransformer>
<Border BorderBrush="Red" BorderThickness="1" Canvas.Left="100" Canvas.Top="100">
<Image x:Name="image" Width="100" Height="100" />
</Border>
</Canvas>
</UserControl>
代码背后:
public MainPage()
{
InitializeComponent();
button.Projection = new Matrix3DProjection() { ProjectionMatrix = new Matrix3D() { M11 = 0.825, M12 = -0.513, M13 = 0, M14 = 0.001, M21 = 0.023, M22 = 0.986, M23 = 0, M24 = -0.002, M31 = 0, M32 = 0, M33 = 1, M34 = 0, OffsetX = 0, OffsetY = 0, OffsetZ = 0, M44 = 1 } };
}
private void Button_Click(object sender, RoutedEventArgs e)
{
WriteableBitmap bitmap = new WriteableBitmap(lt, null);
image.Source = bitmap;
}
答案 1 :(得分:0)
我的问题的解决方案变得简单。只需将源UIElement
作为另一个的子项,然后将投影应用于子元素,但在渲染到WriteableBitmap
时使用父元素。修改后的代码示例如下:
XAML:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="border" Width="200" Height="200" Grid.Column="0">
<Button x:Name="button" Width="120" Height="50" Click="button_Click">Render me</Button>
</Border>
<Image x:Name="image" Grid.Column="1" Width="200" Height="200"/>
</Grid>
背后的代码:
public MainPage()
{
InitializeComponent();
button.Projection = new Matrix3DProjection()
{
ProjectionMatrix = new Matrix3D()
{
M11 = 0.825, M12 = -0.513, M13 = 0, M14 = 0.001,
M21 = 0.023, M22 = 0.986, M23 = 0, M24 = -0.002,
M31 = 0, M32 = 0, M33 = 1, M34 = 0,
OffsetX = 0, OffsetY = 0, OffsetZ = 0, M44 = 1
}
};
}
private void button_Click(object sender, RoutedEventArgs e)
{
// Render the button as a bitmap and display
WriteableBitmap bitmap = new WriteableBitmap(border, null);
image.Source = bitmap;
}
感谢@foson让我更加努力地看待它。