C#锁定位图-xy坐标到像素字节的转换
我试图学习图像处理的LockBitmap类,我在下面看到了这段代码。基本上,它返回x-y坐标的颜色 当然,这个方法只有在我执行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
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*高度)
,其工作原理是否相同?