In my previous article, I have explained Compressing (reducing size) of PNG image using C# in .NET MVC and now in this article, I am going to explain about how to reduce jpg or jpeg file size or to convert other image formats like png into jpg and reduce file size using C# .NET MVC without losing image quality.
Step 1: Create a project in your Visual Studio(2017 in my example), by opening Visual Studio and clicking "File"-> "New"-> "Project", Select MVC template to generate basic home controller and other details.
Step 2: Create a ImageResult class in POCO folder(Create three folders which we will be using POCO, Images->items, and Lib in your project ) which helps us render image uploads error if there is any in the view again
public class ImageResult
{
public bool Success { get; set; }
public string ImageName { get; set; }
public string ErrorMessage { get; set; }
}
Step 3: In your HomeController
use the code below to render Index view and upload File by posting form
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(FormCollection formCollection)
{
foreach (string item in Request.Files)
{
HttpPostedFileBase file = Request.Files[item] as HttpPostedFileBase;
if (file.ContentLength == 0)
continue;
if (file.ContentLength > 0)
{
// width + height will force size, care for distortion
//Exmaple: ImageUpload imageUpload = new ImageUpload { Width = 800, Height = 700 };
// height will increase the width proportially
//Example: ImageUpload imageUpload = new ImageUpload { Height= 600 };
// width will increase the height proportially
ImageUpload imageUpload = new ImageUpload { Width= 600 };
// rename, resize, and upload
//return object that contains {bool Success,string ErrorMessage,string ImageName}
ImageResult imageResult = imageUpload.RenameUploadFile(file);
if (imageResult.Success)
{
//TODO: write the filename to the db
Console.WriteLine(imageResult.ImageName);
}
else
{
//TODO: show view error
// use imageResult.ErrorMessage to show the error
ViewBag.Error = imageResult.ErrorMessage;
}
}
}
return View();
}
}
Step 4: In your Index view, write the code below to upload/send image to IndexAction
(Post method), image file which we need to compress
<div class="row">
<div class="col-md-12">
<h2>Upload Image</h2>
@if (ViewBag.Error != null)
{
<h4 style="color:red">@ViewBag.Error</h4>
}
@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>Upload Image</div>
<input type="file" name="avatar" />
<input type="submit" value="upload" />
}
</div>
</div>
Step 5: Now this is the important step, where we will reduce file size, what basically we will be doing is to first validate image, if it is valid format or not, then save Uncompressed file and then again reduce file size using C# code below, here we will get input Codec first and then reduce file size using C# bitmap & ImageCodecInfo inbuilt class
private void GenerateThumbnails(double scaleFactor, string sourcePath, string targetPath)
{
// Get a bitmap.
Bitmap bmp1 = new Bitmap(sourcePath);
//Or you do can use buil-in method
//ImageCodecInfo jgpEncoder GetEncoderInfo("image/gif");//"image/jpeg",...
ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
// Create an Encoder object based on the GUID
// for the Quality parameter category.
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;
// Create an EncoderParameters object.
// An EncoderParameters object has an array of EncoderParameter
// objects. In this case, there is only one
// EncoderParameter object in the array.
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(targetPath, jgpEncoder, myEncoderParameters);
}
private ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
So your complete ImageUpload.cs
will be as below
using nQuant;
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 UploadImage.POCO;
namespace UploadImage.Lib
{
public class ImageUpload
{
// set default size here
public int Width { get; set; }
public int Height { get; set; }
// folder for the upload, you can put this in the web.config
private readonly string UploadPath = "~/Images/Items/";
public ImageResult RenameUploadFile(HttpPostedFileBase file, Int32 counter = 0)
{
var fileName = Path.GetFileName(file.FileName);
string prepend = "item_";
string finalFileName = prepend + ((counter).ToString()) + "_" + fileName;
if (System.IO.File.Exists
(HttpContext.Current.Request.MapPath(UploadPath + finalFileName)))
{
//file exists => add country try again
return RenameUploadFile(file, ++counter);
}
//file doesn't exist, upload item but validate first
return UploadFile(file, finalFileName);
}
private ImageResult UploadFile(HttpPostedFileBase file, string fileName)
{
ImageResult imageResult = new ImageResult { Success = true, ErrorMessage = null };
var path =
Path.Combine(HttpContext.Current.Request.MapPath(UploadPath), fileName);
string extension = Path.GetExtension(file.FileName);
//make sure the file is valid
if (!ValidateExtension(extension))
{
imageResult.Success = false;
imageResult.ErrorMessage = "Invalid Extension";
return imageResult;
}
try
{
file.SaveAs(path);
Stream strm = file.InputStream;
var targetFile = Path.Combine(HttpContext.Current.Request.MapPath(UploadPath), "reduced_"+fileName);
GenerateThumbnails(0.5, path, targetFile);
return imageResult;
}
catch (Exception ex)
{
// you might NOT want to show the exception error for the user
// this is generaly logging or testing
imageResult.Success = false;
imageResult.ErrorMessage = ex.Message;
return imageResult;
}
}
private bool ValidateExtension(string extension)
{
extension = extension.ToLower();
switch (extension)
{
case ".jpg":
return true;
case ".png":
return true;
case ".gif":
return true;
case ".jpeg":
return true;
default:
return false;
}
}
private void GenerateThumbnails(double scaleFactor, string sourcePath, string targetPath)
{
// Get a bitmap.
Bitmap bmp1 = new Bitmap(sourcePath);
//Or you do can use buil-in method
//ImageCodecInfo jgpEncoder GetEncoderInfo("image/gif");//"image/jpeg",...
ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
// Create an Encoder object based on the GUID
// for the Quality parameter category.
System.Drawing.Imaging.Encoder myEncoder =
System.Drawing.Imaging.Encoder.Quality;
// Create an EncoderParameters object.
// An EncoderParameters object has an array of EncoderParameter
// objects. In this case, there is only one
// EncoderParameter object in the array.
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(targetPath, jgpEncoder, myEncoderParameters);
}
private ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
}
}
Step 6: Build your project and run it in your browser, you will get output as below
Upload any jpg file and check your project folder (Images->Items , create this folder heirarchy if you haven't created and then upload or change URL in ImageUpload.cs), you will be compressed and uncompressed image files.
That's it, we are done, feel free to share this article and comment on it or post a question related to it, by linking it, thanks