C#图片灰度处理(位深度24→位深度8)
#region 灰度处理 /// <summary> /// 将源图像灰度化,并转化为8位灰度图像。 /// </summary> /// <param name="original"> 源图像。 </param> /// <returns> 8位灰度图像。 </returns> public static Bitmap RgbToGrayScale(Bitmap original) { if (original != null) { // 将源图像内存区域锁定 Rectangle rect = new Rectangle(0, 0, original.Width, original.Height); BitmapData bmpData = original.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); // 获取图像参数 int width = bmpData.Width; int height = bmpData.Height; int stride = bmpData.Stride; // 扫描线的宽度,比实际图片要大 int offset = stride - width * 3; // 显示宽度与扫描线宽度的间隙 IntPtr ptr = bmpData.Scan0; // 获取bmpData的内存起始位置的指针 int scanBytesLength = stride * height; // 用stride宽度,表示这是内存区域的大小 // 分别设置两个位置指针,指向源数组和目标数组 int posScan = 0, posDst = 0; byte[] rgbValues = new byte[scanBytesLength]; // 为目标数组分配内存 Marshal.Copy(ptr, rgbValues, 0, scanBytesLength); // 将图像数据拷贝到rgbValues中 // 分配灰度数组 byte[] grayValues = new byte[width * height]; // 不含未用空间。 // 计算灰度数组 byte blue, green, red, YUI; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { blue = rgbValues[posScan]; green = rgbValues[posScan + 1]; red = rgbValues[posScan + 2]; YUI = (byte)(0.229 * red + 0.587 * green + 0.144 * blue); //grayValues[posDst] = (byte)((blue + green + red) / 3); grayValues[posDst] = YUI; posScan += 3; posDst++; } // 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixel posSca