Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 位图.LockBits给出错误的值?_C#_Windows_Gdi - Fatal编程技术网

C# 位图.LockBits给出错误的值?

C# 位图.LockBits给出错误的值?,c#,windows,gdi,C#,Windows,Gdi,我在将一些代码从Bitmap.GetPixel更改为使用LockBits返回的直接像素缓冲时遇到问题。与GetPixel相比,LockBits返回的数据似乎给了我不同的颜色值 这是不幸的,因为这种变化确实会产生不同的颜色,这会破坏自动单元测试。我有一个29*30像素的png文件,我将格式32bpparGB加载到位图中。这真的是因为LockBits和GetPixel返回的数据不同吗。我怎样才能避开这件事 下面是一些用加载的位图重新编程的代码 public unsafe static Bitmap

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

这是不幸的,因为这种变化确实会产生不同的颜色,这会破坏自动单元测试。我有一个29*30像素的png文件,我将格式32bpparGB加载到位图中。这真的是因为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
公共不安全静态位图转换(位图原始位图)
{
位图转换=新位图(原始位图);
矩形rect=新矩形(0,0,转换的.Width,转换的.Height);
var locked=转换的.LockBits(rect、ImageLockMode.ReadWrite、originalBitmap.PixelFormat);
字节*pData=(字节*)已锁定。扫描0;
//每像素字节数
var bpp=((int)converted.PixelFormat>>11)和31;
字节*r;
字节*g;
字节*b;
字节*a;
对于(int y=0;y

大部分时间,但似乎有一些舍入和转换正在进行。我是否可以强制锁位按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);
}
我们从中学到的是。该功能的文档说明:

评论 根据位图的格式,
bitmap::GetPixel
可能返回的值与
bitmap::SetPixel
设置的值不同。例如,如果对像素格式为
32bppPARGB
的位图对象调用
Bitmap::SetPixel
,则像素的RGB分量将被预乘。由于舍入,对
Bitmap::GetPixel
的后续调用可能会返回不同的值。此外,如果对颜色深度为每像素16位的位图对象调用
Bitmap::SetPixel
,则在从32位转换为16位的过程中,信息可能会丢失,随后调用
Bitmap::GetPixel
可能会返回不同的值


PNG不能包含颜色配置文件/伽马设置/任何内容吗?可能
GetPixel
检索像素相对于颜色配置文件的颜色。很明显,原始ARGB值无法存储颜色配置文件,因此您会看到不同的结果。您的bpp变量试图处理像素格式。但除非它是一个32bpp的映像,否则实际上无法工作。至少在LockBits()调用中询问所需的像素格式。PArgb将是一个问题。它还可以通过在原始图像上使用LockBits()来工作。但是代码已经没有意义了,我确实在测试数据中找到了一些24/32bpp的图像。是的,我拒绝其他任何东西。bpp变量提取代码实际上根本不起作用,因为它确实报告了错误的字节数。现在我有了一个支持格式的开关盒。好的,似乎并没有办法解决这个问题。我的图片格式不是PARGB,但似乎PNG也有类似的情况发生。@AloisKraus PARGB只是一个例子。
[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);