C# 以最快的方式替换高质量图像中的一堆颜色?

C# Fastest way to replace bunch of colors in high quality Image?

我有一些 4k 图像(.png,3840p*2160p),我想在其中替换大约 2500 种颜色。

我有一个包含 2500 种当前颜色的 Color[] 数组和一个包含 2500 种总是不同的新颜色的数组。

目前我有一个 System.Drawing.Imaging.ColorMap 数组,我在其中推送 2500 个单个 ColorMap 对象,并将它们各自的 OldColor 和 NewColor 属性设置为其他数组中的每个值。

然后我可以做以下事情:

[...]
ImageAttributes imageAttributes = new ImageAttributes();
imageAttributes.SetRemapTable(colorMapArray);
Rectangle rectangle = new Rectangle(0, 0, myImage.Width, myImage.Height);
Graphics graphics = Graphics.FromImage(myImage);
graphics.DrawImage(myImage, rectangle, 0, 0, myImage.Width, myImage.Height, GraphicsUnit.Pixel, imageAttributes);
myImage.Save("myImageWithReplacedColors.png");

这在技术上可行,并用新值替换了我所有的颜色,但速度非常非常慢。 (最多需要几秒钟)

我有什么选择可以加快这个过程? ..或其他获得相同结果的方法?找了几天都没找到

如果有帮助,4k 图像和应替换的当前颜色数组始终相同。所以我可以将它们保存为特殊的,例如作为字节数组(?)

可以先根据this post提取图像的像素点。然后,您可以使用 ((int)color.R << 16) | ((int)color.G << 8) | color.BColor 对象转换为简单的 32 位整数。然后你可以构建一个 Dictionary<int, int> 来映射字典值。然后,您可以将字节转换为 int 像素,使用字典转换值并将整数转换回图像每个像素的一些字节。这个过程可以使用多个线程并行化,因为 Dictionary 是 thread-safe(只要你只从线程读取它)。

或者,您可以使用基本 int[256*256*256] 查找 table 而不是 Dictionary<int, int> class。如果前者适合 CPU 缓存,那么前者可以快得多,但大多数现代处理器还没有这么大的 L3 缓存(即 16 MiB)。它可以更快,因为只有很少的缓存行(最多 2500 个)被加载到缓存中,并且它们可能在内存中分布得很好(参见 cache associativity)。

现代主流处理器(例如 x86-64 处理器)应该能够在几分之一秒内完成此操作:对于主流 PC,通常在 0.01 到 0.3 秒之间。