国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

C#中Image,Bitmap和BitmapData

2019-11-14 14:07:22
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

先說(shuō)Image,Image 就是個(gè)圖像,不能實(shí)例化,提供了位圖和源文件操作的函數(shù)。本篇文章他就是來(lái)打醬油的,這里提供一個(gè)Bitmap轉(zhuǎn)成BitmapSource的方法。

 1 [DllImport("gdi32")] 2 static extern int DeleteObject(IntPtr o); 3 /// <summary> 4 /// bitmap轉(zhuǎn)換為bitmapsource 以適應(yīng)wpf的image 5 /// </summary> 6 /// <param name="pic"></param> 7 /// <returns></returns> 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 }

接下來(lái)說(shuō)Bitmap和BitmapData。

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

這里要重點(diǎn)說(shuō)說(shuō)Stride屬性,這個(gè)和Width有什么區(qū)別呢,可以這么說(shuō),如果你的圖片大小也就是圖片字節(jié)是4的整數(shù)倍,那么Stride與Width是相等的,否則Stride就是大于Width的最小4的整數(shù)倍。在處理過(guò)程中,Stride肯定是4的整數(shù)倍,這里是個(gè)坑啊。。。

                                                       

                          盜張圖,連接寫(xiě)在文章底部

先看看BitmapData的應(yīng)用,我的場(chǎng)景是,我有一個(gè)一維像素點(diǎn)陣數(shù)組,里面放的是每個(gè)像素點(diǎn)的灰度值,知道寬和高,要轉(zhuǎn)換成bitmap

 1 /// <summary> 2 /// 像素點(diǎn)陣轉(zhuǎn)換為bitmap 3 /// </summary> 4 /// <param name="rawValues">byte[]數(shù)組</param> 5 /// <param name="width">圖片的寬度</param> 6 /// <param name="height">圖片的高度</param> 7 /// <returns>bitmap圖片</returns> 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     //// 獲取圖像參數(shù)  13     //bmpData.Stride = width;14     int stride = bmpData.Stride;  // 掃描線的寬度  15     int offset = stride - width;  // 顯示寬度與掃描線寬度的間隙  16     IntPtr iptr = bmpData.Scan0;  // 獲取bmpData的內(nèi)存起始位置  17     int scanBytes = stride * height;// 用stride寬度,表示這是內(nèi)存區(qū)域的大小  18     //// 下面把原始的顯示大小字節(jié)數(shù)組轉(zhuǎn)換為內(nèi)存中實(shí)際存放的字節(jié)數(shù)組  19     int posScan = 0, posReal = 0;// 分別設(shè)置兩個(gè)位置指針,指向源數(shù)組和目標(biāo)數(shù)組  20     byte[] pixelValues = new byte[scanBytes];  //為目標(biāo)數(shù)組分配內(nèi)存  21     for (int x = 0; x < height; x++)22     {23         //// 下面的循環(huán)節(jié)是模擬行掃描  24         for (int y = 0; y < width; y++)25         {26             pixelValues[posScan++] = rawValues[posReal++];27         }28         posScan += offset;  //行掃描結(jié)束,要將目標(biāo)位置指針移過(guò)那段“間隙”  29     }30     //// 用Marshal的Copy方法,將剛才得到的內(nèi)存字節(jié)數(shù)組復(fù)制到BitmapData中  31     System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);32     bmp.UnlockBits(bmpData);  // 解鎖內(nèi)存區(qū)域  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     //// 算法到此結(jié)束,返回結(jié)果  47     return bmp;48 }

這代碼也是網(wǎng)上找的,具體哪里已經(jīng)忘記了。至于24位位圖數(shù)據(jù)其實(shí)就是 一個(gè)像素點(diǎn)有rgb三個(gè)值而已,道理一樣。

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

 1 //8位位圖得到除去文件頭信息的一位灰度數(shù)組 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 //// 獲取圖像參數(shù)   7  8 int stride = bmpData.Stride;  // 掃描線的寬度   9 10 int offset = stride - map.Width;  // 顯示寬度與掃描線寬度的間隙  11 12 IntPtr iptr = bmpData.Scan0;  // 獲取bmpData的內(nèi)存起始位置  13 14 int scanBytes = stride * map.Height;// 用stride寬度,表示這是內(nèi)存區(qū)域的大小  15 16 //// 下面把原始的顯示大小字節(jié)數(shù)組轉(zhuǎn)換為內(nèi)存中實(shí)際存放的字節(jié)數(shù)組  17 18 mapdata = new byte[scanBytes];  //為目標(biāo)數(shù)組分配內(nèi)存19 20 System.Runtime.InteropServices.Marshal.Copy(iptr, mapdata, 0, scanBytes); //copy內(nèi)存中數(shù)據(jù)到數(shù)組中

這里對(duì)與bitmapdata的操作方式是ReadOnly

為什么說(shuō)stride是坑呢,因?yàn)樵诠ぷ髦校矣幸粋€(gè)大小不為4的整數(shù)倍的文件,通過(guò)上面方法將他們轉(zhuǎn)為圖片,然后操作之后我需要存回去,繼續(xù)存成文件的形式,如果你直接存回去你會(huì)發(fā)現(xiàn)你的文件變大了。這時(shí)候就需要避開(kāi)stride。其實(shí)stride占據(jù)的空間什么都沒(méi)有做,我們?nèi)绾伪闅v構(gòu)建圖片,就如何反遍歷回?cái)?shù)組就可以了

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<height;x++)    {        for (int y=0;y<width;y++)        {            RawMapData[posScan++] = MapData[posReal++];        }        posReal += offset;    }    return RawMapData;}

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

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

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

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

種一棵樹(shù)最好的時(shí)間是十年前,其次是現(xiàn)在。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南溪县| 大同市| 大足县| 全椒县| 惠来县| 永顺县| 曲松县| 十堰市| 宣汉县| 昌宁县| 宁陵县| 深州市| 江城| 朔州市| 崇州市| 太和县| 秦安县| 隆昌县| 宜昌市| 临夏县| 沈阳市| 锦屏县| 威远县| 泰州市| 固阳县| 清原| 博湖县| 老河口市| 沁源县| 乌兰察布市| 桦甸市| 溧阳市| 普陀区| 枣强县| 宁南县| 高阳县| 左权县| 关岭| 灌云县| 曲沃县| 饶河县|