1、Spuria編寫目的編程
昨天晚上由於須要把一些照片的邊緣變亮(或者說變淺),忽然有了寫一個程序去處理的想法。Spuria能夠讀取一張圖片,將圖片的邊緣部分加亮,而後將處理後的圖片保存到用戶指定的位置。函數
Spuria下載地址:http://pan.baidu.com/s/1gdFxIdtspa
原圖片與處理後圖片的對比:設計
2、圖片加亮的方法code
由於我也沒有太多圖片處理方面的編程經驗,用的方法比較笨,就是逐個像素地處理。orm
我用的方法以一張圖片的左上角爲例:事件
處理後的圖片比較大,是本程序的一個缺點。新圖片用QQ截圖後再保存能夠獲得一張看上去同樣但小得多的圖片。圖片
3、界面設計ci
控件TrackBar:tkbDepth圖片處理
用來調節圖片變量的深度,數值越大,程序就會在圖像邊緣越大的地區進行漸變處理
控件ProgressBar:pgbTmp
是程序處理圖片時臨時顯示的處理進度條
用戶能夠單擊瀏覽按鈕從磁盤中讀取圖片,左側顯示原圖片,右側顯示當前處理後的圖片。
經過tkbDepth將右側圖片調整滿意後單擊保存按鈕將生成後的文件保存到磁盤。
4、程序代碼
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Spuria { public partial class SpuriaTool : Form { #region 窗體初始化 public SpuriaTool() { InitializeComponent(); } private void SpuriaTool_Load(object sender, EventArgs e) { //初始化默認圖片 if (pcbLeft.Image != null) { //初始化右側修改後圖片:按TrackBar的值進行修改 pcbRight.Image = null; pcbRight.Image = LightenMargin( pcbLeft.Image.Clone() as Bitmap, tkbDepth.Value); } } #endregion #region 控件事件 //讀入一張新圖片 private void btnBrowse_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.AutoUpgradeEnabled = true; ofd.CheckFileExists = true; ofd.CheckPathExists = true; ofd.ReadOnlyChecked = false; ofd.Multiselect = false; ofd.FileName = ""; ofd.Filter = "PNG|*.png|BMP|*.bmp|JPG|*.jpg|GIF|*.gif"; ofd.Title = "打開圖片"; if (ofd.ShowDialog() == DialogResult.OK) { try { //顯示讀入圖片地址,初始化左側圖片框 txtAddress.Text = ofd.FileName; pcbLeft.Load(ofd.FileName); //在右側圖片框中展現修改後的圖片 pcbRight.Image = LightenMargin( pcbLeft.Image.Clone() as Bitmap, 10); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } //將修改後的圖片保存到磁盤 private void btnSave_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog(); sfd.OverwritePrompt = true; sfd.Filter = "PNG|*.png|BMP|*.bmp|JPEG|*.jpeg|GIF|*.gif"; sfd.FileName = string.Concat("Spuria_", DateTime.Now.Year.ToString("#0000"), DateTime.Now.Month.ToString("#00"), DateTime.Now.Day.ToString("#00"), DateTime.Now.Hour.ToString("#00"), DateTime.Now.Minute.ToString("#00"), DateTime.Now.Second.ToString("#00")); sfd.Title = "保存圖片"; if (sfd.ShowDialog() == DialogResult.OK) { switch (sfd.FilterIndex) { case 0: { pcbRight.Image.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Png); } break; case 1: { pcbRight.Image.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Bmp); } break; case 2: { pcbRight.Image.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Jpeg); } break; case 3: { pcbRight.Image.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Gif); } break; default: break; } } } //當鼠標從TrackBar上鬆開時觸發 private void tkbDepth_MouseUp(object sender, MouseEventArgs e) { if (pcbLeft.Image != null) { pcbRight.Image = null; pcbRight.Image = LightenMargin( pcbLeft.Image.Clone() as Bitmap, tkbDepth.Value); } } #endregion 控件 #region 相關函數 /// <summary> /// 將一個Bitmap圖片的邊緣加亮 /// </summary> /// <param name="bitmap">原圖片</param> /// <param name="depth">加亮深度</param> /// <returns>加亮後圖片</returns> public Bitmap LightenMargin(Bitmap bitmap, int depth) { //輸入合法性檢查 if (bitmap == null) return null; if (depth <= 0) return bitmap; //顯示進度條 pgbTemp.Visible = true; pgbTemp.Value = 0; Bitmap result = new Bitmap(bitmap.Width, bitmap.Height); //minx:橫向到邊框的最短距離 miny:縱向到邊框的最短距離 int minx, miny, mindistance; float coefficient; for (int i = 0; i < bitmap.Width; i++) { for (int j = 0; j < bitmap.Height; j++) { minx = i < bitmap.Width - i ? i : bitmap.Width - i; miny = j < bitmap.Height - j ? j : bitmap.Height - j; //四個角的狀況,做與兩邊相切半徑爲depth的四個圓 if (minx <= depth && miny <= depth) { mindistance = (int)Math.Sqrt( (depth - minx) * (depth - minx) + (depth - miny) * (depth - miny)); //距離圓心距離小於等於depth則漸變(越遠離圓心越淡) if (mindistance <= depth) { coefficient = 1.0f * mindistance / depth; result.SetPixel(i, j, AdjustBrightness( bitmap.GetPixel(i, j), coefficient)); } //距離圓心距離大於depth則置白 else { result.SetPixel(i, j, Color.FromArgb( bitmap.GetPixel(i, j).A, 255, 255, 255)); } } //四條邊的狀況(越靠近邊越淡) else if (minx <= depth || miny <= depth) { mindistance = minx < miny ? minx : miny; coefficient = 1.0f - (1.0f * mindistance / depth); result.SetPixel(i, j, AdjustBrightness(bitmap.GetPixel(i, j), coefficient)); } //圖片中心部分的狀況(不處理) else { result.SetPixel(i, j, bitmap.GetPixel(i, j)); } //刷新進度條 pgbTemp.Value = 100 * i / bitmap.Width; } } //函數運行完畢,隱藏進度條 pgbTemp.Visible = false; return result; } /// <summary> /// 改變一個點的顏色:變亮或變暗 /// </summary> /// <param name="color">被改變顏色</param> /// <param name="coefficient">顏色調整係數:-1f時顏色最淺,1f時顏色最深</param> /// <returns>改變後顏色</returns> public static Color AdjustBrightness(Color color, float coefficient) { if (coefficient < -1f) coefficient = -1f; if (coefficient > 1f) coefficient = 1f; float red = (float)color.R; float green = (float)color.G; float blue = (float)color.B; if (coefficient < 0) { coefficient = 1 + coefficient; red *= coefficient; green *= coefficient; blue *= coefficient; } else { red = (255 - red) * coefficient + red; green = (255 - green) * coefficient + green; blue = (255 - blue) * coefficient + blue; } red = red > 0 ? red : 0; red = red < 255 ? red : 255; green = green > 0 ? green : 0; green = green < 255 ? green : 255; blue = blue > 0 ? blue : 0; blue = blue < 255 ? blue : 255; return Color.FromArgb(color.A, (int)red, (int)green, (int)blue); } #endregion } }
END