嘿!
这是我的设置:
我有一个 ac# 应用程序,可以从一系列图像中提取特征。由于数据集(几千张图像)的大小,它是高度并行化的,这就是为什么我们有一台带有 ssd 的高端机器,它在 Windows7 x64(.NET4 运行时)上运行以解除繁重的工作。我正在使用 Windows 窗体的 Visual Studio 2008 (.NET3.5) 下的 Windows XP SP3 x86 机器上开发它——顺便说一句,没有机会迁移到 WPF。
Edit3: 这很奇怪,但我想我终于知道发生了什么。似乎是在两台机器上产生不同结果的图像格式的编解码器!我不确切知道那里发生了什么,但 xp 机器上的解码器产生的结果比 win7 的更健全。可悲的是,更好的版本仍然在 x86 XP 系统中:(。我想解决这个问题的唯一方法是将输入图像格式更改为无损格式,如 png 或 bmp(愚蠢的我一开始就没有考虑文件格式 :) )。
编辑2: 感谢您的努力。我想我会坚持自己实现一个转换器,这不是我想要的,但我必须以某种方式解决它:)。如果有人正在阅读这篇文章并对我有一些想法,请告诉我。
编辑:
在评论中,我被建议为此使用第三方库。我认为我没有让自己足够清楚,因为我真的不想使用 DrawImage 方法 - 这只是一个有缺陷的快速破解,以获得一个new Bitmap(tmp, ... myPixelFormat)
希望使用一些插值的实际工作。我想要实现的只是将传入的图像转换为带有一些标准插值的通用 PixelFormat。
我的问题如下。一些源图像采用Indexed8bpp jpg格式,与 WinForms 图像处理不太好。因此,在我的图像加载逻辑中,会检查索引图像,它将图像转换为我的应用程序默认格式(例如 Format16bpp),如下所示:
Image GetImageByPath(string path)
{
Image result = null;
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
Image tmp = Image.FromStream(fs); // Here goes the same image ...
if (tmp.PixelFormat == PixelFormat.Format1bppIndexed ||
tmp.PixelFormat == PixelFormat.Format4bppIndexed ||
tmp.PixelFormat == PixelFormat.Format8bppIndexed ||
tmp.PixelFormat == PixelFormat.Indexed)
{
// Creating a Bitmap container in the application's default format
result = new Bitmap(tmp.Width, tmp.Height, DefConf.DefaultPixelFormat);
Graphics g = Graphics.FromImage(result);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// We need not to scale anything in here
Rectangle drawRect = new Rectangle(0, 0, tmp.Width, tmp.Height);
// (*) Here is where the strange thing happens - I know I could use
// DrawImageUnscaled - that isn't working either
g.DrawImage(tmp, drawRect, drawRect, GraphicsUnit.Pixel);
g.Dispose();
}
else
{
result = new Bitmap(tmp); // Just copying the input stream
}
tmp.Dispose();
}
// (**) At this stage the x86 XP memory image differs from the
// the x64 Win7 image despite having the same settings
// on the very same image o.O
result.GetPixel(0, 0).B; // x86: 102, x64: 102
result.GetPixel(1, 0).B; // x86: 104, x64: 102
result.GetPixel(2, 0).B; // x86: 83, x64: 85
result.GetPixel(3, 0).B; // x86: 117, x64: 121
...
return result;
}
我将问题追踪到(*)
. 我认为 InterpolationMode 与它有关,但我选择的其中哪一个没有区别,结果在(**)
两个系统上是不同的。我一直在研究带有一些愚蠢的复制和粘贴行的测试图像数据,以确保以错误的方式访问数据不是问题。
这些图像一起看起来像这个电子反向散射衍射图案。实际的颜色值略有不同,但它们携带了大量信息——插值甚至增强了它。看起来 x86 机器上的合成算法使用 InterpolationMode 属性,而 x64 只是将调色板值散开而不考虑任何插值。
在我对应用程序中的数据实施直方图视图功能之前,我从未注意到两台机器的输出之间有任何差异。在 x86 机器上,它是平衡的,正如人们在观看图像时所期望的那样。另一方面,x64 机器宁愿给出某种稀疏条形图,即索引图像数据的指示。它甚至会影响整个应用程序的整体输出数据——具有相同数据的两台机器上的输出不同,这不是一件好事。
对我来说,这看起来像是 x64 实现中的一个错误,但这只是我 :-)。我只希望 x64 机器上的图像具有与 x86 相同的值。
如果有人有想法,我会非常高兴。我多年来一直在网上寻找类似的行为,但抵抗似乎是徒劳的:)
哦,当心……鲸鱼!