I have a 8 bit bitmap color image. when i do a
Color pixelcolor = b.GetPixel(j,i);
Console.Write(pixelcolor.ToString() + " " );
I get
Color [A=255, R=255, G=255, B=255]
我只需要获取8位值,而不是R、G、B、A分开的24位值。
I have a 8 bit bitmap color image. when i do a
Color pixelcolor = b.GetPixel(j,i);
Console.Write(pixelcolor.ToString() + " " );
I get
Color [A=255, R=255, G=255, B=255]
我只需要获取8位值,而不是R、G、B、A分开的24位值。
使用Bitmap
类本身无法实现此操作。不过,您可以使用LockBits
方法直接访问像素。
public static unsafe Byte GetIndexedPixel(Bitmap b, Int32 x, Int32 y)
{
if (b.PixelFormat != PixelFormat.Format8bppIndexed) throw new ArgumentException("Image is not in 8 bit per pixel indexed format!");
if (x < 0 || x >= b.Width) throw new ArgumentOutOfRangeException("x", string.Format("x should be in 0-{0}", b.Width));
if (y < 0 || y >= b.Height) throw new ArgumentOutOfRangeException("y", string.Format("y should be in 0-{0}", b.Height));
BitmapData data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
try
{
Byte* scan0 = (Byte*)data.Scan0;
return scan0[x + y * data.Stride];
}
finally
{
if (data != null) b.UnlockBits(data);
}
}
使用 Marshal.Copy
的安全替代方案:
public static Byte GetIndexedPixel(Bitmap b, Int32 x, Int32 y)
{
if (b.PixelFormat != PixelFormat.Format8bppIndexed) throw new ArgumentException("Image is not in 8 bit per pixel indexed format!");
if (x < 0 || x >= b.Width) throw new ArgumentOutOfRangeException("x", string.Format("x should be in 0-{0}", b.Width));
if (y < 0 || y >= b.Height) throw new ArgumentOutOfRangeException("y", string.Format("y should be in 0-{0}", b.Height));
BitmapData data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
try
{
Byte[] pixel = new Byte[1];
Marshal.Copy(new IntPtr(data.Scan0.ToInt64() + x + y * data.Stride), pixel, 0, 1);
return pixel[0];
}
finally
{
if (data != null) b.UnlockBits(data);
}
}
Marshal.Copy
来获取字节,从而避免不安全的情况。 - NyergudsGetPixel
常见的问题相同的问题:当循环处理所有内容时,对于每个像素都需要锁定和解锁,在具有成千上万甚至数万像素的图像上操作非常缓慢,而仅检查字节数组的内容则非常快速。 - NyergudsMarshal.Copy
在 x + y*data.Stride
处精确地复制一个字节吗? - Nyergudsnew Rectangle(x, y, 1, 1)
,你实际上只锁定了一个像素,然后data.Scan0
就是你需要的字节的确切地址 ;) - NyergudsBitmap
类中的方法不能直接让您获取调色板索引。
您可以使用Palette
属性获取图像的调色板,然后在那里查找颜色,但这是一个解决方法。
要直接获取调色板索引,您需要使用LockBits
方法直接访问图像数据。您可以使用封送将数据复制到数组中,或者在不安全模式下使用指针进行访问。
Color
值中的 A
属性是 Alpha 组件。它可以具有 0 到 255 的值,其中 0 是完全透明的,255 是完全不透明的。
你需要的值实际上是R
、G
和B
,它们是颜色对应的红色
、绿色
和蓝色
组件的8位位图值。
A
是颜色的Alpha
组件,表示透明度值。如果你不关心它,可以在字符串输出中省略它。
如果您不想使用LockBits,可以这样做:
警告:此方法仅在调色板没有重复值且在设置pixelRGB后未被另一个线程更改时才有效。
/// <summary>
/// Gets the pixel value in bytes. Uses Bitmap GetPixel method.
/// </summary>
/// <param name="bmp">Bitmap</param>
/// <param name="location">Pixel location</param>
/// <returns>Pixel value</returns>
public static byte Get8bppImagePixel(Bitmap bmp, Point location)
{
Color pixelRGB = bmp.GetPixel(location.X, location.Y);
int pixel8bpp = Array.IndexOf(bmp.Palette.Entries, pixelRGB);
return (byte)pixel8bpp;
}