I have a big image in good quality (for my needs), i need resize to small size (30 x 30px), I resize it with graphic.DrawImage. But when i resize it become blurred and little lighter.
also I have try CompositingQuality and InterpolationMode, but it all was bad.
Example, that quality i'm trying get.
My result
Edited
Image of icon i draw myself, maybe it will be better draw it small without resizing?
Edit2
Resizeing code:
Bitmap tbmp;
//drawing all my features in tbmp with graphics
bmp = new Bitmap(width + 5, height + 5);
bmp.MakeTransparent(Color.Black);
using (var gg = Graphics.FromImage(bmp))
{
gg.CompositingQuality = CompositingQuality.HighQuality;
// gg.SmoothingMode = SmoothingMode.HighQuality;
gg.InterpolationMode = InterpolationMode.HighQualityBicubic;
gg.DrawImage(tbmp, new Rectangle(0, 0, width, height), new Rectangle(GXMin, GYMin, GXMax + 20, GYMax + 20), GraphicsUnit.Pixel);
gg.Dispose();
}
I use this method as a way to get a thumbnail image (of any size) from an original (of any size). Note that there are inherent issues when you ask for a size ratio that varies greatly from that of the original. Best to ask for sizes that are in scale to one another:
public static Image GetThumbnailImage(Image OriginalImage, Size ThumbSize)
{
Int32 thWidth = ThumbSize.Width;
Int32 thHeight = ThumbSize.Height;
Image i = OriginalImage;
Int32 w = i.Width;
Int32 h = i.Height;
Int32 th = thWidth;
Int32 tw = thWidth;
if (h > w)
{
Double ratio = (Double)w / (Double)h;
th = thHeight < h ? thHeight : h;
tw = thWidth < w ? (Int32)(ratio * thWidth) : w;
}
else
{
Double ratio = (Double)h / (Double)w;
th = thHeight < h ? (Int32)(ratio * thHeight) : h;
tw = thWidth < w ? thWidth : w;
}
Bitmap target = new Bitmap(tw, th);
Graphics g = Graphics.FromImage(target);
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.High;
Rectangle rect = new Rectangle(0, 0, tw, th);
g.DrawImage(i, rect, 0, 0, w, h, GraphicsUnit.Pixel);
return (Image)target;
}
Related
Link to Project: https://github.com/FFladenmuller/resize-bmp
Code works for a resize with a factor of 1. However, if trying a larger factor and I open the image, Photos says: "It looks like we don't support this file format".
I have not added in padding yet but I have only worked with images whose width is divisible by 4.
For loop to add BGR bytes to new Image:
for (int i = 54; i < oldBMP.Info.Count - 2; i += 3)
{
for(int j = 0; j < sizeMultiplier; j++)
{
newBMP.Info.Add(oldBMP.Info[i]);
newBMP.Info.Add(oldBMP.Info[i + 1]);
newBMP.Info.Add(oldBMP.Info[i + 2]);
}
}
First for loop to increment through BGR triples, second for loop to add each pixel sizeMultiplier amount of times.
Define the following method:
public static Bitmap ResizeImage(Bitmap image, Size size)
{
try
{
Bitmap result = new Bitmap(size.Width, size.Height);
using (Graphics g = Graphics.FromImage((Image)result))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawImage(image, 0, 0, size.Width, size.Height);
}
return result;
}
catch
{
return image;
}
}
Then, within your code, whenever a resize is needed:
Bitmap image = new Bitmap(#"C:\Path\MyImage.bmp");
Single scaleWidth = 1.2f;
Int32 targetWidth = (Int32)((Single)image.Width * scaleWidth);
Single scaleHeight = 1.0f;
Int32 targetHeight = (Int32)((Single)image.Height * scaleHeight);
Size size = new Size(targetWidth, targetHeight);
Bitmap imageResized = ResizeImage(image, size);
An alternative (that has the drawback of reducing the output quality) is the following:
Bitmap image = new Bitmap(#"C:\Path\MyImage.bmp");
Single scaleWidth = 1.2f;
Int32 targetWidth = (Int32)((Single)image.Width * scaleWidth);
Single scaleHeight = 1.0f;
Int32 targetHeight = (Int32)((Single)image.Height * scaleHeight);
Bitmap imageResized = new Bitmap(image, targetWidth, targetHeight);
The following code behaves very oddly. It adds some extra spacing at the bottom of the image, and I can not see why. Result of code:
And this is the code that I am working with:
public static Image ReDraw(this Image main, int w, int h,
CompositingQuality quality = CompositingQuality.Default, //linear?
SmoothingMode smoothing_mode = SmoothingMode.None,
InterpolationMode ip_mode = InterpolationMode.NearestNeighbor)
{
//size
double dbl = (double)main.Width / (double)main.Height;
//preserve size ratio
if ((int)((double)h * dbl) <= w)
w = (int)((double)h * dbl);
else
h = (int)((double)w / dbl);
//draw
Image newImage = new System.Drawing.Bitmap(w, h);
Graphics thumbGraph = Graphics.FromImage(newImage);
thumbGraph.CompositingQuality = quality;
thumbGraph.SmoothingMode = smoothing_mode;
thumbGraph.InterpolationMode = ip_mode;
thumbGraph.Clear(Color.Transparent);
thumbGraph.DrawImage(main, 0, 0, w, h);
thumbGraph.DrawImage(main,
new System.Drawing.Rectangle(0, 0, w, h),
new System.Drawing.Rectangle(0, 0, main.Width, main.Height),
System.Drawing.GraphicsUnit.Pixel);
return newImage;
}
thumbGraph.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
This question already has answers here:
Resize image proportionally with MaxHeight and MaxWidth constraints
(3 answers)
Closed 9 years ago.
Am re sizing an image with the following code
using (Image thumbnail = new Bitmap(100, 50))
{
using (Bitmap source = new Bitmap(imageFile))
{
using (Graphics g = Graphics.FromImage(thumbnail))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(source, 0, 0, 100, 50);
}
}
using (MemoryStream ms = new MemoryStream())
{
thumbnail.Save(ms, ImageFormat.Png);
thumbnail.Save(dest, ImageFormat.Png);
}
}
but it is not giving an image of any quality. pixelation is making the image wired.
i have also tried the code
image re size in stack
but am getting a black screen as the result instead of jpg am using png is the only difference.
any suggestion for improving the image quality. i have to re size the transparent image to a size 100by50.
Thanks in advance.
Try this, Assuming you can use it
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;
}
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