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

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

[C#]LockBits使用筆記

2019-11-17 02:20:03
字體:
供稿:網(wǎng)友

[C#]LockBits使用筆記

昨天想基于一張圖片做個(gè)手機(jī)鎖屏來著,原圖如下:主要是嫌白底太丑了,一開始是想畫圖工具直接油漆桶伺候,然而一澆上去就發(fā)現(xiàn)問題了,變成了這樣:看來得手工處理一下把底色統(tǒng)一了,原圖分辨率挺高的,SetPixel顯然會(huì)太慢,所以只能LockBits咯。LockBits的使用方法和參數(shù)什么的都可以百度和MSDN,不多說,直接貼一個(gè)BitmapWrapper先:

 1 unsafe class BitmapWrapper 2 { 3     PRivate readonly Bitmap bmp; 4     private readonly BitmapData bmpData; 5  6     private readonly byte* scan0; 7     private readonly int byteCount; 8  9     public BitmapWrapper(Bitmap bitmap)10     {11         bmp = bitmap;12         bmpData = bmp.LockBits(13             new Rectangle(0, 0, bmp.Width, bmp.Height),14             ImageLockMode.ReadWrite,15             bmp.PixelFormat);16 17         scan0 = (byte*) bmpData.Scan0;18         // byteCount = bmpData.Stride / bmpData.Width;19         byteCount = bmpData.PixelFormat.ToString().IndexOf("32") > 0 ? 4 : 3;20     }21     public Bitmap UnWrapper()22     {23         bmp.UnlockBits(bmpData);24         return bmp;25     }26     public void SetPixel(Point point, Color color)27     {28         int offset = (point.X - 1) * byteCount + (point.Y - 1) * bmpData.Stride;29         scan0[offset] = color.B;30         scan0[offset + 1] = color.G;31         scan0[offset + 2] = color.R;32         if (byteCount == 4)33             scan0[offset + 3] = color.A;34     }35     public Color GetPixel(Point point)36     {37         int offset = (point.X - 1) * byteCount + (point.Y - 1) * bmpData.Stride;38         Color color = Color.FromArgb(39             scan0[offset + 2],40             scan0[offset + 1],41             scan0[offset]42         );43         if (byteCount == 4)44             color = Color.FromArgb(scan0[offset + 3], color);45         return color;46     }47 }

注意代碼里頭有一句注掉了,那里是我出現(xiàn)第一個(gè)問題的地方。。。本來是想計(jì)算每一像素占的字節(jié)數(shù),那就拿每行的字節(jié)數(shù)除每一行的像素?cái)?shù)咯,于是就錯(cuò)了。。。MSDN查BitmapData.Stride可以看到備注里面的一句話:

跨距是單行像素(一個(gè)掃描行)的寬度,舍入為一個(gè) 4 字節(jié)的邊界。

所以跨距其實(shí)應(yīng)該是等于這樣的:Stride = byteCount * Width + ((byteCount * Width) % 4) == 0 ? 0 : (4 - (byteCount * Width) % 4)于是不知道該怎么反解byteCount,所以用了19行的那個(gè)方法,暫時(shí)忽略其他情況吧。。。第二個(gè)問題是發(fā)生在存取RGB三個(gè)byte值的時(shí)候。因?yàn)槊總€(gè)像素的RGB三個(gè)值是從高位到低位放置的,所以SetPixel里面應(yīng)該是這樣:

scan0[offset] = color.B;scan0[offset + 1] = color.G;scan0[offset + 2] = color.R;

而不是這樣:

scan0[offset] = color.R;scan0[offset + 1] = color.G;scan0[offset + 2] = color.B;

第三個(gè)問題發(fā)生在保存圖片的時(shí)候。。。本來是這么寫的:

bmp.Save("Juven.bmp");

打開圖片再用油漆桶,發(fā)現(xiàn)還是和原來差不多,底色里面仍然參雜了高度接近純白的灰色斑點(diǎn)。因?yàn)镾ave不管你文件擴(kuò)展名是什么的啊!通通默認(rèn)Jpeg啊!一壓縮就前功盡棄了!所以應(yīng)該改成這樣:

bmp.Save(@"Juven.bmp", ImageFormat.Bmp);

這樣就對(duì)了,油漆桶后的效果如下(上傳前轉(zhuǎn)回jpg了,所以這張圖的底色其實(shí)還是不純的):既然都走到這一步了,就干脆走得遠(yuǎn)一點(diǎn),直接代碼做成品了:

 1 Bitmap bmp = new Bitmap(src); 2 BitmapWrapper wrapper = new BitmapWrapper(bmp); 3  4 byte r, g, b; 5 for (int y = 1; y <= bmp.Height; y++) 6 { 7     for (int x = 1; x <= bmp.Width; x++) 8     { 9         Point point = new Point(x, y);10         Color cr = wrapper.GetPixel(point);11         if (cr.R + cr.G + cr.B >= 30)12         {13             if (x < 200)14             {15                 r = 34;16                 g = 177;17                 b = 76;18             }19             else if (x > 395)20             {21                 r = 237;22                 g = 28;23                 b = 36;24             }25             else26                 r = g = b = 255;27             wrapper.SetPixel(point, Color.FromArgb(r, g, b));28         }29         else break;30     }31 32     for (int x = bmp.Width; x > 0; x--)33     {34         Point point = new Point(x, y);35         Color cr = wrapper.GetPixel(point);36         if (cr.R + cr.G + cr.B >= 30)37         {38             if (x < 200)39             {40                 r = 34;41                 g = 177;42                 b = 76;43             }44             else if (x > 400)45             {46                 r = 237;47                 g = 28;48                 b = 36;49             }50             else51                 r = g = b = 255;52             wrapper.SetPixel(point, Color.FromArgb(r, g, b));53         }54         else break;55     }56 }57 wrapper.UnWrapper();58 bmp.Save(target);

成品圖如下:最后想說的是,巴薩梅球王求輕虐十個(gè)以內(nèi)啊!


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 雅江县| 江阴市| 南昌县| 罗江县| 拉孜县| 玉环县| 宁阳县| 焦作市| 上饶市| 马鞍山市| 宣城市| 甘德县| 团风县| 麦盖提县| 静安区| 巫山县| 西盟| 丽水市| 当涂县| 铜山县| 长海县| 突泉县| 舒兰市| 玛曲县| 个旧市| 七台河市| 彰化市| 丰都县| 娄底市| 修水县| 邻水| 乌海市| 贺州市| 鄯善县| 达孜县| 临颍县| 股票| 寿光市| 育儿| 永清县| 广灵县|