0

C#/UWP/Win2D アプリケーションで、非標準のピクセル形式に基づくファイルから画像をすばやくアニメーション化しています。画像間に相関関係はありますが (フリップブック アニメーションを考えてください)、プログラム的なものはありません。

プロトタイプを作成し、以下の関連コードを含めました。「白」と「黒」の色は最終的に色のルックアップ テーブルに変換されます (例: 5 = 白)

....
//Create render target in function elsewhere
CanvasRenderTarget crt = new CanvasRenderTarget(Sender, FrameWidth, FrameHeight, defaultDpi);
GenerateNextFrame(crt);
....

private void GenerateNextFrame(CanvasRenderTarget frame)
{
    var frameSize = FrameHeight * FrameWidth * sizeof(ushort);
    var frameBytes = new byte[frameSize];
    var frameShorts = new ushort[FrameWidth * FrameHeight];
    var colors = new Color[FrameWidth * FrameHeight];
    var white = Colors.White;
    var black = Colors.Black;
    var comp = (ushort.MaxValue / 2);

    //read bytes from file
    FrameFileStream.AsStreamForRead().Read(frameBytes, 0, frameSize);
    //convert bytes to shorts
    System.Buffer.BlockCopy(frameBytes, 0, frameShorts, 0, frameSize);

    //convert shorts to colors
    for (var i = 0; i < colors.Length; i++)
    {
        colors[i] = (frameShorts[i] < comp) ? white : black;
    }
    //set colors on frame
    frame.SetPixelColors(colors);
}

FrameWidth/FrameHeight が 512 の場合、パフォーマンスは 60 FPS まで良好ですが、1024 では 30 FPS まで低下します。それよりも大きいと、パフォーマンスがさらに低下します。

これを大きなデータでプロファイリングすると、色配列のループと SetPixelColors 呼び出しがボトルネックであることがわかります。

これを高速化するためにいくつかの方法 (PLINQ、Parallel.ForEach、データの事前キューイング) を試しましたが、上記の形式よりも高速化できませんでした。

これを処理する正しい方法は、CanvasRenderTarget でサポートされている DirectXPixelFormat の新しいタイプを作成して、SetPixelBytes を使用できるようにすることだと思います。それは不可能に思えます。

次の正しいオプションは、frameBytes を受け入れる PixelShaderEffect を記述し、グレースケールでピクセルを作成し、それを別の効果のソースとして使用して色を設定することです。

IGraphicsEffectSource を作成する例を見つけることができませんでした。

アドバイス、ドキュメント、または何よりも、「これは、バイト配列を PixelShaderEffect に渡す方法です」という作業は大歓迎です。

4

0 に答える 0