1. 程式人生 > >C#把影象處理為正方形影象

C#把影象處理為正方形影象

摘要
在C#的winform平臺上利用基於GDI底層圖形引擎(WPF是DirectX圖形引擎,效率更高,該程式碼再WPF上不適用)的操作進行影象的大小處理,轉化為自定義畫素的正方形影象。

一 基本介面及程式碼

1.圖形介面

正方形影象轉換

2.介面程式碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.
Threading.Tasks; using System.Windows.Forms; namespace ToSquareImage2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Image ima_; int pixelSize; private void btnOpen_Click(object sender, EventArgs e)
{ OpenFileDialog fd = new OpenFileDialog(); fd.Filter = "請選擇圖片|*.GIF;*.BMP;*.JPG;*.PNG"; if (fd.ShowDialog() == DialogResult.OK) { string path = fd.FileName; Image ima = Image.FromFile(path); ima_ =
ima; pictureBox1.Image = ima; } } private void btnSave_Click(object sender, EventArgs e) { bool canBeParsed = int.TryParse(textBox1.Text, out pixelSize); if (canBeParsed) { pixelSize = int.Parse(textBox1.Text); SaveFileDialog sf = new SaveFileDialog(); sf.Filter = ".jpg|*.JPG"; if (sf.ShowDialog() == DialogResult.OK) { string path = sf.FileName; Transform.Class3.MakeSquareImage(ima_, path, pixelSize); if (path != "") { MessageBox.Show("儲存成功"); } else { MessageBox.Show("儲存失敗"); } } } else { MessageBox.Show("邊長設定有誤!"); } } } }

3.函式程式碼

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace Transform
{
    /// <summary>
    /// 製作小正方形
    /// </summary>
    class Class3
    {
        /// <summary>
        /// 儲存圖片
        /// </summary>
        /// <param name="image">Image 物件</param>
        /// <param name="savePath">儲存路徑</param>
        /// <param name="ici">指定格式的編解碼引數</param>
        private static void SaveImage(Image image, string savePath, ImageCodecInfo ici)
        {
            //設定 原圖片 物件的 EncoderParameters 物件
            EncoderParameters parameters = new EncoderParameters(1);
            parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, ((long)100));
            image.Save(savePath, ici, parameters);
            parameters.Dispose();
        }

        /// <summary>
        /// 獲取影象編碼解碼器的所有相關資訊
        /// </summary>
        /// <param name="mimeType">包含編碼解碼器的多用途網際郵件擴充協議 (MIME) 型別的字串</param>
        /// <returns>返回影象編碼解碼器的所有相關資訊</returns>
        private static ImageCodecInfo GetCodecInfo(string mimeType)
        {
            ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders();
            foreach (ImageCodecInfo ici in CodecInfo)
            {
                if (ici.MimeType == mimeType)
                    return ici;
            }
            return null;
        }

        /// <summary>
        /// 計算新尺寸
        /// </summary>
        /// <param name="width">原始寬度</param>
        /// <param name="height">原始高度</param>
        /// <param name="maxWidth">最大新寬度</param>
        /// <param name="maxHeight">最大新高度</param>
        /// <returns></returns>
        private static Size ResizeImage(int width, int height, int maxWidth, int maxHeight)
        {
            if (maxWidth <= 0)
                maxWidth = width;
            if (maxHeight <= 0)
                maxHeight = height;
            decimal MAX_WIDTH = (decimal)maxWidth;
            decimal MAX_HEIGHT = (decimal)maxHeight;
            decimal ASPECT_RATIO = MAX_WIDTH / MAX_HEIGHT;

            int newWidth, newHeight;
            decimal originalWidth = (decimal)width;
            decimal originalHeight = (decimal)height;

            if (originalWidth > MAX_WIDTH || originalHeight > MAX_HEIGHT)
            {
                decimal factor;
                // determine the largest factor 
                if (originalWidth / originalHeight > ASPECT_RATIO)
                {
                    factor = originalWidth / MAX_WIDTH;
                    newWidth = Convert.ToInt32(originalWidth / factor);
                    newHeight = Convert.ToInt32(originalHeight / factor);
                }
                else
                {
                    factor = originalHeight / MAX_HEIGHT;
                    newWidth = Convert.ToInt32(originalWidth / factor);
                    newHeight = Convert.ToInt32(originalHeight / factor);
                }
            }
            else
            {
                newWidth = width;
                newHeight = height;
            }
            return new Size(newWidth, newHeight);
        }

        /// <summary>
        /// 得到圖片格式
        /// </summary>
        /// <param name="name">檔名稱</param>
        /// <returns></returns>
        public static ImageFormat GetFormat(string name)
        {
            string ext = name.Substring(name.LastIndexOf(".") + 1);
            switch (ext.ToLower())
            {
                case "jpg":
                case "jpeg":
                    return ImageFormat.Jpeg;
                case "bmp":
                    return ImageFormat.Bmp;
                case "png":
                    return ImageFormat.Png;
                case "gif":
                    return ImageFormat.Gif;
                default:
                    return ImageFormat.Jpeg;
            }
        }


        /// <summary>
        /// 製作小正方形
        /// </summary>
        /// <param name="image">圖片物件</param>
        /// <param name="newFileName">新地址</param>
        /// <param name="newSize">長度或寬度</param>
        public static void MakeSquareImage(Image image, string newFileName, int newSize)
        {
            //獲取最短邊
            int i = 0;
            int width = image.Width;
            int height = image.Height;
            if (width > height)
                i = height;
            else
                i = width;

            //構造點陣圖
            Bitmap b = new Bitmap(newSize, newSize);

            try
            {
                Graphics g = Graphics.FromImage(b);
                //設定高質量插值法
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                //設定高質量,低速度呈現平滑程度
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                //清除整個繪圖面並以透明背景色填充
                g.Clear(Color.Transparent);
                if (width < height)
                    g.DrawImage(image, new Rectangle(0, 0, newSize, newSize), new Rectangle(0, (height - width) / 2, width, width), GraphicsUnit.Pixel);
                else
                    g.DrawImage(image, new Rectangle(0, 0, newSize, newSize), new Rectangle((width - height) / 2, 0, height, height), GraphicsUnit.Pixel);

                SaveImage(b, newFileName, GetCodecInfo("image/" + GetFormat(newFileName).ToString().ToLower()));
            }
            finally
            {
                image.Dispose();
                b.Dispose();
            }
        }

        /// <summary>
        /// 製作小正方形
        /// </summary>
        /// <param name="fileName">圖片檔名</param>
        /// <param name="newFileName">新地址</param>
        /// <param name="newSize">長度或寬度</param>
        public static void MakeSquareImage(string fileName, string newFileName, int newSize)
        {
            MakeSquareImage(Image.FromFile(fileName), newFileName, newSize);
        }
    }
}

二 思路及程式碼解釋

1.檔案操作部分

檔案讀取

            OpenFileDialog fd = new OpenFileDialog();
            fd.Filter = "請選擇圖片|*.GIF;*.BMP;*.JPG;*.PNG";
            if (fd.ShowDialog() == DialogResult.OK)
            {
                string path = fd.FileName;
                Image ima = Image.FromFile(path);
                ima_ = ima;
                pictureBox1.Image = ima;
            }

這裡是使用了OpenFileDialog這個開啟檔案對話方塊類
這個類的常用屬性

常用屬性 屬性說明
Filter 確定對話方塊中顯示的檔案型別
InitialDirectory 對話方塊顯示的初始目錄
FileName 選定檔案的完整路徑
SafeFileName 僅包含檔案的檔名(包含字尾)

檔案儲存

            bool canBeParsed = int.TryParse(textBox1.Text, out pixelSize);
            if (canBeParsed)
            {
                pixelSize = int.Parse(textBox1.Text);
                SaveFileDialog sf = new SaveFileDialog();
                sf.Filter = ".jpg|*.JPG";
                if (sf.ShowDialog() == DialogResult.OK)
                {
                    string path = sf.FileName;
                    Transform.Class3.MakeSquareImage(ima_, path, pixelSize);
                    if (path != "")
                    {
                        MessageBox.Show("儲存成功");
                    }
                    else
                    {
                        MessageBox.Show("儲存失敗");
                    }
                }
            }
            else
            {
                MessageBox.Show("邊長設定有誤!");
            }

上面僅為介面元素的檔案儲存對話方塊程式碼,目的僅僅是為了獲得儲存檔案的路徑,然後傳入處理方法內,再進行真正的檔案儲存,真正的儲存檔案程式碼如下:

        /// <summary>
        /// 儲存圖片
        /// </summary>
        /// <param name="image">Image 物件</param>
        /// <param name="savePath">儲存路徑</param>
        /// <param name="ici">指定格式的編解碼引數</param>
        private static void SaveImage(Image image, string savePath, ImageCodecInfo ici)
        {
            //設定 原圖片 物件的 EncoderParameters 物件
            EncoderParameters parameters = new EncoderParameters(1);
            parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, ((long)100));
            image.Save(savePath, ici, parameters);
            parameters.Dispose();
        }

圖片Image類中有一個save的方法可以用來儲存圖片

2.函式程式碼部分

函式名 說明
MakeSquareImage 通過對最短邊的獲取,然後建立自定義大小的點陣圖,最後再利用Graphics類裡面的DrawImage方法進行繪製(該方法不適用與WPF),繪製完成直接儲存
GetFormat 在儲存圖片的時候需要獲取格式,用SubString方法以及LastIndexOf方法可以快速獲取,最後結合switch進行匹配,返回相應的格式
ResizeImage 暫時用不到
GetCodecInfo 獲取影象編碼器解碼的相關資訊,儲存影象需要用到
SaveImage 儲存影象

GitHub程式碼
https://github.com/Mushano/C-ImageTransformToSquare