1

それぞれ約 2500 色を置き換えたい 4k 画像 (.png、3840p*2160p) がいくつかあります。

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 プロセッサなど) は、これを数分の 1 秒で実行できるはずです。通常、メインストリーム PC では 0.01 ~ 0.3 秒です。

于 2022-02-24T20:52:00.877 に答える