gpt4 book ai didi

c# - Bitmap.LockBits 给出错误的值?

转载 作者:可可西里 更新时间:2023-11-01 09:55:52 32 4
gpt4 key购买 nike

我在将一些代码从 Bitmap.GetPixel 更改为使用 LockBits 返回的直接像素缓冲区时遇到问题。与 GetPixel 相比,LockBits 返回的数据似乎确实给了我不同的颜色值。

这很不幸,因为此更改确实会产生不同的颜色,这会破坏自动化单元测试。我有一个 29*30 像素的 png 文件,我确实将 Format32bppArgb 加载到位图中。这真的是 LockBits 和 GetPixel 返回的数据不同吗?我该如何解决这个问题?

这里是一些用加载的位图重现它的代码

public unsafe static Bitmap Convert(Bitmap originalBitmap)
{
Bitmap converted = new Bitmap(originalBitmap);
Rectangle rect = new Rectangle(0, 0, converted.Width, converted.Height);
var locked = converted.LockBits(rect, ImageLockMode.ReadWrite, originalBitmap.PixelFormat);
byte* pData = (byte*)locked.Scan0;

// bytes per pixel
var bpp = ((int)converted.PixelFormat >> 11) & 31;

byte* r;
byte* g;
byte* b;
byte* a;

for (int y = 0; y < locked.Height; y++)
{
var row = pData + (y * locked.Stride);

for (int x = 0; x < locked.Width; x++)
{
a = row + x * bpp + 3;
r = row + x * bpp + 2;
g = row + x * bpp + 1;
b = row + x * bpp + 0;
var col = Color.FromArgb(*a, *r, *g, *b);
var origCol = originalBitmap.GetPixel(x, y);
if (origCol != col)
{
Debug.Print("Orig: {0} Pixel {1}", origCol, col);
}

}
}
converted.UnlockBits(locked);

return converted;
}

Orig: Color [A=128, R=128, G=128, B=255] Pixel Color [A=128, R=127, G=127, B=255]
Orig: Color [A=0, R=128, G=128, B=255] Pixel Color [A=0, R=0, G=0, B=0]

Orig: Color [A=45, R=128, G=128, B=255] Pixel Color [A=45, R=130, G=130, B=254]
ok -2 -2 +1

大多数时候,似乎要进行一些舍入和转换。我可以强制 LockBits 像 GetPixel 返回的那样返回数据吗?

最佳答案

据我所知,PNG 可以包含颜色配置文件和 Gamma 校正信息以及任何其他可能影响像素最终颜色与其原始表示的内容。

即使我们忽略有关 PNG 的特定知识,一般来说 GetPixel 也可以返回与预期不同的值。

Bitmap.GetPixel 是这样实现的:

public Color GetPixel(int x, int y)
{

int color = 0;

if (x < 0 || x >= Width)
{
throw new ArgumentOutOfRangeException("x", SR.GetString(SR.ValidRangeX));
}

if (y < 0 || y >= Height)
{
throw new ArgumentOutOfRangeException("y", SR.GetString(SR.ValidRangeY));
}

int status = SafeNativeMethods.Gdip.GdipBitmapGetPixel(new HandleRef(this, nativeImage), x, y, out color);

if (status != SafeNativeMethods.Gdip.Ok)
throw SafeNativeMethods.Gdip.StatusException(status);

return Color.FromArgb(color);
}

SafeNativeMethods.Gdip.GdipBitmapGetPixel 的定义是:

[DllImport(ExternDll.Gdiplus, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Unicode)] // 3 = Unicode 
[ResourceExposure(ResourceScope.None)]
internal static extern int GdipBitmapGetPixel(HandleRef bitmap, int x, int y, out int argb);

我们从中学到了什么 hereGdiplus::Bitmap::GetPixel .该功能的文档说:

Remarks

Depending on the format of the bitmap, Bitmap::GetPixel might not return the same value as was set by Bitmap::SetPixel. For example, if you call Bitmap::SetPixel on a Bitmap object whose pixel format is 32bppPARGB, the pixel's RGB components are premultiplied. A subsequent call to Bitmap::GetPixel might return a different value because of rounding. Also, if you call Bitmap::SetPixel on a Bitmap object whose color depth is 16 bits per pixel, information could be lost during the conversion from 32 to 16 bits, and a subsequent call to Bitmap::GetPixel might return a different value.

关于c# - Bitmap.LockBits 给出错误的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13154172/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com