这在这里有点令人费解。以下代码是一个小测试应用程序的一部分,用于验证代码更改没有引入回归。为了让它更快,我们使用memcmp
了这似乎是比较两个相同大小的图像的最快方法(不足为奇)。
然而,我们有一些测试图像表现出一个相当令人惊讶的问题:memcmp
位图数据告诉我们它们不相等,但是,逐像素比较根本没有发现任何差异。我的印象是,LockBits
在 a 上使用时,Bitmap
您会得到图像的实际原始字节。对于 24 bpp 位图,有点难以想象像素相同但底层像素数据不同的情况。
一些令人惊讶的事情:
- 差异始终
00
是一个图像和另一个图像中的单个字节FF
。 - 如果将 for 更改为
PixelFormat
or ,则比较成功。LockBits
Format32bppRgb
Format32bppArgb
- 如果将
BitmapData
第一次调用返回的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);
}