Сохраняем AVI файл из WPF

Опубликовано Июн 13, 2010 в .NET, Particler, WPF | Нет комментариев

Собственно сохранение скриншотов WPF программы с помощью RenderTargetBitmap и BitmapEncoder не новость. Сложнее сохранить анимацию и не просто в набор картинок, а сразу в AVI файл.

Мне удалось найти только один способ сделать это, с использованием весьма старой библиотеки http://www.codeproject.com/KB/audio-video/avifilewrapper.aspx Библиотека предназначена для работы с AVI файлами из .NET, написана на C# и работает даже на .NET 1.1.

Если вы знаете другой способ, подскажите!

Если вы хотите работать с AVI из WPF, посмотрите сразу другой пример http://blogs.msdn.com/b/saveenr/archive/2008/09/22/wpf-xaml-saving-an-animation-as-an-avi-video-file.aspx

Пример хороший, но передавать Bitmap через файл слишком накладно, лучше использовать MemoryStream.

    BmpBitmapEncoder encoder = new BmpBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));

    using (MemoryStream stream = new MemoryStream())
    {
        encoder.Save(stream);

        System.Drawing.Bitmap drawingBitmap = new System.Drawing.Bitmap(stream);
        aviStream.AddFrame(drawingBitmap);
    }

Сохранение AVI было необходимо для улучшения программы Particler, поэтому пришлось провести серию экспериментов.

Оценим быстродействие сохранения AVI файлов из WPF программы, на примере Particler

В первом варианте результаты рендера сохраняются из RenderTargetBitmap с помощью PngBitmapEncoder в PNG файлы.

FPS = 3.5 — сохранение PNG

Добавляем сохранение AVI файла. System.Drawing.Bitmap для AVI фреймов получаем из сохраняемых на диск PNG файлов.

FPS = 2.5 — сохранение PNG + Uncompressed AVI (660 Мб)
FPS = 2.6 — сохранение PNG + Xvid MPEG-4 Codec AVI (540 Кб)

Интересно.
При сохранении AVI даже большого размера, время работы увеличивается всего на 30%.
Причём время записи на диск 650 Мб равнозначно по затратам времени потерям на сжатие этого же объёма данных кодеком MPEG-4.

Модифицируем программу, убираем вообще сохранение PNG файлов на диск, передавая результат кодирования PngBitmapEncoder в Bitmap через MemoryStream.

FPS = 2.5 — PNG через MemoryStream + Uncompressed AVI (660 Мб)
FPS = 2.6 — PNG через MemoryStream + Xvid MPEG-4 Codec AVI (540 Кб)

Ещё чудесатее.
Время не изменилось, так как файлы записывались на диск асинхронно (не явно), совершенно не влияя на работу программы.

Теперь очевидно, что время тратится на кодирование PngBitmapEncoder.
Заменяем его на BmpBitmapEncoder.

FPS = 7.9 — BMP через MemoryStream + Uncompressed AVI (660 Мб)
FPS = 8.7 — BMP через MemoryStream + Xvid MPEG-4 Codec AVI (540 Кб)

И получаем ускорение в 3.5 раза! На этом оптимизацию можно закончить 🙂

Оставить комментарий