1

我正在尝试学习用于图像处理的 LockBitmap 类,并且遇到了下面发布的这段代码。基本上它返回 xy 坐标的颜色。

当然,这种方法只有在我执行source.LockBits()and Marshal.Copy()/之后才有效unsafe context

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;
}
  1. 什么是cCount,为什么总是这样Depth / 8
  2. int i = ((y * Width) + x) * cCount,这是从 (x,y) 坐标转换为 的固定公式Pixels[i]吗?为什么?
4

2 回答 2

1

首先,cCount一个像素是多少字节(bytes per pixel),Depth一个像素是多少位(bits per pixel)。除以 8 以将位转换为字节。(虽然,Depth / 8效率低下,(int)Math.Ceiling(Depth / 8d)改用)

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

于 2018-04-06T15:14:36.697 回答
0
  1. 并非总是如此,看看这个。这可能是比你更好的实现。

    它可以是 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);
  1. 因为位图作为数组存储在内存中。

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

可以把它想象成你把所有的像素放在一条线上,它从左下角开始,到左上角,最后从左下角的第二行到下图的第二行,一直到右上角。

于 2016-03-22T09:25:29.683 回答