C#中將byte數群組轉換為8bit灰階映像

來源:互聯網
上載者:User

類似的文章在網上可以看到不少,但多多少少都存在一些問題。這兩天做實驗室的項目用到這個功能 ,我從頭把它整理了一遍。

在看代碼之前,首先解釋幾個問題。

byte數組存放的是映像每個像素的灰階值,byte類型正好是從0~255,存放8bit灰階映像的時候,一個 數組元素就是一個像素的灰階值。僅有這個數組還不足以恢複出原來的映像,還必須事Crowdsourced Security Testing道映像的長、 寬值;

建立Bitmap類的時候必須指定PixelFormat為Format8bppIndexed,這樣才最符合映像本身的特性;

Bitmap類雖然提供了GetPixel()、SetPixel()這樣的方法,但我們絕對不能用這兩個方法來進行大規 模的像素讀寫,因為它們的效能實在很囧;

Managed 程式碼中,能不用unsafe就盡量不用。在.NET 2.0中已經提供了BitmapData類及其LockBits()、 UnLockBits()操作,能夠安全地進行記憶體讀寫;

映像的width和它儲存時的stride是不一樣的。位元影像的掃描線寬度一定是4的倍數,因此映像在記憶體中 的大小並不是它的顯示大小;

Format8bppIndexed類型的PixelFormat是索引格式,其調色盤並不是灰階的而是偽彩,因此需要我們 對其加以修改。

代碼如下,解說寫在注釋裡了:

 1         /// <summary>
  2         /// 將一個位元組數群組轉換為8bit灰階位元影像
  3         /// </summary>
  4         /// <param name="rawValues">顯示位元組數組</param>
  5         /// <param name="width">映像寬度</param>
  6         /// <param name="height">映像高度</param>
  7         /// <returns>位元影像</returns>
  8         public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height)
  9         {
10             //// 申請目標位元影像的變數,並將其記憶體地區鎖定
11             Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
12             BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
13                 ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
14
15             //// 擷取映像參數
16             int stride = bmpData.Stride;  // 掃描線的寬度
17             int offset = stride - width;  // 顯示寬度與掃描線寬度的間隙
18             IntPtr iptr = bmpData.Scan0;  // 擷取bmpData的記憶體起始位置
19             int scanBytes = stride * height;   // 用stride寬度,表示這是 記憶體地區的大小
20
21             //// 下面把原始的顯示大小位元組數群組轉換為記憶體中實際存放的位元組數組
22             int posScan = 0, posReal = 0;   // 分別設定兩個位置指標,指向 源數組和目標數組
23             byte[] pixelValues = new byte[scanBytes];  //為目標數組分配內 存
24
25             for (int x = 0; x < height; x++)
26             {
27                 //// 下面的迴圈節是類比行掃描
28                 for (int y = 0; y < width; y++)
29                 {
30                     pixelValues[posScan++] = rawValues [posReal++];
31                 }
32                 posScan += offset;  //行掃描結束,要將目標位置指標移過 那段“間隙”
33             }
34
35             //// 用Marshal的Copy方法,將剛才得到的記憶體位元組數組複製到 BitmapData中
36             System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);
37             bmp.UnlockBits(bmpData);  // 解鎖記憶體地區
38
39             //// 下面的代碼是為了修改產生位元影像的索引表,從偽彩修改為灰階
40             ColorPalette tempPalette;
41             using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
42             {
43                 tempPalette = tempBmp.Palette;
44             }
45             for (int i = 0; i < 256; i++)
46             {
47                 tempPalette.Entries[i] = Color.FromArgb(i, i, i);
48             }
49
50             bmp.Palette = tempPalette;
51
52             //// 演算法到此結束,返回結果
53             return bmp;
54         }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.