Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-smooth DoubleAnimation

I am using DoubleAnimation for zooming and panning in and out of map. My map is an image with huge resolution (15,000 x 8,438). The problem is that on first time the zoom animation is very faltering and not smooth, at second time it`s getting better and so on. How can I make my animation smoother or make some cashing of the image or animation before performing it, or maybe using other form of animation?

My Code:

namespace AnimationTest
{

public partial class MainWindow : Window
{
    ScaleTransform transP;
    TranslateTransform trans2P;

    DoubleAnimation animP;
    DoubleAnimation animYP;
    DoubleAnimation animXP;
    TransformGroup myTransformGroupP;

    public MainWindow()
    {
        InitializeComponent();

        transP = new ScaleTransform();
        trans2P = new TranslateTransform();

        myTransformGroupP = new TransformGroup();
        myTransformGroupP.Children.Add(transP);
        myTransformGroupP.Children.Add(trans2P);

        animP = new DoubleAnimation(1, 20, TimeSpan.FromMilliseconds(3000));

        animXP = new DoubleAnimation(0, -14000, TimeSpan.FromMilliseconds(3000));
        animYP = new DoubleAnimation(0, -4000, TimeSpan.FromMilliseconds(3000));
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {

        image1.RenderTransform = myTransformGroupP;
        transP.BeginAnimation(ScaleTransform.ScaleXProperty, animP);
        transP.BeginAnimation(ScaleTransform.ScaleYProperty, animP);

        trans2P.BeginAnimation(TranslateTransform.XProperty, animXP);
        trans2P.BeginAnimation(TranslateTransform.YProperty, animYP);

    }

}
}
like image 278
Dim Avatar asked Jul 02 '13 11:07

Dim


4 Answers

I have not tried your animation approach, i tried to implement my own logic to to this.

First i am inspired by zooming animation used by Picasa. So i tried to implement similar type of animation and this works fine for me on my core2duo processor with image size of 10000x5000 without any lag. This approach consumed a lot of memory, but when i compared my memory usage with Picasa ImageViewer it was almost same. This approach may increase the loading time of your application but this can be handled and not a problem here.

Here is the Code for Main Window Grid that i have Used.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Height="30" Width="100" Content="Zoom" Click="ButtonZoom_OnClick" />
    <Image RenderOptions.BitmapScalingMode="HighQuality" Stretch="Uniform" Width="100" Height="100" Grid.Row="1"
           Margin="30" VerticalAlignment="Center" HorizontalAlignment="Center" Source="mad1.jpg" Name="ImageMain"
           x:FieldModifier="private" />

</Grid>

Button Click event Code

private void ButtonZoom_OnClick(object sender, RoutedEventArgs e)
{
    Task.Factory.StartNew(() =>
        {
            var i = 0;
            while (i++ < 100)
            {
                var i1 = i;
                //var i1 = (-0.00092)*(i*i) + (0.092)*i + 0.2;
                Dispatcher.Invoke(new Action(() =>
                    {
                        if (i1 < 10 || i1 > 90)
                        {
                            ImageMain.Height += 0.5;
                            ImageMain.Width += 0.5;
                        }
                        else if (i1 < 30 || i1 > 70)
                        {
                            ImageMain.Height += 1;
                            ImageMain.Width += 1;
                        }
                        else
                        {
                            ImageMain.Height += 3;
                            ImageMain.Width += 3;
                        }
                    }));
                Thread.Sleep(30);
            }

        });
}

The commented line in this code is a quadratic equation for a smooth animation for acceleration and acceleration of animation. the roots are calculated for starting zooming by 0.2 and half at 2.5 and stops at 0.2 with in range of [0-100]. if you want to create your fully customized animation you may use WolframAlpha to check your animation graph. but the simple approach is to use simple control statements to control your animation.

This code is only for zooming your image, your approach will be similar for zoom out.

like image 189
Mujahid Daud Khan Avatar answered Nov 15 '22 00:11

Mujahid Daud Khan


Have you looked into Microsoft's DeepZoom technology (this is what they use for Bing Maps)? http://msdn.microsoft.com/en-us/library/cc645050(v=vs.95).aspx#deep_zoom_examples

like image 3
New Dev Avatar answered Nov 15 '22 02:11

New Dev


Since you have not shown any XAML I'll try from the most basic - try to reduce bitmap scaling mode with RenderOptions.BitmapScalingMode="LowQuality" on your image element like this:

<Image x:Name="image1"
       Source="huge-image.jpg"
       Stretch="Uniform"
       RenderOptions.BitmapScalingMode="LowQuality" />

Note, that this is only actual if you targeting .NET 3.0-3.5 since starting from .NET 4.0 the "LowQuality" setting is already set as default, so you have no need to specify it explicitly. But if your zoom-in animation still faltering you could try to change this default scaling from LowQuality to even more lower NearestNeighbor which, according to documentation:

...provides performance benefits over LowQuality mode when the software rasterizer is used. This mode is often used to magnify a bitmap.

Also since you are about to show large image with some loss of quality it may be better to specify UseLayoutRounding="True" on your image or it parent element to improve image quality.

like image 3
Sevenate Avatar answered Nov 15 '22 00:11

Sevenate


You want to use a cached composition. Render your map but assign a BitmapCache to the CacheMode property and set the RenderAtScale to a value larger than 1. If you zoom into your map 5x you should use the RenderAtScale with this value as it caches the image for this type of zoom. This may result in a much higher memory consumption but may smooth the scrolling.

Further more Nolonar may be right. You may need to create mipmaps for the image and provide tile rendering to partially load seen tiles as your image is quite large.

like image 2
Samuel Avatar answered Nov 15 '22 00:11

Samuel