RenderTransform RotateTransform模糊图像

时间:2013-02-16 02:57:25

标签: c# wpf xaml animation bitmap

我有以下自定义UserControl代表我的应用中的卡片:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:Core="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Namespace="clr-namespace:MyApp" xmlns:Properties="clr-namespace:MyApp.Properties" Core:Class="MyApp.Card" Height="176" RenderTransformOrigin="0.5,0.5" Width="83" UseLayoutRounding="True">
    <UserControl.LayoutTransform>
        <TransformGroup>
            <RotateTransform/>
            <ScaleTransform/>
        </TransformGroup>
    </UserControl.LayoutTransform>
    <UserControl.RenderTransform>
        <TransformGroup>
            <RotateTransform/>
            <ScaleTransform/>
        </TransformGroup>
    </UserControl.RenderTransform>
    <UserControl.Resources>
        <Namespace:ImagesConverter Core:Key="ImagesConverter"/>
    </UserControl.Resources>
    <Canvas Core:Name="Layout">
        <Image Core:Name="Image" HorizontalAlignment="Left" Source="{Binding Source={Core:Static Properties:Resources.Cards}, Converter={StaticResource ImagesConverter}}" Stretch="None" VerticalAlignment="Top">
            <Image.Clip>
                <RectangleGeometry Core:Name="Clipping" Rect="0,0,83,176"/>
            </Image.Clip>
            <Image.RenderTransform>
                <TranslateTransform Core:Name="Translation" X="0" Y="0"/>
            </Image.RenderTransform>
        </Image>
        <Rectangle Core:Name="Highlight" Canvas.Left="-2" Canvas.Top="-2" Height="180" Opacity="0.7" Stroke="#FFFFF500" StrokeThickness="3" Visibility="Collapsed" Width="87"/>
    </Canvas>
</UserControl>

正如你所看到的...我有一个包含所有卡面的PNG图像,然后,当我在构造函数中创建一个新的卡传递SuitRank枚举值时,我计算出正确剪裁rectagle和图像的翻译。 一切都像魅力一样...除非我尝试使用需要旋转90°的Storyboard动画我的卡片。这是我的代码(StoryboardMainWindow.Resources中定义):

<DoubleAnimation BeginTime="00:00:00.4" Duration="00:00:00.2" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" To="90"/>

结果如下:

enter image description here

enter image description here

我无法理解发生了什么......但是你可以看到,图像会以某种方式拉伸并变得非常模糊。我尝试在我的卡片控件中使用UseLayoutRounding="True",并在我的SnapsToDevicePixels="True"中使用MainWindow按照其他地方的建议...但它不起作用! 当然......如果我使用LayoutTransform而不是RenderTransform来旋转卡片,一切都很完美,而且卡片并不模糊......但是我不能让卡片围绕它的中心和我的动画旋转需要从中心旋转90°。为卡片高度的一半设置动画Canvas.Top以及布局旋转在我看来就像一个非常不完美的解决方案...而且它也使我的动画看起来非常糟糕。 你能建议我一个解决方案吗?

[编辑]我尝试使用RenderOptions.BitmapScalingMode="NearestNeighbor"RenderOptions.EdgeMode="Aliased" ......但它变得更糟:

enter image description here

4 个答案:

答案 0 :(得分:2)

问题在于底层图像以及布局的奇数值为Width(83)。即使设置为“0.5,0.5”,RenderTransformOrigin可能会向上或向下舍入该值,从而导致渲染非常糟糕。 将图像和布局宽度更改为偶数值(82),完全解决了问题。

答案 1 :(得分:1)

您可以尝试更改RenderOptions上的Image并查看是否可以找到有效的设置,我已添加了一个我在应用程序中用于此确切情况的设置示例

   RenderOptions.BitmapScalingMode="NearestNeighbor"
   RenderOptions.EdgeMode="Aliased"

示例:

    <Image RenderOptions.BitmapScalingMode="NearestNeighbor"
           RenderOptions.EdgeMode="Aliased"
           Core:Name="Image" HorizontalAlignment="Left" Source="{Binding Source={Core:Static Properties:Resources.Cards}, Converter={StaticResource ImagesConverter}}" Stretch="None" VerticalAlignment="Top">
        <Image.Clip>
            <RectangleGeometry Core:Name="Clipping" Rect="0,0,83,176"/>
        </Image.Clip>
        <Image.RenderTransform>
            <TranslateTransform Core:Name="Translation" X="0" Y="0"/>
        </Image.RenderTransform>
    </Image>

答案 2 :(得分:1)

您表示使用LayoutTransform可以完美地工作而不会模糊图像。您是否尝试过使用它并将中心指定为旋转轴?

类似的东西:

<Image ...>
  <Image.LayoutTransform>
    <RotateTransform CenterX="0.5" CenterY="0.5" Angle="90"/>
  </Image.LayoutTransform>
</Image>

答案 3 :(得分:1)

正如@Tommaso Belluzzo所说,这是因为RenderTransformOrigin =&#34; 0.5,0.5&#34;
你上面的答案真的解决了我的问题 请允许我将代码显示如下:

System.Drawing.Bitmap bm = null;
//RotateTransform(angle) with RenderTransformOrigin="0.5,0.5" might cause blurry if the width or height is odd,
using (System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(path))
{
    int width = bitmap.Width;
    int height = bitmap.Height;
    if (0 != width % 2) width ++;
    if (0 != height % 2) height ++;
    bm = new System.Drawing.Bitmap(width, height);

    bm.SetResolution(96, 96);
    using (System.Drawing.Graphics g = System.Drawing. Graphics.FromImage(bm))
    {
        //I don't want to do anything which may modify(resize) the original image.
        g.Clear(System.Drawing.Color.White);
        g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
    }
    //bm.Save(directory+@"\tmp.bmp", ImageFormat.Bmp);

}
//.....(show bm)