四 指针法 C/C++的习惯,不是C#的特点 public static Bitmap RGB2Gray(Bitmap srcBitmap) { int wide = srcBitmap.Width; int height = srcBitmap.Height ; Rectangle rect = new Rectangle(0, 0, wide, height); BitmapData srcBmData = srcBitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); Bitmap dstBitmap = CreateGrayscaleImage(wide, height); BitmapData dstBmData = dstBitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); System.IntPtr srcScan = srcBmData.Scan0; System.IntPtr dstScan = dstBmData.Scan0; Unsafe //启动不安全代码 { byte* srcP = (byte*)(void*) srcScan; byte* dstP = (byte*)(void*) dstScan; int srcOffset = srcBmData.Stride - wide * 3; int dstOffset = dstBmData.Stride - wide ; byte red, green, blue; for (int y = 0; y < height; y++) { for (int x = 0; x <wide ; x++, srcP += 3, dstP++) { blue = srcP [0]; green = srcP [1]; red = srcP [2]; * dstP = (byte)(.299 * red + .587 * green + .114 * blue); } srcP += srcOffset; dstP += dstOffset; } } srcBitmap.UnlockBits(srcBmData); dstBitmap.UnlockBits(dstBmData ); return dstBitmap; }//# 五. 矩阵法 并不是什么新方法,只是将图像数据分做R,G,B三个矩阵(二维数组)存储,类似MATLAB的习惯. public static bool GetRGB(Bitmap Source, out int[,] R, out int[,] G, out int[,] B) { try { int iWidth = Source.Width; int iHeight = Source.Height; Rectangle rect = new Rectangle(0, 0, iWidth, iHeight); System.Drawing.Imaging.BitmapData bmpData = Source.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, Source.PixelFormat); IntPtr iPtr = bmpData.Scan0; int iBytes = iWidth * iHeight * 3; byte[] PixelValues = new byte[iBytes]; System.Runtime.InteropServices.Marshal.Copy(iPtr, PixelValues, 0, iBytes); Source.UnlockBits(bmpData); // 注意这个地方图像的两维方向与数组两维的方向是转置的关系 R = new int[iHeight, iWidth]; G = new int[iHeight, iWidth]; B = new int[iHeight, iWidth]; int iPoint = 0; for (int i = 0; i < iHeight; i++) { for (int j = 0; j < iWidth; j++) { // 注意,Windows 中三基色的排列顺序是 BGR 而不是 RGB! B[i, j] = Convert.ToInt32(PixelValues[iPoint++]); G[i, j] = Convert.ToInt32(PixelValues[iPoint++]); R[i, j] = Convert.ToInt32(PixelValues[iPoint++]); } } return true; } catch (Exception) { R = null; G = null; B = null; return false; } }//# public static Bitmap FromRGB(int[,] R, int[,] G, int[,] B) { int iWidth = G.GetLength(1); int iHeight = G.GetLength(0); Bitmap Result = new Bitmap(iWidth, iHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb); Rectangle rect = new Rectangle(0, 0, iWidth, iHeight); System.Drawing.Imaging.BitmapData bmpData = Result.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb); IntPtr iPtr = bmpData.Scan0; int iStride = bmpData.Stride; int iBytes = iWidth * iHeight * 3; byte[] PixelValues = new byte[iBytes]; int iPoint = 0; for (int i = 0; i < iHeight; i++) for (int j = 0; j < iWidth; j++) { int iG = G[i, j]; int iB = B[i, j]; int iR = R[i, j]; PixelValues[iPoint] = Convert.ToByte(iB); PixelValues[iPoint + 1] = Convert.ToByte(iG); PixelValues[iPoint + 2] = Convert.ToByte(iR); iPoint += 3; } System.Runtime.InteropServices.Marshal.Copy(PixelValues, 0, iPtr, iBytes); Result.UnlockBits(bmpData); return Result; }//# public static bool GetGray(Bitmap srcBitmap, out byte [,] gray) { Bitmap tempBitmap; if (srcBitmap.PixelFormat != PixelFormat.Format8bppIndexed) tempBitmap = ImageProcess.Image.Gray(srcBitmap); else tempBitmap = srcBitmap; int wide = tempBitmap.Width; int height = tempBitmap.Height; gray = new byte [height, wide]; BitmapData gbmData = tempBitmap.LockBits(new Rectangle(0, 0, wide, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); System.IntPtr ScanG = gbmData.Scan0; int gOffset = gbmData.Stride - wide; unsafe { byte* g = (byte*)(void*)ScanG; // for each pixel for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < wide; x++, g++) { gray[y ,x ] =*g; } g += gOffset; } } tempBitmap.UnlockBits(gbmData); return true ; }//# public static Bitmap FromGray(byte [,] Gray) { int iWidth = Gray.GetLength(1); int iHeight = Gray.GetLength(0); Bitmap dstBitmap = ImageProcess.Image.CreateGrayscaleImage(iWidth, iHeight); BitmapData gbmData = dstBitmap.LockBits(new Rectangle(0, 0, iWidth, iHeight), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); System.IntPtr ScanG = gbmData.Scan0; int gOffset = gbmData.Stride - iWidth; unsafe { byte* g = (byte*)(void*)ScanG; // 注意这个地方图像的两维方向与数组两维的方向是转置的关系 for (int i = 0; i < iHeight; i++) { for (int j = 0; j < iWidth; j++) { *g=(byte )Gray[i, j] ; g++; } g += gOffset; } } dstBitmap.UnlockBits(gbmData); return dstBitmap; } //# /*********************************补充******************************************/ /// <summary> /// Create and initialize grayscale image /// </summary> public static Bitmap CreateGrayscaleImage( int width, int height ) { // create new image Bitmap bmp = new Bitmap( width, height, PixelFormat.Format8bppIndexed ); // set palette to grayscale SetGrayscalePalette( bmp ); // return new image return bmp; }//# /// <summary> /// Set pallete of the image to grayscale /// </summary> public static void SetGrayscalePalette( Bitmap srcImg ) { // check pixel format if ( srcImg.PixelFormat != PixelFormat.Format8bppIndexed ) throw new ArgumentException( ); // get palette ColorPalette cp = srcImg.Palette; // init palette for ( int i = 0; i < 256; i++ ) { cp.Entries[i] = Color.FromArgb( i, i, i ); } // set palette back srcImg.Palette = cp; }//# /*********************************END********************************************/

评论