Windows Phone实用开发技巧(40):使用NGif创建GIF图片

NGif是.net 中用来创建gif图片的类库,可以迁移到windows phone中来,在windows phone中创建gif图片。

Gif动画就是在一定时间间隔内,将图片依次显示,将多幅图像保存为一个图像文件,从而形成动画。

把NGif迁移到windows phone有两种不同的方式

1. 在原始的NGif中采用image对象表示当前帧的图像,windows phone中也有image对象,直接使用,只要修改部分不兼容的代码即可

2. 使用WriteableBitmap代替image,用来表示当前帧的图像。

在文字末尾的示例demo中两种方式都有源代码提供。

方式一:

在NGif中,使用了GDI技术,我们可以使用WriteableBitmap的扩展方法去替换。

Image temp =
    new Bitmap(width, height);
Graphics g = Graphics.FromImage(temp);
g.DrawImage(image, 0, 0);
image = temp;
g.Dispose();

可以写为

WriteableBitmap temp = new WriteableBitmap(image,null);
temp.Resize(width, height, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
image = new Image { Source = temp };

至于其他的迁移代码可以在源代码中查看。

本文将会使用迁移后的NGif从相册中选择图片,制作GIF图片以及最后在程序中显示制作的图片。首页运行效果如下:

20120911wp701

图片选择的模板如下:

        <DataTemplate x:Key="DT_Image">
            <Grid>
                <Button Click="Button_Click">
                    <Button.Template>
                        <ControlTemplate>
                            <Image Source="{Binding Thumbnail}" Height="100" Width="100" Margin="5" />
                        </ControlTemplate>
                    </Button.Template>
                </Button>
                <Image Source="selected.png" 
                       Height="32" Width="32" 
                       Visibility="{Binding IsSelectedVisibility}" 
                       HorizontalAlignment="Right" 
                       VerticalAlignment="Bottom"/>
            </Grid>            
        </DataTemplate>

 

ListBox代码如下:

            <ListBox x:Name="lbDefault" Margin="7,-10,0,0" 
                     ItemTemplate="{StaticResource DT_Image}" 
                     ItemsSource="{Binding DefaultImages}">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <toolkit:WrapPanel/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
            </ListBox>

 

至于从相册中加载图片可以查看程序源代码。

看一下制作GIF的代码

private void btn2_Click(object sender, RoutedEventArgs e)
{
    List<PhotoCell> list = new List<PhotoCell>();
    foreach (var item in defaultImages)
    {
        if (item.IsSelectedVisibility == System.Windows.Visibility.Visible)
        {
            list.Add(item);
        }
    }
    if (list.Count == 0)
    {
        MessageBox.Show("请选择图片");
        return;
    }

    String outputFilePath = "test2.gif";
    GifLib2.AnimatedGifEncoder maker = new GifLib2.AnimatedGifEncoder();
    maker.Start(outputFilePath);
    maker.SetDelay(500);
    //-1:no repeat,0:always repeat
    maker.SetRepeat(0);

    foreach (var item in list)
    {
        maker.AddFrame(item.Image.Resize(320, 320, WriteableBitmapExtensions.Interpolation.NearestNeighbor));
    }
    maker.Finish();
    MessageBox.Show("done, find it in iso named :" + outputFilePath);
    NavigationService.Navigate(new Uri("/DisplayGifPage.xaml?name=" + outputFilePath, UriKind.Relative));
}

 

首先实例化AnimatedGifEncoder对象,设置其输出路径,间隔时间,以及重复次数,然后将要制作的图片添加到其帧中就可以了。

制作Gif完成后,我们会在程序中显示制作的Gif,此时就要用到GifDecoder了,将Gif解码为一张张图片。

private void LoadGif(string name)
{
    GifDecoder decoder = new GifDecoder();
    using (var store = IsolatedStorageFile.GetUserStoreForApplication())
    {
        if (!store.FileExists(name))
        {
            MessageBox.Show("gif image 不存在");
            return;
        }
        using (var stream = store.OpenFile(name, System.IO.FileMode.Open, System.IO.FileAccess.Read))
        {
            decoder.Read(stream);

            //get frame size to set image size
            Size size = decoder.GetFrameSize();
            image.Width = size.Width;
            image.Height = size.Height;

            int delay = decoder.GetDelay(1);

            //0 stand for loop forever, otherwise is the real count
            int loopCount = decoder.GetLoopCount();
            //decoder.GetLoopCount
            int imagecount = decoder.GetFrameCount();
            for (int i = 0; i < imagecount; i++)
            {
                imageList.Add(decoder.GetFrame(i));
            }
            DisplayGif(delay, loopCount);
        }
    }
}

从独立存储空间中加载Gif,并且获取他的一些属性:重复次数,帧数,以及每一帧对应的图像,然后使用一个Timer将其显示即可:

private void DisplayGif(int delay, int loopCount)
{
    DispatcherTimer timer = new DispatcherTimer();
    timer.Interval = TimeSpan.FromMilliseconds(delay);
    int index = 0;
    int loopedCount = 0;//已经循环的次数
    timer.Tick += (sender, e) =>
    {
        //如果是永远循环
        if (loopCount == 0)
        {
            if (index == imageList.Count - 1)
            {
                index = 0;
            }
        }
        else
        {
            if (loopCount == loopedCount)
            {
                timer.Stop();
            }
            loopedCount++;
        }
        image.Source = imageList[index];
        index++;
    };
    timer.Start();
}

本文仅仅讲述了如何在windows phone中制作Gif,并且解码并显示Gif,其中很多代码可以优化,大家可以酌情使用本示例中的代码。

源代码可以在这里找到。

posted @ 2012-09-11 10:23 Alexis 阅读(...) 评论(...) 编辑 收藏