Chào các bạn, hôm nay mình sẽ giới thiệu đến các bạn một thủ thuật trong lập trình web với ASP.NET MVC. Chắc hẳn các bạn làm web đã từng trải qua những tình huống khi cần upload một hình ảnh làm ảnh đại diện sẽ phải crop hình cho vừa và giảm dung lượng cho website. Vậy làm thế nào để làm được điều đó ? Đơn giản với các bước bên dưới.

Tham khảo thêm bài viết Hướng dẫn upload và resize hình ảnh trong ASP.NET MVC

Hàm Crop Image trong ASP.NET C#

public bool SaveCroppedImage(Image image, int maxWidth, int maxHeight, string filePath)
        {
            ImageCodecInfo jpgInfo = ImageCodecInfo.GetImageEncoders()
                                     .Where(codecInfo =>
                                     codecInfo.MimeType == "image/jpeg").First();
            Image finalImage = image;
            System.Drawing.Bitmap bitmap = null;
            try
            {
                int left = 0;
                int top = 0;
                int srcWidth = maxWidth;
                int srcHeight = maxHeight;
                bitmap = new System.Drawing.Bitmap(maxWidth, maxHeight);
                double croppedHeightToWidth = (double)maxHeight / maxWidth;
                double croppedWidthToHeight = (double)maxWidth / maxHeight;

                if (image.Width > image.Height)
                {
                    srcWidth = (int)(Math.Round(image.Height * croppedWidthToHeight));
                    if (srcWidth < image.Width)
                    {
                        srcHeight = image.Height;
                        left = (image.Width - srcWidth) / 2;
                    }
                    else
                    {
                        srcHeight = (int)Math.Round(image.Height * ((double)image.Width / srcWidth));
                        srcWidth = image.Width;
                        top = (image.Height - srcHeight) / 2;
                    }
                }
                else
                {
                    srcHeight = (int)(Math.Round(image.Width * croppedHeightToWidth));
                    if (srcHeight < image.Height)
                    {
                        srcWidth = image.Width;
                        top = (image.Height - srcHeight) / 2;
                    }
                    else
                    {
                        srcWidth = (int)Math.Round(image.Width * ((double)image.Height / srcHeight));
                        srcHeight = image.Height;
                        left = (image.Width - srcWidth) / 2;
                    }
                }
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    g.CompositingQuality = CompositingQuality.HighQuality;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                    new Rectangle(left, top, srcWidth, srcHeight), GraphicsUnit.Pixel);
                }
                finalImage = bitmap;
            }
            catch { }
            try
            {
                using (EncoderParameters encParams = new EncoderParameters(1))
                {
                    encParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100);
                    //quality should be in the range 
                    //[0..100] .. 100 for max, 0 for min (0 best compression)
                    finalImage.Save(filePath, jpgInfo, encParams);
                    return true;
                }
            }
            catch { }
            if (bitmap != null)
            {
                bitmap.Dispose();
            }
            return false;
        }  
    }

Và sau đó hàm Crop Image này sẽ được gọi ở Controller

Gọi hàm Crop Image C# ở Controller MVC

[HttpPost]
public ActionResult Upload(HttpPostedFileBase imageFile)
{
   SaveCroppedImage(Image.FromStream(imageFile.InputStream), 
   100, 100, @"C:\Temp\image.jpg");
   return View();
}

Code mẫu sử dụng hàm Crop hình ảnh trong ASP.NET MVC

Cấu trúc code mẫu như hình sau (Các bạn chú ý đến các file minh viền đỏ):

crop-hinh-mvc

Đầu tiên tạo file HomeController.cs với code như sau:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CropImage.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            ViewBag.Error = TempData["e"] == null ? "" : TempData["e"].ToString();
            ViewBag.Files = TempData["file"] == null ? new List<string>() : (List<string>)TempData["file"];
            return View();
        }

    }
}

Tiếp theo tạo View Index.cshtml cho controller home hiển thị form upload:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Demo upload và Crop hình ảnh</title>
</head>
<body>
    <h1>Upload và Resize hình ảnh</h1>
    @if (!string.IsNullOrEmpty(ViewBag.Error)) { 
        <div>
            @Html.Raw(ViewBag.Error)
        </div>
    }
    @if (ViewBag.Files!=null) { 
        <ul>
            @foreach (var file in ViewBag.Files) { 
                <li>@Html.Raw(file)</li>
            }
        </ul>
    }
    <div>
        @using (Html.BeginForm("Upload", "File", FormMethod.Post, new { enctype = "multipart/form-data" }))
        { 
            <p>Chọn file upload: <input type="file" name="file"/></p>
            <h4>Kích thước crop</h4>
            <p>Width: @Html.TextBox("width", "", new  { @type="number", min="10"})</p>
            <p>Height: @Html.TextBox("height", "", new  { @type="number", min="10"})</p>
            <p><button type="submit">Upload và Crop hình</button></p>
        }
    </div>
</body>
</html>

Sau khi tạo xong các bạn chạy project sẽ được form upload như sau:

crop-hinh-mvc

Việc tiếp theo các bạn tạo controller FileController.cs để xử lý file upload và crop file khi người dùng submit.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CropImage.Controllers
{
    public class FileController : Controller
    {
        [HttpPost]
        public ActionResult Upload(FormCollection fc)
        {

            string w = fc["width"];
            string h = fc["height"];
            int width = 200;
            int height = 200;
            if (!string.IsNullOrEmpty(w))
            {
                int.TryParse(w, out width);
            }
            if (!string.IsNullOrEmpty(h))
            {
                int.TryParse(h, out height);
            }

            List<string> fileNames = new List<string>();
            try
            {
                // Duyệt qua các file được gởi lên phía client
                foreach (string fileName in Request.Files)
                {
                    //Lấy ra file trong list các file gởi lên
                    HttpPostedFileBase file = Request.Files[fileName];
                    //Save file content goes here

                    if (file != null && file.ContentLength > 0)
                    {
                        //Định nghĩa đường dẫn lưu file trên server
                        //ở đây mình lưu tại đường dẫn yourdomain.com/Uploads/
                        var originalDirectory = new DirectoryInfo(string.Format("{0}Uploads\\", Server.MapPath(@"\")));
                        //Lưu trữ hình ảnh theo từng tháng trong năm
                        string pathString = System.IO.Path.Combine(originalDirectory.ToString(), DateTime.Now.ToString("yyyy-MM"));
                        bool isExists = System.IO.Directory.Exists(pathString);
                        if (!isExists) System.IO.Directory.CreateDirectory(pathString);
                        var path = string.Format("{0}\\{1}", pathString, file.FileName);
                        string newFileName = file.FileName;
                        //lấy đường dẫn lưu file sau khi kiểm tra tên file trên server có tồn tại hay không
                        var newPath = GetNewPathForDupes(path, ref newFileName);
                        string serverPath = string.Format("/{0}/{1}/{2}", "Uploads", DateTime.Now.ToString("yyyy-MM"), newFileName);
                        //Lưu hình ảnh Resize từ file sử dụng file.InputStream
                        SaveCroppedImage(Image.FromStream(file.InputStream), width, height, newPath);
                        fileNames.Add("LocalPath: " + newPath + "<br/>ServerPath: " + serverPath);
                    }
                }
            }
            catch (Exception ex)
            {
                TempData["e"] = ex.Message;
            }
            TempData["file"] = fileNames;
            return RedirectToAction("Index", "Home");

        }

        //Hàm crop hình ảnh
        public bool SaveCroppedImage(Image image, int maxWidth, int maxHeight, string filePath)
        {
            ImageCodecInfo jpgInfo = ImageCodecInfo.GetImageEncoders()
                                     .Where(codecInfo =>
                                     codecInfo.MimeType == "image/jpeg").First();
            Image finalImage = image;
            System.Drawing.Bitmap bitmap = null;
            try
            {
                int left = 0;
                int top = 0;
                int srcWidth = maxWidth;
                int srcHeight = maxHeight;
                bitmap = new System.Drawing.Bitmap(maxWidth, maxHeight);
                double croppedHeightToWidth = (double)maxHeight / maxWidth;
                double croppedWidthToHeight = (double)maxWidth / maxHeight;

                if (image.Width > image.Height)
                {
                    srcWidth = (int)(Math.Round(image.Height * croppedWidthToHeight));
                    if (srcWidth < image.Width)
                    {
                        srcHeight = image.Height;
                        left = (image.Width - srcWidth) / 2;
                    }
                    else
                    {
                        srcHeight = (int)Math.Round(image.Height * ((double)image.Width / srcWidth));
                        srcWidth = image.Width;
                        top = (image.Height - srcHeight) / 2;
                    }
                }
                else
                {
                    srcHeight = (int)(Math.Round(image.Width * croppedHeightToWidth));
                    if (srcHeight < image.Height)
                    {
                        srcWidth = image.Width;
                        top = (image.Height - srcHeight) / 2;
                    }
                    else
                    {
                        srcWidth = (int)Math.Round(image.Width * ((double)image.Height / srcHeight));
                        srcHeight = image.Height;
                        left = (image.Width - srcWidth) / 2;
                    }
                }
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    g.CompositingQuality = CompositingQuality.HighQuality;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                    new Rectangle(left, top, srcWidth, srcHeight), GraphicsUnit.Pixel);
                }
                finalImage = bitmap;
            }
            catch { }
            try
            {
                using (EncoderParameters encParams = new EncoderParameters(1))
                {
                    encParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100);
                    //quality should be in the range 
                    //[0..100] .. 100 for max, 0 for min (0 best compression)
                    finalImage.Save(filePath, jpgInfo, encParams);
                    return true;
                }
            }
            catch { }
            if (bitmap != null)
            {
                bitmap.Dispose();
            }
            return false;
        }

        private string GetNewPathForDupes(string path, ref string fn)
        {
            string directory = Path.GetDirectoryName(path);
            string filename = Path.GetFileNameWithoutExtension(path);
            string extension = Path.GetExtension(path);
            int counter = 1;
            string newFullPath = path;
            string new_file_name = filename + extension;
            while (System.IO.File.Exists(newFullPath))
            {
                string newFilename = string.Format("{0}({1}){2}", filename, counter, extension);
                new_file_name = newFilename;
                newFullPath = Path.Combine(directory, newFilename);
                counter++;
            };
            fn = new_file_name;
            return newFullPath;
        }

    }
}

Sau khi tạo xong controler FileController.cs các bạn có thể chạy project để xem kết quả. Bên dưới là kết quả khi mình thưc hiện crop hình theo kích thước 200×200 px.

Các bạn có thể download full code mẫu ở cuối bài viết để tham khảo.

Kết quả khi sử dụng Hàm Crop Image bên trên

Hình gốc khi upload không crop image

Crop hình sử dụng ASP.NET MVC

Hình ảnh sau khi crop với kích thước 200×200 px

bloghay.org (20)

Ngoài ra bạn có thể áp dụng cho bất kỳ website nào sử dụng ASP.NET không nhất thiết phải MVC (Chỉ khác nhau hàm xử lý upload). Chúc các bạn thành công, mọi thắc mắc xin vui lòng để lại lời nhắn tại khung comment.

FILE DOWNLOAD:

CropImage.zip

» Tham khảo: Dịch vụ Camera an ninh tại Đà Nẵng được lựa chọn lắp đặt nhiều nhất