Spuria - 一個用C#寫的讓圖片邊緣顏色變淺的工具

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

相關文章
相關標籤/搜索