I have a function which takes in an image and resizes it to fit a canvas while maintaining its aspect ratio. This code is only a minorly modified version of the code from this answer: c# Image resizing to different size while preserving aspect ratio
For this example, my canvas height is 642, my canvas width is 823.
When I run the below function, the line
graphic.DrawImage(image, posX, posY, newWidth, newHeight);
seemingly does nothing to the image size. Going in:
Image.Height == 800,
Image.Width == 1280.
newHeight = 514,
newWidth == 823
AFTER running graphic.DrawImage
Image.Height == 800,
Image.Width == 1280.
As you can see, Image's height and width are unchanged.
Does anyone see a gapingly obvious error that would cause this to happen? Thank you!
private Bitmap resizeImage(Bitmap workingImage,
int canvasWidth, int canvasHeight)
{
Image image = (Bitmap)workingImage.Clone();
System.Drawing.Image thumbnail =
new Bitmap(canvasWidth, canvasHeight);
double ratioX = (double)canvasWidth / (double)workingImage.Width;
double ratioY = (double)canvasHeight / (double)workingImage.Height;
double ratio = ratioX < ratioY ? ratioX : ratioY;
int newHeight = Convert.ToInt32((double)workingImage.Height * ratio);
int newWidth = Convert.ToInt32((double)workingImage.Width * ratio);
int posX = Convert.ToInt32((canvasWidth - ((double)workingImage.Width * ratio)) / 2);
int posY = Convert.ToInt32((canvasHeight - ((double)workingImage.Height * ratio)) / 2);
using (Graphics graphic = Graphics.FromImage(thumbnail))
{
graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphic.Clear(SystemColors.Control);
graphic.DrawImage(image, posX, posY, newWidth, newHeight); //<--- HERE
}
System.Drawing.Imaging.ImageCodecInfo[] info =
System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
System.Drawing.Imaging.EncoderParameters encoderParameters;
encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality,
100L);
return workingImage;
}
Size of your image is defined here
Image image = (Bitmap)workingImage.Clone();
This
graphic.DrawImage(image, posX, posY, newWidth, newHeight);
only draws the image with specified arguments, but it does not mean that the image size gets changed. In other words, drawing an image simply does not change its size, it just takes the image and draws it on a canvas as you wish.
Image Resizing functanality pupose see the below link
http://www.codeproject.com/Articles/30524/An-Easy-to-Use-Image-Resizing-and-Cropping-Control?msg=5203911#xx5203911xx
This link content may help you
Related
Following this question Resize image proportionally with MaxHeight and MaxWidth constraints
I implemented the solution as follows:
public static class ImageResizer
{
public static Image ResizeImage(String origFileLocation, int maxWidth, int maxHeight)
{
Image img = Image.FromFile(origFileLocation);
if (img.Height < maxHeight && img.Width < maxWidth) return img;
using (img)
{
Double xRatio = (double)maxWidth / img.Width;
Double yRatio = (double)maxHeight / img.Height;
Double ratio = Math.Max(xRatio, yRatio);
int nnx = (int)Math.Floor(img.Width * ratio);
int nny = (int)Math.Floor(img.Height * ratio);
Bitmap cpy = new Bitmap(nnx, nny, PixelFormat.Format32bppArgb);
using (Graphics gr = Graphics.FromImage(cpy))
{
gr.Clear(Color.Transparent);
// This is said to give best quality when resizing images
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.DrawImage(img,
new Rectangle(0, 0, nnx, nny),
new Rectangle(0, 0, img.Width, img.Height),
GraphicsUnit.Pixel);
}
return cpy;
}
}
}
And then saving image this way:
resized.Save(resizedFilePath, System.Drawing.Imaging.ImageFormat.Gif);
However, trying it, shrinking image, the result is very grained as you can see in this photo
I would assume that shrinking image should result with no noticeable effects. Any ideas about it?
Yes. As #Ivan Stoev suggested. The problem is not with the resizing, rather in the saving method which appears to compress the image by default for some reason.
I used
resized.Save(resizedFilePath, System.Drawing.Imaging.ImageFormat.Png);
for saving and now everything seems fine. Thank you.
resized.Save(resizedFilePath, System.Drawing.Imaging.ImageFormat.Png);
size large not optimation
I am fairly new to C# GDI+ graphics.
I want to draw an image over another, which should be centered horizontally and vertically in a fixed height and width container on an image.
I tried to do this with horizontal centering and the output is weird.
I am sharing the commented code of how I am trying to do it, let me know if there is any easier way to do it, I just want to scale and center the image.
//The parent image resolution is 4143x2330
//the container for child image is 2957x1456
Image childImage = Image.FromFile(path.Text.Trim());
Image ParentImage = (Image)EC_Automation.Properties.Resources.t1;
Bitmap bmp2 = (Bitmap)ParentImage;
Graphics graphic = Graphics.FromImage(ParentImage);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
double posX = (2957 / 2.0d) - (childImage.Width / 2.0d);
//HAlf of the container size - Half of the image size should make it center in container
graphic.DrawImage((Image)childImage,
new Rectangle(new Point((int)posX, 420), new Size( 2957, 1456))); //Drawing image
public Image ScaleImage(Image image, int maxWidth, int maxHeight)
{
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(maxWidth, maxHeight);
using (var graphics = Graphics.FromImage(newImage))
{
// Calculate x and y which center the image
int y = (maxHeight/2) - newHeight / 2;
int x = (maxWidth / 2) - newWidth / 2;
// Draw image on x and y with newWidth and newHeight
graphics.DrawImage(image, x, y, newWidth, newHeight);
}
return newImage;
}
Thanks #Gabriel Calegari
for center image set x below code
int x = (PaperWidth/ 2) - imageWidth / 2;
graph.DrawImage(image, x, 0, imageWidth, ImageHeight);
Solved it , I was drawing the image of fixed width, whereas it should have been with a new width based on the aspect ratio and new height,
Also I was taking trying to find the center of the image from Container, which should have been the center of the whole parent Image
First of all, sorry for the title but I don't know how to explain it better.
Here is my question. I'm scaling images, check for duplicates and watermark them. The interesting thing is that when I save them to a "/temp/" folder, the whole process is faster than just scaling and using them while they're loaded in the memory.
This is the code that I'm using for scaling:
private static Bitmap ScaleImage(string pathToImage, int maxWidth, int maxHeight)
{
Bitmap image = new Bitmap(pathToImage);
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.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
Bitmap bmp = new Bitmap(newImage);
return bmp;
}
Then I just assign the scaled images to variables:
Image imageLeft = ScaleImage(tempImage1, 48, 48);
Image imageRight = ScaleImage(tempImage2, 48, 48);
... and compare them.
So what bothers me is why this is slower than saving all scaled images in a folder and then do the comparsion?
I am Resizing a Image and add watermark to image. And Return the image. Here is my code.
Image resizedImage = ResizeImage(original6, new Size(500, 375));
Re size function:
public static System.Drawing.Image ResizeImage(System.Drawing.Image image, Size size)
{
int newWidth;
int newHeight;
if (true)
{
int originalWidth = image.Width;
int originalHeight = image.Height;
float percentWidth = (float)size.Width / (float)originalWidth;
float percentHeight = (float)size.Height / (float)originalHeight;
float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
newWidth = (int)(originalWidth * percent);
newHeight = (int)(originalHeight * percent);
}
else
{
newWidth = size.Width;
newHeight = size.Height;
}
System.Drawing.Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
}
System.Drawing.Bitmap bitmapimage = new System.Drawing.Bitmap(newImage, size.Width, size.Height);// create bitmap with same size of Actual image
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmapimage);
SolidBrush brush = new SolidBrush(Color.FromArgb(113, 255, 255, 255));
//Adding watermark text on image
g.DrawString("My watermark", new Font("Arial", 16, FontStyle.Bold), brush, 5, 100);
return bitmapimage;
}
I am retrieve the new re sized image with watermark and going to save as new image file.
resized6.Save(Server.MapPath(sSavePath + ownerRef + "Pic6v2" + ".jpg"));
This is working fine. However I can't control the file size.
When my original JPG is only 45kb but when my new re-sized image is 500kb. How can I reduce the file size.?
info: original resolution (400x300 px) and new image (500x375px)
I don't remember this off the top of my head, but file size generally has to do with JPEG quality settings. You also need to make sure it's saved as an actual jpg, not a bitmap, which I don't see that you're doing..
See also: C# Simple Image Resize : File Size Not Shrinking
JPEG Quality settings:
http://msdn.microsoft.com/en-us/library/bb882583.aspx
You may be able to change the quality of the JPEG to get a smaller file size. See
http://msdn.microsoft.com/en-us/library/bb882583.aspx
also
Quality of a saved JPG in C#
I need to resize my image proportionately without changing aspect ratio.I have the code to resize with fixed hight and width but I need to resize image proportionately with max height(say 600 pixels). How can I modify the code to suit my requirement?
public static void Main()
{
var image = Image.FromFile(#"c:\logo.png");
var newImage = ScaleImage(image, 300, 400);
newImage.Save(#"c:\test.png", ImageFormat.Png);
}
public static Image ScaleImage(Image image, int maxWidth, int maxHeight)
{
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.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
return newImage;
}
Please provide your valuable thoughts.
This almost feels to easy and I feel I'm missing something. Anyway, won't that do the trick?
public static Image ScaleImage(Image image, int maxHeight)
{
var ratio = (double)maxHeight / image.Height;
var newWidth = (int)(image.Width * ratio);
var newHeight = (int)(image.Height * ratio);
var newImage = new Bitmap(newWidth, newHeight);
using (var g = Graphics.FromImage(newImage))
{
g.DrawImage(image, 0, 0, newWidth, newHeight);
}
return newImage;
}
Use the following function
public Bitmap ProportionallyResizeBitmapByHeight(Bitmap imgToResize, int height)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float scale = 0;
scale = (height / (float)sourceHeight);
int destWidth = (int)(sourceWidth * scale);
int destHeight = (int)(sourceHeight * scale);
Bitmap result = new Bitmap(destWidth, destHeight);
result.SetResolution(imgToResize.HorizontalResolution, imgToResize.VerticalResolution);
Graphics g = Graphics.FromImage(result);
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return result;
}
Well, thinking through the process:
if you have an image that 800 x 600 in size and want to resize it to newWidth x 400 height (plus whatever the respective newWidth will be), you get the ratio by dividing the newHeight (maxHeight in your case) with 600 and multiply 800 with this ratio, right?
So, in this case you need to change maxWidth and maxHeight to optional parameters (say 800 by 600) to give yourself some dynamism and get the following:
public static Image ScaleImage(Image image, int maxWidth = 800, int maxHeight = 600)
{
int newWidth;
int newHeight;
double ratio = image.Height / image.Width;
if(maxHeight != 600) {
newWidth = image.Width * ratio;
newHeight = maxHeight;
}
Bitmap newImage = new Bitmap(newWidth, newHeight);
Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
return newImage;
}
I hope this helps. I didn't test it, but I've rewritten my VB code, so allegedly it should be okay...
There's also a ResizeStream method here: http://forums.asp.net/t/1576697.aspx/1 that you might find useful.
If you want to keep image quality, you can use the CompositingQuality and SmoothingMode, etc. variables.
100% Worked
private static BitmapFrame CreateResizedImage(ImageSource source, int Max_width, int Max_height, int margin)
{
float scaleHeight = (float)Max_width / (float)source.Height;
float scaleWidth = (float)Max_height / (float)source.Width;
float scale = Math.Min(scaleHeight, scaleWidth);
int width = (int)(source.Width * scale);
int height = (int)(source.Height * scale);
var rect = new Rect(margin, margin, width - margin * 2, height - margin * 2);
var group = new DrawingGroup();
RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);
group.Children.Add(new ImageDrawing(source, rect));
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
drawingContext.DrawDrawing(group);
var resizedImage = new RenderTargetBitmap(
width, height, // Resized dimensions
96, 96, // Default DPI values
PixelFormats.Default); // Default pixel format
resizedImage.Render(drawingVisual);
return BitmapFrame.Create(resizedImage);
}
//--------Main------------//
BitmapImage imageSource = (BitmapImage)ImagePreview.Source;
var NewImage= CreateResizedImage(imageSource , 300, 300, 0);