所以我使用了System.Drawing位图实现,看起来像是在将格式设置为PixelFormat.Format24bppRgb时,它实际上将其解释为24Bgr而不是RGB
latestImage = new Bitmap(bitmap.Width, bitmap.Height, bitmap.Stride, PixelFormat.Format24bppRgb, bitmap.Scan0);
for (int x = 0; x < _latestImage.Width; x++)
{
for (int y = 0; y < _latestImage.Height; y++)
{
var c = _latestImage.GetPixel(x, y);
byte r = Marshal.ReadByte((bitmap.Scan0 + (x * 3) + 0) + (y * bitmap.Stride));
byte g = Marshal.ReadByte((bitmap.Scan0 + (x * 3) + 1) + (y * bitmap.Stride));
byte b = Marshal.ReadByte((bitmap.Scan0 + (x * 3) + 2) + (y * bitmap.Stride));
_latestImage.SetPixel(x, y, System.Drawing.Color.FromArgb(r, g, b));
}
}
_latestImage.Save(temp3, ImageFormat.Jpeg);
对比
_latestImage = new Bitmap(bitmap.Width, bitmap.Height, bitmap.Stride, PixelFormat.Format24bppRgb, bitmap.Scan0);
_latestImage.Save(temp3, ImageFormat.Jpeg);
在第一个例子中,我在所有的东西上循环,手动设置颜色,它工作正常,但永远需要。在第二个例子中,红色和蓝色在图像中交换。
是我疯了还是.net实现错了?
我尝试过不同的格式,但其余的更糟糕。一直在寻找另一个库来处理我的位图数据,但还没有找到解决方案。
1条答案
按热度按时间qxgroojn1#
在第一个例子中,我循环了所有的东西,并手动设置颜色,它的工作很好,但需要永远
当然可以,你调用的
GetPixel
和SetPixel
都非常慢,你可以访问Scan0
中的原始数据,直接通过Span<byte>
写入即可。有趣的是,你甚至没有使用
GetPixel
的结果,你只是为了好玩而调用它?是我疯了还是.net实现错了?
当然,你是这样的,因为你没有考虑你编程的环境,特别是你的机器的字节序(它可能与其他人运行你的代码的字节序相同,也可能不同)。
同样需要注意的是,你的WPF标签和你正在编写的GDI+代码是截然相反的。你的代码是完全在CPU上运行的古老代码。像WPF这样的现代框架在GPU上进行图像处理、存储和显示。