现在网上的例子多数都是24位图像转24位灰度图的,即使有转8位灰度的,也是通过GetPixel(转换速度太慢)或者指针方式(一来C#并不推荐这种模式,二来我也没有学过c++之类的对指针实在不熟悉)来实现的,而没有c#推荐的数组方式的.
因为bmp在内存中储存的时候,每行都是必须是4的倍数才可以,开始忘记处理这个间隙,结果导致有的图片可以正常转换,有的图片就发生图像扭曲.
处理完这个后,又发现输出的都是一些带颜色的色点组成的图像,不是灰度图,经过查资料才知道输出的是伪彩色,要转成灰度才可以.
/// 灰度处理(BitmapData类)
/// </summary>
/// <returns>输出8位灰度图片</returns>
public static Bitmap 灰度处理(Bitmap 图像)
{
Bitmap bmp = new Bitmap(图像.Width, 图像.Height, PixelFormat.Format8bppIndexed);
//设定实例BitmapData相关信息
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData data = 图像.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
//锁定bmp到系统内存中
BitmapData data2 = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
//获取位图中第一个像素数据的地址
IntPtr ptr = data.Scan0;
IntPtr ptr2 = data2.Scan0;
int numBytes = data.Stride * data.Height;
int numBytes2 = data2.Stride * data2.Height;
int n2 = data2.Stride - bmp.Width; //// 显示宽度与扫描线宽度的间隙
byte[] rgbValues = new byte[numBytes];
byte[] rgbValues2 = new byte[numBytes2];
//将bmp数据Copy到申明的数组中
Marshal.Copy(ptr, rgbValues, 0, numBytes);
Marshal.Copy(ptr2, rgbValues2, 0, numBytes2);
int n = 0;
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width * 3; x += 3)
{
int i = data.Stride * y + x;
n++;
}
n += n2; //跳过差值
}
//将数据Copy到内存指针
Marshal.Copy(rgbValues, 0, ptr, numBytes);
Marshal.Copy(rgbValues2, 0, ptr2, numBytes2);
//// 下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度
ColorPalette tempPalette;
using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
{
tempPalette = tempBmp.Palette;
}
for (int i = 0; i < 256; i++)
{
tempPalette.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = tempPalette;
//从系统内存解锁bmp
图像.UnlockBits(data);
bmp.UnlockBits(data2);
return bmp;
}
联系客服