我正在 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);
}
性能很好~60FPS,FrameWidth/FrameHeight 为 512,但在 1024 时下降到~30FPS。任何比这更大的性能更差。
使用大数据对此进行分析表明,颜色数组的循环和 SetPixelColors 调用是瓶颈。
我尝试了几种方法来加快速度(PLINQ、Parallel.ForEach、数据预排队),但未能比上面找到的形式更快。
我相信处理这个问题的正确方法是为 CanvasRenderTarget 创建一种新的受支持类型的 DirectXPixelFormat,这样我就可以使用 SetPixelBytes。这似乎是不可能的。
下一个正确的选项似乎是编写一个接受 frameBytes 的 PixelShaderEffect,以灰度创建像素,然后将其用作另一个效果的来源来设置颜色。
我找不到任何创建 IGraphicsEffectSource 的示例。
任何建议、文档,或者最重要的是,一个有效的“这是您将字节数组传递到 PixelShaderEffect 的方式”将不胜感激。