背景
最近在研究C#进行图像处理,在图像处理中算法中,往往都是针对的是矩阵运算的。矩阵其实就是一个二维的数组。
为了图像处理的速度,我们都需要放在内存中处理。但网络上收集的代码,往往都是以一维数组的样子提供结果,这样不利于后期图像的算法实现。
初期通过自己摸索,均不能很好地将一幅图转换成二维数组,于是又在网络上一顿海捞。
终于不负血汗!
也得益于热心人士的信息提供,才有今天的烦恼解除,所以我也将我实现的代码共享给需要朋友们。
提要
之前我一直未能成功进行二维数组转换的根本原因在于未能了解到BitmapData.Stride属性的存在。
BitmapData.Stride属性官方的解释是这样的。
Bitmap对象的跨距宽度,以字节为单位BitmapData.Stride Property (System.Drawing.Imaging)docs.microsoft.com
跨距是一行的像素 (扫描行),向上舍入为 4 字节边界的宽度。如果正跨距,位图是自上而下的。如果为负跨距,位图是自下而上的
咋一看解释,不大好理解。其实它要说的内容概括如下。
- BitmapData.Stride>=图像宽度x3
- BitmapData.Stride<=(图像宽度+1)x3
- 内存数据是以Stride参照换行的,而并非连贯的BGR
而且,Stride还有正负(代表位图的扫描方向),通常为正。
所以,以惯常BRG连续扫图像内存,通常得不到我们想要的结果
代码
using
unsafe 版本 图片转 二维数组(网络上收集)
//private unsafe byte[,] imageToByte(Bitmap bit_Image)//指针方法//{// int cols = bit_Image.Width;// int rows = bit_Image.Height;// System.Drawing.Imaging.BitmapData da = new System.Drawing.Imaging.BitmapData();// da = bit_Image.LockBits(new Rectangle(0, 0,// bit_Image.Width, bit_Image.Height),// System.Drawing.Imaging.ImageLockMode.ReadWrite,// System.Drawing.Imaging.PixelFormat.Format24bppRgb);//图像格式24位RGB ;// int stride = da.Stride;// byte* temp = (byte*)da.Scan0.ToPointer();//创建 byte* 指针格式,获取图像首地址 // byte[,] data = new byte[cols, rows]; //图像列:cols 图像行rows// //指针是一位一位移动的,因此图像转byte时,从第一行第一个位置开始向右移动,每次移动三个位// for (int y = 0; y < rows; y++)// {// for (int x = 0; x < cols; x++) // x是和cols对应,获取一个rgb,x移动三个位// {// data[x, y] = (byte)(temp[0]);// temp += 3; //指针每次移动三个位// }// temp += stride - 3 * cols; //注意要跳过空白的数据段// }// bit_Image.UnlockBits(da);// return data;//}
-----------------------------------------------------------------------------
VB6.0 Picturebox 图像与二维数组互转
Private
使用示例
Private Sub Command1_Click()Dim Val() As ByteReDim Val(0 To 255, 0 To 255) As ByteFor x = 0 To 255For y = 0 To 255Val(x, y) = xNextNextTrans_2D_To_Map Picture1, ValTrans_Map_To_2D Picture1, ValTrans_2D_To_Map Picture1, Val
End Sub