背景
最近在研究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