我正在尝试使用LockBits制作颜色选择器,这样当我将光标移到图片框上时,它会显示光标所在位置的颜色。然而,我感兴趣的是如何使用LockBits来实现这一点。
不幸的是,我的尝试总是显示为白色:
void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Image);
// we will try to get the pixel using raw data and make color from it
BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
// default format is 32bpp argb ( 4 bytes per pixel)
unsafe
{
byte* scanline = (byte*)data.Scan0;
for(int y = 0; y < data.Height; y++)
{
// row
for (int x = 0; x < data.Width; x+=4)
{
int r = scanline[x];
int g = scanline[x+1];
int b = scanline[x+2];
//int a = scanline[x+3];
Color color = Color.FromArgb(255, r, g, b);
pictureBox2.BackColor = color;
}
}
}
bmp.UnlockBits(data);
//Color color = bmp.GetPixel(e.X, e.Y);
}发布于 2016-08-03 05:35:49
以下是解决方案:
unsafe Color getPixel(Bitmap bmp, int x, int y)
{
BitmapData bmData = bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
// not a complete check, but a start on how to use different pixelformats
int pixWidth = bmp.PixelFormat == PixelFormat.Format24bppRgb ? 3 :
bmp.PixelFormat == PixelFormat.Format32bppArgb ? 4 : 4;
IntPtr scan0 = bmData.Scan0;
int stride = bmData.Stride;
byte* p = (byte*)scan0.ToPointer() + y * stride;
int px = x * pixWidth;
byte alpha = (byte) (pixWidth == 4 ? p[px + 3] : 255);
Color color = Color.FromArgb(alpha , p[px + 2], p[px + 1], p[px + 0]);
bmp.UnlockBits(bmData);
return color;
}你可以这样称呼它:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
panel2.BackColor = getPixel((Bitmap)panel1.BackgroundImage, e.X, e.Y);
}当然,您可以使用任何类型的位图源代码,如Label.Image或PictureBox.Image…
颜色通道被称为ARGB,但实际上是有序的BGRA。
请注意,stride是位图像素行的物理宽度,包括可能的etra字节以填充为4字节的倍数。
另请注意,其他使用锁定位的解决方案无需指针即可工作。
正如上面的注释所指出的,这实际上比使用GetPixel慢,因为设置不安全的访问向量会消耗任何增益,即使在读出几个像素时也是如此。
https://stackoverflow.com/questions/38730017
复制相似问题