无码亚洲国产一区二区三区电影,国产精品综合网,一级做a爰片久久毛片潮喷免费一,精品国产一区二区三av无蜜臀
  • <tbody id="fzefn"></tbody>
    <tbody id="fzefn"></tbody>

    <track id="fzefn"></track>

      <bdo id="fzefn"><optgroup id="fzefn"><thead id="fzefn"></thead></optgroup></bdo>
    1. « 首頁 - 西安必信達軟件技術有限公司 - BXDSOFT.COM
      C#中Image , Bitmap 和 BitmapData
      「先說Image,Image 就是個圖像,不能實例化,提供了位圖和源文件操作的函數。本篇文章他就是來打醬油的,這里提供一個Bitmap轉成BitmapSource的方法。(2023-2-25)」

      C#中Image , Bitmap 和 BitmapData

      先說Image,Image 就是個圖像,不能實例化,提供了位圖和源文件操作的函數。本篇文章他就是來打醬油的,這里提供一個Bitmap轉成BitmapSource的方法。


      1 [DllImport("gdi32")]
      2 static extern int DeleteObject(IntPtr o);
      3 ///
      4 /// bitmap轉換為bitmapsource 以適應wpf的image
      5 ///

      6 ///
      7 ///
      8 public static BitmapSource GetMapSource(Bitmap pic)
      9 {
      10 IntPtr ip = pic.GetHbitmap();
      11 BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
      12 ip, IntPtr.Zero, Int32Rect.Empty,
      13 System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
      14 DeleteObject(ip);
      15 return bitmapSource;
      16 }



      接下來說Bitmap和BitmapData。

      Bitmap類
      Bitmap對象封裝了GDI+中的一個位圖,此位圖由圖形圖像及其屬性的像素數據組成.因此Bitmap是用于處理由像素數據定義的圖像的對象.該類的主要方法和屬性如下:
      1. GetPixel方法和SetPixel方法:獲取和設置一個圖像的指定像素的顏色.
      2. PixelFormat屬性:返回圖像的像素格式.
      3. Palette屬性:獲取和設置圖像所使用的顏色調色板.
      4. Height Width屬性:返回圖像的高度和寬度.
      5. LockBits方法和UnlockBits方法:分別鎖定和解鎖系統內存中的位圖像素.在基于像素點的圖像處理方法中使用LockBits和UnlockBits是一個很好的方式,這兩種方法可以使我們指定像素的范圍來控制位圖的任意一部分,從而消除了通過循環對位圖的像素逐個進行處理,每調用LockBits之后都應該調用一次UnlockBits.
      BitmapData類
      BitmapData對象指定了位圖的屬性
      1. Height屬性:被鎖定位圖的高度.
      2. Width屬性:被鎖定位圖的高度.
      3. PixelFormat屬性:數據的實際像素格式.
      4. Scan0屬性:被鎖定數組的首字節地址,如果整個圖像被鎖定,則是圖像的第一個字節地址.
      5. Stride屬性:步幅,也稱為掃描寬度.

      這里要重點說說Stride屬性,這個和Width有什么區別呢,可以這么說,如果你的圖片大小也就是圖片字節是4的整數倍,那么Stride與Width是相等的,否則Stride就是大于Width的最小4的整數倍。在處理過程中,Stride肯定是4的整數倍,這里是個坑啊。。。



      連接寫在文章底部

      先看看BitmapData的應用,我的場景是,我有一個一維像素點陣數組,里面放的是每個像素點的灰度值,知道寬和高,要轉換成bitmap


      1 ///
      2 /// 像素點陣轉換為bitmap
      3 ///

      4 /// byte[]數組
      5 /// 圖片的寬度
      6 /// 圖片的高度
      7 /// bitmap圖片
      8 public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height)
      9 {
      10 Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
      11 BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
      12 //// 獲取圖像參數
      13 //bmpData.Stride = width;
      14 int stride = bmpData.Stride; // 掃描線的寬度
      15 int offset = stride - width; // 顯示寬度與掃描線寬度的間隙
      16 IntPtr iptr = bmpData.Scan0; // 獲取bmpData的內存起始位置
      17 int scanBytes = stride * height;// 用stride寬度,表示這是內存區域的大小
      18 //// 下面把原始的顯示大小字節數組轉換為內存中實際存放的字節數組
      19 int posScan = 0, posReal = 0;// 分別設置兩個位置指針,指向源數組和目標數組
      20 byte[] pixelValues = new byte[scanBytes]; //為目標數組分配內存
      21 for (int x = 0; x < height; x++)
      22 {
      23 //// 下面的循環節是模擬行掃描
      24 for (int y = 0; y < width; y++)
      25 {
      26 pixelValues[posScan++] = rawValues[posReal++];
      27 }
      28 posScan += offset; //行掃描結束,要將目標位置指針移過那段“間隙”
      29 }
      30 //// 用Marshal的Copy方法,將剛才得到的內存字節數組復制到BitmapData中
      31 System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);
      32 bmp.UnlockBits(bmpData); // 解鎖內存區域
      33 //// 下面的代碼是為了修改生成位圖的索引表,從偽彩修改為灰度
      34 ColorPalette tempPalette;
      35 using (Bitmap tempBmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed))
      36 {
      37 tempPalette = tempBmp.Palette;
      38 }
      39 for (int i = 0; i < 256; i++)
      40 {
      41 tempPalette.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);
      42 }
      43
      44 bmp.Palette = tempPalette;
      45
      46 //// 算法到此結束,返回結果
      47 return bmp;
      48 }



      這代碼也是網上找的,具體哪里已經忘記了。至于24位位圖數據其實就是 一個像素點有rgb三個值而已,道理一樣。

      同樣,我們也可以根據圖片得到他的灰度數組


      1 //8位位圖得到除去文件頭信息的一位灰度數組
      2
      3
      4 BitmapData bmpData = map.LockBits(new System.Drawing.Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
      5
      6 //// 獲取圖像參數
      7
      8 int stride = bmpData.Stride; // 掃描線的寬度
      9
      10 int offset = stride - map.Width; // 顯示寬度與掃描線寬度的間隙
      11
      12 IntPtr iptr = bmpData.Scan0; // 獲取bmpData的內存起始位置
      13
      14 int scanBytes = stride * map.Height;// 用stride寬度,表示這是內存區域的大小
      15
      16 //// 下面把原始的顯示大小字節數組轉換為內存中實際存放的字節數組
      17
      18 mapdata = new byte[scanBytes]; //為目標數組分配內存
      19
      20 System.Runtime.InteropServices.Marshal.Copy(iptr, mapdata, 0, scanBytes); //copy內存中數據到數組中



      這里對與bitmapdata的操作方式是ReadOnly

      為什么說stride是坑呢,因為在工作中,我有一個大小不為4的整數倍的文件,通過上面方法將他們轉為圖片,然后操作之后我需要存回去,繼續存成文件的形式,如果你直接存回去你會發現你的文件變大了。這時候就需要避開stride。其實stride占據的空間什么都沒有做,我們如何遍歷構建圖片,就如何反遍歷回數組就可以了


      public static byte[] GetMapData(byte[] MapData,int width,int height)
      {
      var length = MapData.Length;
      if(width==length/height)
      {
      return MapData;
      }
      int offset=length/height-width;
      var scanBytes = width * height;
      byte[] RawMapData = new byte[scanBytes];
      int posScan = 0, posReal = 0;
      for(int x=0;x {
      for (int y=0;y {
      RawMapData[posScan++] = MapData[posReal++];
      }
      posReal += offset;
      }
      return RawMapData;
      }



      至于24位位圖轉8位位圖,還是看這位博主的博客,他總結了很多,我還是覺得opencv比較快捷方便。

      http://blog.csdn.net/jiangxinyu/article/details/6222302

      另外還看到了一下c#處理圖片的方法,比如光照,霧化,浮雕等,請移步下面鏈接

      http://www.pin5i.com/showtopic-20228.html

      種一棵樹最好的時間是十年前,其次是現在。
      (當郊)
      點擊進入「必信達創業合作論壇」下一篇:c#中實現圖片灰度化技術詳解 »
      Copyright © 1999-2023 西安必信達軟件技術有限公司
      无码亚洲国产一区二区三区电影,国产精品综合网,一级做a爰片久久毛片潮喷免费一,精品国产一区二区三av无蜜臀