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));
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 printing
Compositing controls how pixels are blended with the background -- might not be needed since we're only drawing one thing.
graphics.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 calculated
graphics.SmoothingMode specifies whether lines, curves, and the edges of filled areas use smoothing (also called antialiasing) -- probably only works on vectors
graphics.PixelOffsetMode affects rendering quality when drawing the new image
Maintaining 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.
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));
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;
}
You could try 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.
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
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;
}
This will -
Resize width AND height without the need for a loop
Doesn't exceed the images original dimensions
//////////////
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;
}
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;
}
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;
}
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);
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
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.)
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");
}
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;
}
}
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);
}
}
}
}
}
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;
if (Sourceratio >= 1)
{
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);
}
}
I'm taking a screenshot of my form and then sending it to the printer. The image is too large, it goes off the sides of the page. I've been looking around for the past few hours to no avail. Can someone assist?
When I open the file itself it looks good in a print preview. If I then print from the preview its fine. But I wanted to do this with no user intervention.
public void SetupPrintHandler()
{
PrintDocument printDoc = new PrintDocument();
printDoc.PrintPage += new PrintPageEventHandler(OnPrintPage);
printDoc.DefaultPageSettings.Landscape = true;
printDoc.Print();
}
private void OnPrintPage(object sender, PrintPageEventArgs args)
{
using (Image image = Image.FromFile(#"C:/temp2.bmp"))
{
Graphics g = args.Graphics;
g.DrawImage(image, 0, 0);
}
}
private void printscreen()
{
ScreenCapture sc = new ScreenCapture();
Image img = sc.CaptureScreen();
sc.CaptureWindowToFile(this.Handle, "C:/temp2.bmp", ImageFormat.Bmp);
SetupPrintHandler();
}
So what I did just now as instead of the screen shot, for testing, I save what was in panel3 which is 2 pictureboxes. So i'm taking the size of panel3.
Bitmap bmp = new Bitmap(panel3.ClientSize.Width, panel3.ClientSize.Height);
panel3.DrawToBitmap(bmp, panel3.ClientRectangle);
bmp.Save(subPath + file + ".bmp");
Which again, looks great on a print preview and if I click print from the print preview it prints fine. But if I just send it straight to the printer it doesn't fit. So maybe its not a size issue but a setting I have to send to the printer when not using print preview?
Update
So I may have found the issue. When you un-check "Fit to frame" when printing a picture it fits perfectly. However there doesn't seem to be an option when sending directly to the printer the way I am where I can disable "Fit to frame"
If you want to resize and keep the aspect of the image I do the following
public Stream ResizeImage(Stream stream, ImageFormat imageFormat, int width, int height)
{
var originalImage = Image.FromStream(stream);
var sourceWidth = originalImage.Width;
var sourceHeight = originalImage.Height;
const int sourceX = 0;
const int sourceY = 0;
var destX = 0;
var destY = 0;
float nPercent;
var nPercentW = ((float)width / sourceWidth);
var nPercentH = ((float)height / sourceHeight);
if (nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = Convert.ToInt16((width - (sourceWidth * nPercent)) / 2);
}
else
{
nPercent = nPercentW;
destY = Convert.ToInt16((height - (sourceHeight * nPercent)) / 2);
}
var destWidth = (int)(sourceWidth * nPercent);
var destHeight = (int)(sourceHeight * nPercent);
// specify different formats based off type ( GIF and PNG need alpha channel - 32aRGB 8bit Red 8bit Green 8bit B 8bit Alpha)
Bitmap newImage;
if (imageFormat.Equals(ImageFormat.Png) || imageFormat.Equals(ImageFormat.Gif))
{
newImage = new Bitmap(width, height, PixelFormat.Format32bppArgb);
}
else
{
newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);
}
newImage.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
var newGraphics = Graphics.FromImage(newImage);
// don't clear the buffer with white if we have transparency
if (!imageFormat.Equals(ImageFormat.Png) && !imageFormat.Equals(ImageFormat.Gif))
{
newGraphics.Clear(Color.White);
}
newGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
newGraphics.DrawImage(originalImage,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
newGraphics.Dispose();
originalImage.Dispose();
var memoryStream = new MemoryStream();
newImage.Save(memoryStream, imageFormat);
memoryStream.Position = 0;
return memoryStream;
}
Using this you can resize the image. You need to pick up a scaling size before print.
As example - rescale 'image' to 227x171 pixels.
image = new Bitmap(image, new Size(227, 171));
I have to display image in photo gallery # width=200 height=180, but while uploading images I have to resize it , but the problem is every image have different resolution. How can I resize the images with different resolution so that images remain intact.
Here is my code :
private void ResizeImage()
{
System.Drawing.Image ImageToUpload = System.Drawing.Image.FromStream(FileUpload1.PostedFile.InputStream);
byte[] image = null;
int h = ImageToUpload.Height;
int w = ImageToUpload.Width;
int r = int.Parse(ImageToUpload.VerticalResolution.ToString());
int NewWidth = 200;//constant
int NewHeight = 180;//constant
byte[] imagesize = FileUpload1.FileBytes;
System.Drawing.Bitmap BitMapImage = new System.Drawing.Bitmap(ImageToUpload, NewWidth, NewHeight);//this line gives horrible output
MemoryStream Memory = new MemoryStream();
BitMapImage.Save(Memory, System.Drawing.Imaging.ImageFormat.Jpeg);
Memory.Position = 0;
image = new byte[Memory.Length + 1];
Memory.Read(image, 0, image.Length);
}
if resolution is 96 and if I set maxwidth=200 then its height would be 150 then only the image looks small and accurate. Can't we resize image in desired way so that it looks exact?
The function will resize the image maintaining aspect ratio.
public static Image Resize(Image originalImage, int w, int h)
{
//Original Image attributes
int originalWidth = originalImage.Width;
int originalHeight = originalImage.Height;
// Figure out the ratio
double ratioX = (double)w / (double)originalWidth;
double ratioY = (double)h / (double)originalHeight;
// use whichever multiplier is smaller
double ratio = ratioX < ratioY ? ratioX : ratioY;
// now we can get the new height and width
int newHeight = Convert.ToInt32(originalHeight * ratio);
int newWidth = Convert.ToInt32(originalWidth * ratio);
Image thumbnail = new Bitmap(newWidth, newHeight);
Graphics graphic = Graphics.FromImage(thumbnail);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
graphic.Clear(Color.Transparent);
graphic.DrawImage(originalImage, 0, 0, newWidth, newHeight);
return thumbnail;
}
Usage
Image BitMapImage = Resize(ImageToUpload, NewWidth, NewHeight);
Here i keep height fixed to 180 to maintain aspect ratio. It will resize the image and save to disk. The return value is the percentage value which i use in 'background-size' css.
public float ResizePhoto(string filepath, string filename)
{
var path = Path.Combine(filepath, filename);
var newPath = Path.Combine(filepath, "sml_" + filename);
Image orgImage = Image.FromFile(path);
float fixedHt = 180f;
int destHeight, destWidth;
float reqScale;
if(orgImage.Height > fixedHt)
{
destHeight = (int)fixedHt;
destWidth = (int)(fixedHt / orgImage.Height * orgImage.Width);
reqScale = destWidth / destHeight * 100;
}
else
{
destHeight = orgImage.Height;
destWidth = orgImage.Width;
reqScale = fixedHt / destHeight * 100;
}
Bitmap bmp = new Bitmap(destWidth, destHeight);
bmp.SetResolution(orgImage.HorizontalResolution,orgImage.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmp);
grPhoto.DrawImage(orgImage,
new Rectangle(0, 0, destWidth, destHeight),
new Rectangle(0, 0, orgImage.Width, orgImage.Height),
GraphicsUnit.Pixel);
bmp.Save(newPath);
return reqScale;
}
How would you resize a JPEG image, to a fixed width whilst keeping aspect ratio? In a simple way, whilst preserving quality.
This will scale in the vertical axis only:
public static Image ResizeImageFixedWidth(Image imgToResize, int width)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = ((float)width / (float)sourceWidth);
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
If you are reducing the width by 25 percent to a fixed value, you must reduce the height by 25 percent.
If you are increasing the width by 25 percent to a fixed value, you must increasing the height by 25 percent.
It's really straight forward.
Assuming there is a (double width) variable:
Image imgOriginal = Bitmap.FromFile(path);
double height = (imgOriginal.Height * width) / imgOriginal.Width;
Image imgnew = new Bitmap((int)width, (int)height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(imgnew);
g.DrawImage(imgOriginal, new Point[]{new Point(0,0), new Point(width, 0), new Point(0, height)}, new Rectangle(0,0,imgOriginal.Width, imgOriginal.Height), GraphicsUnit.Pixel);
In the end you´ll have a new image with widthxheight, then, you´ll need to flush the graphics e save the imgnew.
I think there are plenty of samples of this if you search for them. Here's the one I commonly use...
public static Stream ResizeGdi(Stream stream, System.Drawing.Size size)
{
Image image = Image.FromStream(stream);
int width = image.Width;
int height = image.Height;
int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
float percent = 0, percentWidth = 0, percentHeight = 0;
percentWidth = ((float)size.Width / (float)width);
percentHeight = ((float)size.Height / (float)height);
int destW = 0;
int destH = 0;
if (percentHeight < percentWidth)
{
percent = percentHeight;
}
else
{
percent = percentWidth;
}
destW = (int)(width * percent);
destH = (int)(height * percent);
MemoryStream mStream = new MemoryStream();
if (destW == 0
&& destH == 0)
{
image.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return mStream;
}
using (Bitmap bitmap = new Bitmap(destW, destH, System.Drawing.Imaging.PixelFormat.Format48bppRgb))
{
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
{
//graphics.Clear(Color.Red);
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawImage(image,
new Rectangle(destX, destY, destW, destH),
new Rectangle(sourceX, sourceY, width, height),
GraphicsUnit.Pixel);
}
bitmap.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}
mStream.Position = 0;
return mStream as Stream;
}
Example of the calling code...
Stream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
resizedStream = ImageUtility.ResizeGdi(stream, new System.Drawing.Size(resizeWidth, resizeHeight));
A quick search on code project has found the following article. It allows for resizing of images which accepts a boolean to restrain the new image to keep the originals aspect ratio. I'm unsure of what the quality is like as no screenshots were provided. See the article here
I am trying to print my form using GDI ,but when I print it ,the quality of the print is not that good(donknow whether Image getting aliased?) ,form size is 700x700 ,also there is one parameter which dint understood -raster op code-,here is code am using...
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g1 = this.CreateGraphics();
System.Drawing.Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);
Graphics g2 = Graphics.FromImage(MyImage);
IntPtr dc1 = g1.GetHdc();
IntPtr dc2 = g2.GetHdc();
BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);
g1.ReleaseHdc(dc1);
g2.ReleaseHdc(dc2);
Bitmap bmp = new Bitmap(MyImage);
int x = e.MarginBounds.X;
int y = e.MarginBounds.Y;
int width = bmp.Width;
int height = bmp.Height;
if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height))
{
width = e.MarginBounds.Width;
height = bmp.Height * e.MarginBounds.Width / bmp.Width;
}
else
{
height = e.MarginBounds.Height;
width = bmp.Width * e.MarginBounds.Height / bmp.Height;
}
System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(x, y, width, height);
e.Graphics.DrawImage(bmp, destRect, 0, 0, bmp.Width, bmp.Height, System.Drawing.GraphicsUnit.Pixel);
}
Maybe you have a problem with the original image. Give me a link to an image. Check the image size.
Try insert line
g2.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
Good luck!
It is normal that the result will be scaled and aliased. The source has too few pixels compared to the resolution of a modern printer.
Consider using WPF, that uses a vector based rendering thus there's no loss/distortion when scaling.
Cheers