Reputation: 10888
As Size
, Width
and Height
are Get()
properties of System.Drawing.Image
;
How can I resize an Image object at run-time in C#?
Right now, I am just creating a new Image
using:
// objImage is the original Image
Bitmap objBitmap = new Bitmap(objImage, new Size(227, 171));
Upvotes: 369
Views: 743104
Reputation: 60642
Adding another answer for the sake of completeness
For modern .NET core apps, using System.Drawing
is not the best choice especially if you need cross-platform resizing without OS dependencies (libgdi in this case).
I've used ImageSharp
library in the past (it's 100% managed code so no OS dependencies). However it uses too much memory for our use case.
That is why we switched to PhotoSauce
. This library does depend on a native codec, but it is distributed nicely with the nuget-package and works cross-platform (tested on win64, linux64 various distros).
P.S. I'm not affiliated with any of the above just wanted to recommend an awesome product (PhotoSauce).
Upvotes: 0
Reputation: 455
Below function will return the new size to display the image.This may not be helpful here.But it will return resized Display Rectangle size.
public static class ResizeImage
{
/// <summary>
/// Return new resized size to display the image
/// </summary>
/// <param name="srcrectanle">source rectangle of image or you can pass the bitmap and set the size accrodingly</param>
/// <param name="initSize">initial size of the page to draw image</param>
/// <returns></returns>
public static SizeF getResizedRectangle(RectangleF srcrectanle, SizeF initSize)
{
float sw = srcrectanle.Width;
float sh = srcrectanle.Height;
float dw = initSize.Width;
float dh = initSize.Height;
float finalHeight, finalWidth;
float sourceRatio = sw / sh;
float destRatio = dw / dh;
if (sourceRatio >= destRatio)
{
finalWidth = (int)dw;
float ratio = sw / dw;
finalHeight = (sh / ratio);
}
else
{
finalHeight = (int)dh;
float ratio = sh / dh;
finalWidth = (sw / ratio);
}
return new SizeF(finalHeight, finalHeight);
}
}
Upvotes: 1
Reputation: 555
You could try my library net-vips, the C# binding for libvips. It's a lazy, streaming, demand-driven image processing library, so it can do operations like this without needing to load the whole image.
For example, it comes with a handy image thumbnailer:
using Image image = Image.Thumbnail("image.jpg", 300, 300);
image.WriteToFile("my-thumbnail.jpg");
It also supports smart crop, a way of intelligently determining the most important part of the image and keeping it in focus while cropping the image. For example:
using Image image = Image.Thumbnail("owl.jpg", 128, crop: Enums.Interesting.Attention);
image.WriteToFile("tn_owl.jpg");
Where owl.jpg
is an off-centre composition:
Gives this result:
First it shrinks the image to get the vertical axis to 128 pixels, then crops down to 128 pixels across using the attention
strategy. This one searches the image for features which might catch a human eye, see Smartcrop()
for details.
Upvotes: 36
Reputation: 1803
Not sure what is so difficult about this, do what you were doing, use the overloaded Bitmap constructor to create a re-sized image, the only thing you were missing was a cast back to the Image data type:
public static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
yourImage = resizeImage(yourImage, new Size(50,50));
Upvotes: 177
Reputation: 42
Use below function with below example for changing image size :
//Example :
System.Net.Mime.MediaTypeNames.Image newImage = System.Net.Mime.MediaTypeNames.Image.FromFile("SampImag.jpg");
System.Net.Mime.MediaTypeNames.Image temImag = FormatImage(newImage, 100, 100);
//image size modification unction
public static System.Net.Mime.MediaTypeNames.Image FormatImage(System.Net.Mime.MediaTypeNames.Image img, int outputWidth, int outputHeight)
{
Bitmap outputImage = null;
Graphics graphics = null;
try
{
outputImage = new Bitmap(outputWidth, outputHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
graphics = Graphics.FromImage(outputImage);
graphics.DrawImage(img, new Rectangle(0, 0, outputWidth, outputHeight),
new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
return outputImage;
}
catch (Exception ex)
{
return img;
}
}
Upvotes: 0
Reputation: 128
This code is same as posted from one of above answers.. but will convert transparent pixel to white instead of black ... Thanks:)
public Image resizeImage(int newWidth, int newHeight, string stPhotoPath)
{
Image imgPhoto = Image.FromFile(stPhotoPath);
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
//Consider vertical pics
if (sourceWidth < sourceHeight)
{
int buff = newWidth;
newWidth = newHeight;
newHeight = buff;
}
int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
float nPercent = 0, nPercentW = 0, nPercentH = 0;
nPercentW = ((float)newWidth / (float)sourceWidth);
nPercentH = ((float)newHeight / (float)sourceHeight);
if (nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = System.Convert.ToInt16((newWidth -
(sourceWidth * nPercent)) / 2);
}
else
{
nPercent = nPercentW;
destY = System.Convert.ToInt16((newHeight -
(sourceHeight * nPercent)) / 2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(newWidth, newHeight,
PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.White);
grPhoto.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
imgPhoto.Dispose();
return bmPhoto;
}
Upvotes: 9
Reputation: 2012
Resize and save an image to fit under width and height like a canvas keeping image proportional
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
namespace Infra.Files
{
public static class GenerateThumb
{
/// <summary>
/// Resize and save an image to fit under width and height like a canvas keeping things proportional
/// </summary>
/// <param name="originalImagePath"></param>
/// <param name="thumbImagePath"></param>
/// <param name="newWidth"></param>
/// <param name="newHeight"></param>
public static void GenerateThumbImage(string originalImagePath, string thumbImagePath, int newWidth, int newHeight)
{
Bitmap srcBmp = new Bitmap(originalImagePath);
float ratio = 1;
float minSize = Math.Min(newHeight, newHeight);
if (srcBmp.Width > srcBmp.Height)
{
ratio = minSize / (float)srcBmp.Width;
}
else
{
ratio = minSize / (float)srcBmp.Height;
}
SizeF newSize = new SizeF(srcBmp.Width * ratio, srcBmp.Height * ratio);
Bitmap target = new Bitmap((int)newSize.Width, (int)newSize.Height);
using (Graphics graphics = Graphics.FromImage(target))
{
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(srcBmp, 0, 0, newSize.Width, newSize.Height);
using (MemoryStream memoryStream = new MemoryStream())
{
target.Save(thumbImagePath);
}
}
}
}
}
Upvotes: 0
Reputation: 3626
Note: this will not work with ASP.Net Core because WebImage depends on System.Web, but on previous versions of ASP.Net I used this snippet many times and was useful.
String ThumbfullPath = Path.GetFileNameWithoutExtension(file.FileName) + "80x80.jpg";
var ThumbfullPath2 = Path.Combine(ThumbfullPath, fileThumb);
using (MemoryStream stream = new MemoryStream(System.IO.File.ReadAllBytes(fullPath)))
{
var thumbnail = new WebImage(stream).Resize(80, 80);
thumbnail.Save(ThumbfullPath2, "jpg");
}
Upvotes: 1
Reputation: 160
public static Image resizeImage(Image image, int new_height, int new_width)
{
Bitmap new_image = new Bitmap(new_width, new_height);
Graphics g = Graphics.FromImage((Image)new_image );
g.InterpolationMode = InterpolationMode.High;
g.DrawImage(image, 0, 0, new_width, new_height);
return new_image;
}
Upvotes: 12
Reputation: 282865
This will perform a high quality resize:
/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width,image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
wrapMode.SetWrapMode(WrapMode.TileFlipXY)
prevents ghosting around the image borders -- naïve resizing will sample transparent pixels beyond the image boundaries, but by mirroring the image we can get a better sample (this setting is very noticeable)destImage.SetResolution
maintains DPI regardless of physical size -- may increase quality when reducing image dimensions or when printinggraphics.CompositingMode
determines whether pixels from a source image overwrite or are combined with background pixels. SourceCopy
specifies that when a color is rendered, it overwrites the background color.graphics.CompositingQuality
determines the rendering quality level of layered images.graphics.InterpolationMode
determines how intermediate values between two endpoints are calculatedgraphics.SmoothingMode
specifies whether lines, curves, and the edges of filled areas use smoothing (also called antialiasing) -- probably only works on vectorsgraphics.PixelOffsetMode
affects rendering quality when drawing the new imageMaintaining aspect ratio is left as an exercise for the reader (actually, I just don't think it's this function's job to do that for you).
Also, this is a good article describing some of the pitfalls with image resizing. The above function will cover most of them, but you still have to worry about saving.
Upvotes: 633
Reputation: 4028
in this question, you'll have some answers, including mine:
public Image resizeImage(int newWidth, int newHeight, string stPhotoPath)
{
Image imgPhoto = Image.FromFile(stPhotoPath);
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
//Consider vertical pics
if (sourceWidth < sourceHeight)
{
int buff = newWidth;
newWidth = newHeight;
newHeight = buff;
}
int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
float nPercent = 0, nPercentW = 0, nPercentH = 0;
nPercentW = ((float)newWidth / (float)sourceWidth);
nPercentH = ((float)newHeight / (float)sourceHeight);
if (nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = System.Convert.ToInt16((newWidth -
(sourceWidth * nPercent)) / 2);
}
else
{
nPercent = nPercentW;
destY = System.Convert.ToInt16((newHeight -
(sourceHeight * nPercent)) / 2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(newWidth, newHeight,
PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.Black);
grPhoto.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
imgPhoto.Dispose();
return bmPhoto;
}
Upvotes: 52
Reputation: 27201
If you're working with a BitmapSource
:
var resizedBitmap = new TransformedBitmap(
bitmapSource,
new ScaleTransform(scaleX, scaleY));
If you want finer control over quality, run this first:
RenderOptions.SetBitmapScalingMode(
bitmapSource,
BitmapScalingMode.HighQuality);
(Default is BitmapScalingMode.Linear
which is equivalent to BitmapScalingMode.LowQuality
.)
Upvotes: 3
Reputation: 171
This is the code that I worked out for a specific requirement ie: the destination is always in landscape ratio. It should give you a good start.
public Image ResizeImage(Image source, RectangleF destinationBounds)
{
RectangleF sourceBounds = new RectangleF(0.0f,0.0f,(float)source.Width, (float)source.Height);
RectangleF scaleBounds = new RectangleF();
Image destinationImage = new Bitmap((int)destinationBounds.Width, (int)destinationBounds.Height);
Graphics graph = Graphics.FromImage(destinationImage);
graph.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// Fill with background color
graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), destinationBounds);
float resizeRatio, sourceRatio;
float scaleWidth, scaleHeight;
sourceRatio = (float)source.Width / (float)source.Height;
if (sourceRatio >= 1.0f)
{
//landscape
resizeRatio = destinationBounds.Width / sourceBounds.Width;
scaleWidth = destinationBounds.Width;
scaleHeight = sourceBounds.Height * resizeRatio;
float trimValue = destinationBounds.Height - scaleHeight;
graph.DrawImage(source, 0, (trimValue / 2), destinationBounds.Width, scaleHeight);
}
else
{
//portrait
resizeRatio = destinationBounds.Height/sourceBounds.Height;
scaleWidth = sourceBounds.Width * resizeRatio;
scaleHeight = destinationBounds.Height;
float trimValue = destinationBounds.Width - scaleWidth;
graph.DrawImage(source, (trimValue / 2), 0, scaleWidth, destinationBounds.Height);
}
return destinationImage;
}
Upvotes: 8
Reputation: 66355
This will -
//////////////
private void ResizeImage(Image img, double maxWidth, double maxHeight)
{
double resizeWidth = img.Source.Width;
double resizeHeight = img.Source.Height;
double aspect = resizeWidth / resizeHeight;
if (resizeWidth > maxWidth)
{
resizeWidth = maxWidth;
resizeHeight = resizeWidth / aspect;
}
if (resizeHeight > maxHeight)
{
aspect = resizeWidth / resizeHeight;
resizeHeight = maxHeight;
resizeWidth = resizeHeight * aspect;
}
img.Width = resizeWidth;
img.Height = resizeHeight;
}
Upvotes: 11
Reputation: 127
public string CreateThumbnail(int maxWidth, int maxHeight, string path)
{
var image = System.Drawing.Image.FromFile(path);
var ratioX = (double)maxWidth / image.Width;
var ratioY = (double)maxHeight / image.Height;
var ratio = Math.Min(ratioX, ratioY);
var newWidth = (int)(image.Width * ratio);
var newHeight = (int)(image.Height * ratio);
var newImage = new Bitmap(newWidth, newHeight);
Graphics thumbGraph = Graphics.FromImage(newImage);
thumbGraph.CompositingQuality = CompositingQuality.HighQuality;
thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
//thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
thumbGraph.DrawImage(image, 0, 0, newWidth, newHeight);
image.Dispose();
string fileRelativePath = "newsizeimages/" + maxWidth + Path.GetFileName(path);
newImage.Save(Server.MapPath(fileRelativePath), newImage.RawFormat);
return fileRelativePath;
}
Click here http://bhupendrasinghsaini.blogspot.in/2014/07/resize-image-in-c.html
Upvotes: 7
Reputation: 481
Why not use the System.Drawing.Image.GetThumbnailImage
method?
public Image GetThumbnailImage(
int thumbWidth,
int thumbHeight,
Image.GetThumbnailImageAbort callback,
IntPtr callbackData)
Example:
Image originalImage = System.Drawing.Image.FromStream(inputStream, true, true);
Image resizedImage = originalImage.GetThumbnailImage(newWidth, (newWidth * originalImage.Height) / originalWidth, null, IntPtr.Zero);
resizedImage.Save(imagePath, ImageFormat.Png);
Source: http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx
Upvotes: 30
Reputation: 1009
In the application I made it was necessary to create a function with multiple options. It's quite large, but it resizes the image, can keep the aspect ratio and can cut of the edges to return only the center of the image:
/// <summary>
/// Resize image with a directory as source
/// </summary>
/// <param name="OriginalFileLocation">Image location</param>
/// <param name="heigth">new height</param>
/// <param name="width">new width</param>
/// <param name="keepAspectRatio">keep the aspect ratio</param>
/// <param name="getCenter">return the center bit of the image</param>
/// <returns>image with new dimentions</returns>
public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width, Boolean keepAspectRatio, Boolean getCenter)
{
int newheigth = heigth;
System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFileLocation);
// Prevent using images internal thumbnail
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
if (keepAspectRatio || getCenter)
{
int bmpY = 0;
double resize = (double)FullsizeImage.Width / (double)width;//get the resize vector
if (getCenter)
{
bmpY = (int)((FullsizeImage.Height - (heigth * resize)) / 2);// gives the Y value of the part that will be cut off, to show only the part in the center
Rectangle section = new Rectangle(new Point(0, bmpY), new Size(FullsizeImage.Width, (int)(heigth * resize)));// create the section to cut of the original image
//System.Console.WriteLine("the section that will be cut off: " + section.Size.ToString() + " the Y value is minimized by: " + bmpY);
Bitmap orImg = new Bitmap((Bitmap)FullsizeImage);//for the correct effect convert image to bitmap.
FullsizeImage.Dispose();//clear the original image
using (Bitmap tempImg = new Bitmap(section.Width, section.Height))
{
Graphics cutImg = Graphics.FromImage(tempImg);// set the file to save the new image to.
cutImg.DrawImage(orImg, 0, 0, section, GraphicsUnit.Pixel);// cut the image and save it to tempImg
FullsizeImage = tempImg;//save the tempImg as FullsizeImage for resizing later
orImg.Dispose();
cutImg.Dispose();
return FullsizeImage.GetThumbnailImage(width, heigth, null, IntPtr.Zero);
}
}
else newheigth = (int)(FullsizeImage.Height / resize);// set the new heigth of the current image
}//return the image resized to the given heigth and width
return FullsizeImage.GetThumbnailImage(width, newheigth, null, IntPtr.Zero);
}
To make it easier to acces the function it's possible to add some overloaded functions:
/// <summary>
/// Resize image with a directory as source
/// </summary>
/// <param name="OriginalFileLocation">Image location</param>
/// <param name="heigth">new height</param>
/// <param name="width">new width</param>
/// <returns>image with new dimentions</returns>
public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width)
{
return resizeImageFromFile(OriginalFileLocation, heigth, width, false, false);
}
/// <summary>
/// Resize image with a directory as source
/// </summary>
/// <param name="OriginalFileLocation">Image location</param>
/// <param name="heigth">new height</param>
/// <param name="width">new width</param>
/// <param name="keepAspectRatio">keep the aspect ratio</param>
/// <returns>image with new dimentions</returns>
public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width, Boolean keepAspectRatio)
{
return resizeImageFromFile(OriginalFileLocation, heigth, width, keepAspectRatio, false);
}
Now are the last two booleans optional to set. Call the function like this:
System.Drawing.Image ResizedImage = resizeImageFromFile(imageLocation, 800, 400, true, true);
Upvotes: 7