Я пытаюсь создать механизм рендеринга APNG-анимации в WPF.Большинство источников, которые я нашел, либо недоступны, либо ограничены, поэтому я решил попробовать сделать свой собственный рендер.То, что я написал, еще не идеально, поскольку у него слишком высокая загрузка ЦП (~ 20%), но проблема, с которой я сталкиваюсь, связана с утилизацией фреймов.Я либо получаю слишком много анимации, либо слишком мало.Уничтожение слишком большого количества результатов приводит к «сбою» анимации, которая иногда внезапно исчезает.Утилизация с меньшим количеством результатов приводит к тому, что фрагменты предыдущих кадров остаются на изображении и не исчезают до следующего цикла.
В соответствии со спецификацией APNG, вы располагаете кадр сразу после рендеринга, вместо удаления предыдущего кадра,Вот что я попробовал.Это код, который я использую для визуализации фрейма.
private static void RenderImage(Image image, Frame frame)
{
image.Dispatcher.Invoke(() =>
{
if (frame.fcTLChunk.SequenceNumber == 0)
DisposeImageSource(image);
var src = GetImageFromStream(frame.GetStream());
var xOff = Convert.ToInt32(frame.fcTLChunk.XOffset);
var yOff = Convert.ToInt32(frame.fcTLChunk.YOffset);
var wbSrc = new WriteableBitmap(src);
var current = image.Source?.CloneCurrentValue();
var wb = (WriteableBitmap)image.Source ?? BitmapFactory.New((int)image.Width, (int)image.Height);
var rec = new Int32Rect(xOff, yOff, src.PixelWidth, src.PixelHeight);
var stride = wbSrc.BackBufferStride;
wb.WritePixels(rec, wbSrc.BackBuffer, wbSrc.PixelHeight * stride, stride);
image.Source = wb;
switch (frame.fcTLChunk.DisposeOp)
{
case DisposeOps.APNGDisposeOpBackground:
DisposeImageSource(image);
break;
case DisposeOps.APNGDisposeOpPrevious:
if (frame.fcTLChunk.SequenceNumber == 0)
goto case DisposeOps.APNGDisposeOpBackground;
image.Source = current;
break;
}
});
}
Вероятно, я неправильно понимаю спецификацию APNG или просто ошибаюсь при ее реализации, поэтому я надеюсь, что кто-то может помочь мне понять, что яя делаю неправильно.