ここはちょっと不可解です。次のコードは、コードの変更によって回帰が発生していないことを確認するための小さなテスト アプリケーションの一部です。高速化するために、同じサイズの 2 つの画像を比較する最速の方法と思われる方法を使用memcmp
しました(当然のことですが)。
ただし、かなり驚くべき問題を示すいくつかのテスト画像があります。memcmp
ビットマップ データでは、それらが等しくないことがわかりますが、ピクセルごとの比較ではまったく違いが見つかりません。LockBits
onを使用するBitmap
と、画像の実際の生のバイトが得られるという印象を受けました。24 bpp のビットマップの場合、ピクセルが同じであるが、基になるピクセルデータが異なるという状況を想像するのは少し難しいです。
いくつかの驚くべきこと:
- 違いは常に
00
、一方のイメージと他方のイメージにある 1バイトですFF
。 PixelFormat
forLockBits
をFormat32bppRgb
またはに変更するFormat32bppArgb
と、比較は成功します。BitmapData
最初の呼び出しで返された値を 4 番目の引数として 2 番目の引数に渡すLockBits
と、比較は成功します。- 上記のように、ピクセルごとの比較も成功します。
率直に言って、なぜこれが起こるのか想像できないので、私はここで少し困惑しています.
(縮小) 以下のコード。csc /unsafe
24bpp PNG 画像を最初の引数としてコンパイルして渡すだけです。
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
class Program
{
public static void Main(string[] args)
{
Bitmap title = new Bitmap(args[0]);
Console.WriteLine(CompareImageResult(title, new Bitmap(title)));
}
private static string CompareImageResult(Bitmap bmp, Bitmap expected)
{
string retval = "";
unsafe
{
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
var resultData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
var expectedData = expected.LockBits(rect, ImageLockMode.ReadOnly, expected.PixelFormat);
try
{
if (memcmp(resultData.Scan0, expectedData.Scan0, resultData.Stride * resultData.Height) != 0)
retval += "Bitmap data did not match\n";
}
finally
{
bmp.UnlockBits(resultData);
expected.UnlockBits(expectedData);
}
}
for (var x = 0; x < bmp.Width; x++)
for (var y = 0; y < bmp.Height; y++)
if (bmp.GetPixel(x, y) != expected.GetPixel(x, y))
{
Console.WriteLine("Pixel diff at {0}, {1}: {2} - {3}", x, y, bmp.GetPixel(x, y), expected.GetPixel(x, y));
retval += "pixel fail";
}
return retval != "" ? retval : "success";
}
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int memcmp(IntPtr b1, IntPtr b2, long count);
}