C#锁定位图-xy坐标到像素字节的转换

C#锁定位图-xy坐标到像素字节的转换,c#,bitmap,theory,lockbits,C#,Bitmap,Theory,Lockbits,我试图学习图像处理的LockBitmap类,我在下面看到了这段代码。基本上,它返回x-y坐标的颜色 当然,这个方法只有在我执行source.LockBits()和Marshal.Copy()/不安全上下文之后才有效 public Color GetPixel(int x, int y, Bitmap source) { int Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat); int Wid

我试图学习图像处理的LockBitmap类,我在下面看到了这段代码。基本上,它返回x-y坐标的颜色

当然,这个方法只有在我执行
source.LockBits()
Marshal.Copy()
/
不安全上下文之后才有效

public Color GetPixel(int x, int y, Bitmap source)
{
    int Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
    int Width = source.Width;
    int Height = source.Height;
    Color clr = Color.Empty;

    // Get color components count
    int cCount = Depth / 8;
    int PixelCounts = Width * Height;
    byte[] Pixels = new byte[cCount * PixelCounts];

    // Get start index of the specified pixel
    int i = ((y * Width) + x) * cCount;

    byte b = Pixels[i];
    byte g = Pixels[i + 1];
    byte r = Pixels[i + 2];
    byte a = Pixels[i + 3]; // a
    clr = Color.FromArgb(a, r, g, b);

    return clr;
}
  • 什么是
    cCount
    ,为什么总是
    Depth/8
  • inti=((y*Width)+x)*cCount
    ,这是将(x,y)坐标转换为
    像素[i]
    的固定公式吗?为什么?
  • 并非总是如此,检查一下这可能是一个优于您的实现

    它可以是8、16、24、32等,因为颜色信息需要8(或16等)字节

  • 来自发布源的示例代码:

     // Get start index of the specified pixel
            int i = ((y * Width) + x) * cCount;
    
            if (i > Pixels.Length - cCount)
                throw new IndexOutOfRangeException();
    
            if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                byte a = Pixels[i + 3]; // a
                clr = Color.FromArgb(a, r, g, b);
            }
            if (Depth == 24) // For 24 bpp get Red, Green and Blue
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                clr = Color.FromArgb(r, g, b);
            }
            if (Depth == 8)
            // For 8 bpp get color value (Red, Green and Blue values are the same)
            {
                byte c = Pixels[i];
                clr = Color.FromArgb(c, c, c);
    
  • 因为位图作为数组存储在内存中

    (y*Width)是维度,+x)是维度中的像素,*cCount是每个像素的步长。(每个像素都需要在内存中计算字节。)


  • 把所有像素放在一行,从左下角开始,到左上角,最后从左下角到第二行上下角,一直到右上角。

    首先,
    cCount
    是一个像素的字节数(
    每个像素的字节数
    ),
    深度
    是一个像素的位数(
    每个像素的位数
    )。用8除法将位转换为字节。(尽管,
    Depth/8
    效率低下,但请改用
    (int)Math.天花(Depth/8d)


    要回答第二个问题,将逐行排列像素。由于每一行都是
    width
    像素,因此每一行的大小将
    width*cCount
    字节。如果您想获得第二行的位置,可以使用
    ((2-1)*宽度)*cCount
    。如果要获取该行中第四个像素的位置,可以使用
    ((2-1)*width+(4-1))*cCount
    。因此,要获得带有坐标的像素的位置,
    (x,y)
    ,您可以使用公式,
    (y*width+x)*cCount

    ,这是非常简单的,并且只适用于简单的32位位图(忽略
    像素
    从一开始就不会获得任何数据)。它不处理调色板、对齐、位对齐(并非所有位图都是“字节对齐”的)等。如果你想绕过安全的GDI+方法,你需要做一些研究——快速代码的关键通常是忽略与你无关的边缘情况,但这意味着首先要知道边缘情况是什么,如果你能安全地忽略它们,我会理解的。@Luaan,谢谢你的回复。我真的想做更多关于这方面的研究。你有什么教程/网站可以推荐吗?我甚至不知道谷歌应该用什么关键词。问题是,所有这些都是古老的、低级的东西。这主要是你必须从许多不同的来源拼凑起来的知识,很可能根本不值得。即使是现在的游戏都在使用32位ARGB(好吧,除了那些转到HDR:P的)。例如,如果你可以假设某个像素格式,你可以忽略几乎所有的复杂性——确保这一点的一个可能方法是简单地选择最常见的格式(MSPaint的32位是当今Windows上最常见的),然后依靠GDI+从其他格式转换。根据该网站,它总是深度/8。我实际上想知道这是什么
    颜色组件
    。据我理解,
    深度
    这里是
    bpp
    。那么为什么cCount总是
    bpp/8
    ?@Liren深度是以位为单位的,您正在寻址字节。一个字节有8位。当然,当深度为7、2或14时,这种情况就会发生,例如:)@Liren yep就是这样,dw,这发生在我们所有人身上。我解释了为什么它的
    ((y*宽度)+x)*cCount
    帮助?我现在理解了
    *cCount
    部分。但是为什么
    (y*宽度)+x
    ?为什么要与宽度相乘?对于y+(x*高度)
    ,其工作原理是否相同?