WPF APNG рендеринг - PullRequest
       29

WPF APNG рендеринг

0 голосов
/ 16 июня 2019

Я пытаюсь создать механизм рендеринга 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 или просто ошибаюсь при ее реализации, поэтому я надеюсь, что кто-то может помочь мне понять, что яя делаю неправильно.

...