このコードは私が使っているものと似ています。絶対に、この場合、安全でないコードが唯一の方法です。メモリの周りのピクセルでいっぱいのビットマップをマーシャリングする必要はありません、そしてあなたは比較のためにそれを2回しなければならないでしょう!
ただし、ピクセルを比較することは、2つの数値を比較することと見なす必要があります。ピクセルは色の赤、緑、青の各コンポーネントで3バイトであるため、もちろんアルファ(多くの場合無視されます)は、UInt32の代わりに値を比較することをお勧めします。これには、ある数値(1ピクセル)を別の数値と比較するという利点があります。それらが同じである場合は、次に進みます。
これを機能させるには、バイト*ではなくUInt32*が必要です。第二に、上記のコードは、私が見ることができるストライドを考慮していません。これは、画像の各水平線が実際にはピクセル自体の合計とは異なるバイト数を使用する可能性がある場所です。24ビット(rgb)とアルファ(a)を扱っている可能性が高いため、ピクセルはすでに整列しているはずなので、上記のコードは機能するはずです。しかし、それが100%の確率で行われるという保証はありません。
私は本当にうるさいように聞こえるかもしれませんが、パフォーマンスはあなたにとって何かを意味すると思います-そしてゲームのバックグラウンドから来ると、それは私にも影響します。
(上記のリンクからパート1に移動しました。Karl-JohanSjögrenに感謝します)
BitmapData bData = b.LockBits(new Rectangle(0, 0, _image.Width, _image.Height), ImageLockMode.ReadWrite, b.PixelFormat);
この行に到達するときは、本当に注意する必要があります。ロックしているPixelFormatは、ソース画像のPixelFormatの1つと一致している必要があります。そうしないと、期待どおりに動作しない可能性があります。
LockBitsから、掘り下げる必要のあるBitmapDataを取得します。
byte* scan0 = (byte*)bData.Scan0.ToPointer();
これは私が参照している行です-これをUInt32*にするので、命令ごとに1バイトを読み取るのではなく、UInt32として一度に4バイトを読み取ります。
このメモリに配列としてアクセスします。ストライドが1Yピクセルに相当することを認識して、1次元配列へのオフセットを計算します。したがって、ストライドにYを掛けます。ただし、同じになります。トラップ私はこの時点で何度も持っています!
int stride = bData.Stride / 4; // the width is expressed in bytes, yet we need it as UInt32's. As there's 4 bytes per UInt32, this makes sense of the divide by 4.
したがって、ピクセルの読み取りは次のように行うことができます。
int x = 123;
int y = 321;
UInt32 pixelColour = scan0[(y * stride) + x];
最後に、完了したらビットマップのロックを解除することを忘れないでください。忘れやすいもの。また、変更したピクセルを別のビットマップに保存する場合は、同じ方法でピクセルを書き込む必要があります。ピクセルを読み取るための配列としてポインターを使用する私の例は、ピクセルを書き込むために同じことを行う方法が明らかであるはずだと思います。
もう1つの考え-Jpegやその他の不可逆圧縮画像を比較しようとしていないことを願っています-変更は非常に予測不可能であり、あなたの考えとはまったく異なる可能性があるためです。代わりに、BMPやPNGなどの損失のない画像形式を使用する必要があります。
これが誰かを助けることを願っています。