What is the fastest and more reliable way of generating thumbnails in .NET? I need to get any image, compress it in JPEG and resize it.
I’ve seen several examples with GDI+, some non-free components and I remember WPF has some good stuff about imaging. GDI+ is pretty old and the WPF stuff maybe has no benefits on a server environment though.
This has to work in a ASP.NET MVC application that runs on full trust, and if possible, synchronously.
What would you recommend?
UPDATE:
Based on Mantorok’s answer I have worked out this example, but it’s still GDI+, and it crashes if I try with a large image:
public void GenerateThumbnail(String filename, Int32? desiredWidth,
Int32? desiredHeight, Int64 quality, Stream s)
{
using (Image image = Image.FromFile(filename))
{
Int32 width=0, height=0;
if ((!desiredHeight.HasValue && !desiredWidth.HasValue) ||
(desiredHeight.HasValue && desiredWidth.HasValue))
throw new ArgumentException(
"You have to specify a desired width OR a desired height");
if (desiredHeight.HasValue)
{
width = (desiredHeight.Value * image.Width) / image.Height;
height = desiredHeight.Value;
}
else
{
height = (desiredWidth.Value * image.Height) / image.Width;
width = desiredWidth.Value;
}
using (var newImage = new Bitmap(width, height))
using (var graphics = Graphics.FromImage(newImage))
using (EncoderParameter qualityParam =
new EncoderParameter(System.Drawing.Imaging.Encoder.Quality,
quality))
using (EncoderParameters encoderParams = new EncoderParameters(1))
{
graphics.DrawImage(image, 0, 0, width, height);
ImageCodecInfo jpegCodec = ImageCodecInfo.GetImageEncoders().
Single(e => e.MimeType.Equals("image/jpeg",
StringComparison.Ordinal));
encoderParams.Param[0] = qualityParam;
newImage.Save(s, jpegCodec, encoderParams);
}
}
}
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This has done me fine for years:
public static void CreateThumbnail(string filename, int desiredWidth, int desiredHeight, string outFilename)
{
using (System.Drawing.Image img = System.Drawing.Image.FromFile(filename))
{
float widthRatio = (float)img.Width / (float)desiredWidth;
float heightRatio = (float)img.Height / (float)desiredHeight;
// Resize to the greatest ratio
float ratio = heightRatio > widthRatio ? heightRatio : widthRatio;
int newWidth = Convert.ToInt32(Math.Floor((float)img.Width / ratio));
int newHeight = Convert.ToInt32(Math.Floor((float)img.Height / ratio));
using (System.Drawing.Image thumb = img.GetThumbnailImage(newWidth, newHeight, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailImageAbortCallback), IntPtr.Zero))
{
thumb.Save(outFilename, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
public static bool ThumbnailImageAbortCallback()
{
return true;
}
Method 2
For intensive server-side code, I suggest you use other techniques than GDI+ that has not been designed to handle images chunk by chunk (in a streaming manner).
You can use Windows Imaging Component or WPF for this task. There is a very good example on how to do this in a fast and – more important – scalable manner here:
The fastest way to resize images from ASP.NET. And it’s (more) supported-ish.
Method 3
I use ImageMagick for photo processing
UPDATED
Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using ImageMagickObject;
namespace photostorage.Models
{
public class PhotoProcessing
{
public MagickImage ResizeImg(string filepath, string filename)
{
Object[] rotate = new Object[] { filepath + "/" + filename,
"-auto-orient", filepath + "/" + filename };
Object[] big = new Object[] { filepath + "/" + filename,
"-resize", "800", filepath + "/" + "big_" + filename };
Object[] middle = new Object[] { filepath + "/big_" + filename,
"-resize", "400", filepath + "/" + "mid_" + filename };
Object[] small = new Object[] { filepath + "/mid_" + filename,
"-resize", "200", filepath + "/" + "small_" + filename };
Object[] crop = new Object[] { filepath + "/small_" + filename,
"-resize", "50", filepath + "/" + "crop_" + filename };
ImageMagickObject.MagickImage img =
new ImageMagickObject.MagickImage();
img.Convert(rotate);
img.Convert(big);
img.Convert(middle);
img.Convert(small);
img.Convert(crop);
return img;
}
}
}
Controller:
PhotoProcessing resizeImg = new PhotoProcessing();
[HttpPost]
public string Index(params,params,params...)
{
var GetResize = resizeImg.ResizeImg(
destinationFolder + "/" + curFolder, fullFileName);
}
Method 4
See my answer here Create thumbnail image
There is a function on Image which returns a thumbnail like this:
Image image = Image.FromFile(fileName); Image thumb = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero); thumb.Save(Path.ChangeExtension(fileName, "thumb"));
Method 5
I can’t say whether this is the most efficient manner, but here is a snippet of code I wrote to produce 3 smaller images from a large image:
private void GenerateImages(byte[] data, string extension, string filename)
{
// Assuming data is the original filename.
var ms = new MemoryStream(data);
var image = Image.FromStream(ms);
image.Save(filename);
ResizeImage(image, 800, 600, "large.jpg");
ResizeImage(image, 480, 320, "medium.jpg");
ResizeImage(image, 192, 144, "small.jpg");
}
private void ResizeImage(Image image, int width, int height, string filename)
{
using (var newImage = new Bitmap(width, height))
{
var graphics = Graphics.FromImage(newImage);
graphics.DrawImage(image, 0, 0, width, height);
newImage.Save(filename, ImageFormat.Jpeg);
}
}
Method 6
http://www.codeproject.com/KB/graphics/image_croppingVBNet.aspx
this is for center croping image i hope i will help you more..
http://www.codeproject.com/KB/GDI-plus/imageresize.aspx
Method 7
I am using Aurigma Image Uploader tool. it’s pretty nice control. but it is paid you can check aurigma
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0