1

我有一些 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 图像和应替换的具有当前颜色的阵列始终相同。所以我可以将它们特殊保存,例如作为字节数组(?)

4

1 回答 1

1

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

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

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

于 2022-02-24T20:52:00.877 回答