Rescaling image causes loss of pixels - c#

I seem to be having trouble up-scaling an image that is 8x8 pixels. When testing, I wanted to scale the image up to 64x64 pixels. However, when doing so, this was the result:
Rescaling it the way I did below, removes 4 pixels height on the top, and 4 pixels width on the left, and adds 4 black pixels height on the bottom, and 4 pixels width on the right.
Here is the code I am using to rescale the image:
private static Image ScaleImage(string username, int size)
{
Image avatar = MergeImage(username);
int originalWidth = avatar.Width;
int originalHeight = avatar.Height;
float ratioX = (float)size / (float)originalWidth;
float ratioY = (float)size / (float)originalHeight;
float ratio = Math.Min(ratioX, ratioY);
int newWidth = (int)(originalWidth * ratio);
int newHeight = (int)(originalHeight * ratio);
Bitmap newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format48bppRgb);
using (Graphics g = Graphics.FromImage(newImage))
{
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.DrawImage(avatar, 0, 0, newWidth, newHeight);
}
return newImage;
}
I am unsure of what is going wrong here. Any help would be greatly appreciated.

Add this before g.DrawImage:
g.PixelOffsetMode = PixelOffsetMode.Half;

Related

Resize code ruins quality? [duplicate]

This question already has an answer here:
How resize image without losing quality
(1 answer)
Closed 5 years ago.
So I'm trying to resize HUGE images, like 5500x3500 JPGs down to 1024x768 or less. The following function works, but it really runs the quality, makes the text all fuzzy.
static public Bitmap 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);
Bitmap bmp = new Bitmap(newImage);
return bmp;
}
Any idea of a better way to do this?
As suggested in comment, you should use Interpolation mode to control image quality during scaling. To know how to use it, refer to the following doc from Microsoft,
https://learn.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-use-interpolation-mode-to-control-image-quality-during-scaling
You should set the quality-properties in Graphics-object to HighQuality:
static public Bitmap 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);
using (Bitmap newImage = new Bitmap(newWidth, newHeight))
{
using (Graphics g = Graphics.FromImage(newImage))
{
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
Bitmap bmp = new Bitmap(newImage);
return bmp;
}
}
}
Also be sure to use using-block with objects that implements iDisposable: Image, Bitmap and Graphichs all do.

Scale or resize an 8bit image with 8bit image as result (PixelFormat.Format8bppIndexed)

I try to scale a grey8 image for video transmission via TCP-clients in C#/.NET.
My image from an IpCam is currently 1920x1080 and I want to resize it to 640x480 in order to reduce traffic on the connection:
I found a working example here on Stack Overflow the only problem is.
public static Image ResizeImage(Bitmap image, Size size, bool preserveAspectRatio = true)
{
int newWidth;
int newHeight;
if (preserveAspectRatio)
{
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;
}
Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic; //NearestNeighbor
graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
}
return(newImage);
}
.the image I get from this function is a 32ARgb image, which is not what I want. Because it introduces 3 additional color channels (Alpha and RBG).
Is there a way of scaling the image down without changing the color pattern?
I also tried to use the InterpolationMode.NearestNeighbor but I only got a 32bit-bitmap out of it.

How to increase image's height and width without stretching it

I have a div section of width 1000px and 290 px height.if i upload image of width 500px and height 400px,and increase height and width from code,here is my code sample,it get stretch the image
var thumbnailImg = new Bitmap(newWidth, newHeight);
var thumbGraph = Graphics.FromImage(thumbnailImg);
thumbGraph.CompositingQuality = CompositingQuality.HighQuality;
thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
//Bitmap bmpImage = new Bitmap(img);
var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);
//Bitmap bmpcrop = bmpImage.Clone(imageRectangle, bmpImage.PixelFormat);
//return (Image)bmpcrop;
thumbGraph.DrawImage(img, imageRectangle);
MemoryStream stram = new MemoryStream();
thumbnailImg.Save(stram, img.RawFormat);
byte[] imagebytes = stram.ToArray();
return imagebytes;
To resize an image ensuring that it is the same proportions, the ratio of the initial height x width (h x w) will have to be the same as the final h x w.
In your case your initial ratio is 500:400 while the final is 1000:290.
From 500:400, you can make it 1000:800, making it 2x bigger. Here the initial ratio is the same as the final ratio.
However, this won't fit the width of your specified div.
The other way is to reduce the width to 290, which means to proportionally reduce the height, you have to make the height be reduced by a factor of (1000 * (290/400)) which will be less than 1000.
So the only way is to either change your initial picture dimensions or your div dimensions if you want a perfect fit.

Reduce bitmap image physical size?

I am loading images onto an excel page, once done this excel is around 48,284 KB This is to large and affects the download speed and is not efficient to what we are trying to achieve.
I am trying to reduce this Excel file size as much as possible and think that reducing the image sizes would do the trick as the excel file without images is around 1000 kb.
This is what i have tried so far with no affect:
public Image ReduceImageSize(Image img)
{
float iwidth = 150;
float iheight = 150;
var brush = new SolidBrush(Color.Black);
var Resizedimage = new Bitmap(img);
float scale = Math.Min(iwidth / Resizedimage.Width, iheight / Resizedimage.Height);
var graph = Graphics.FromImage(Resizedimage);
graph.InterpolationMode = InterpolationMode.Low;
graph.CompositingQuality = CompositingQuality.Default;
graph.SmoothingMode = SmoothingMode.None;
var scaleWidth = (int)(Resizedimage.Width * scale);
var scaleHeight = (int)(Resizedimage.Height * scale);
graph.FillRectangle(brush, new RectangleF(0, 0, iwidth, iheight));
graph.DrawImage(Resizedimage, new Rectangle(((int)iwidth - scaleWidth) / 2, ((int)iheight - scaleHeight) / 2, scaleWidth, scaleHeight));
return Resizedimage;
}
At this point i'm looking for any way to reduce the size if it involves losing some quality or reducing the images dimensions.
Please help.
You made Resizedimage the same size as img.
Use the following code to fix the result image size:
var Resizedimage = new Bitmap(iwidth,iheight);
An example resizing an image keeping the aspect ratio:
Image img = Image.FromFile(#"c:\temp\1.jpg");
Bitmap resizedImg = new Bitmap(150, 150);
double ratioX = (double)resizedImg.Width / (double)img.Width;
double ratioY = (double)resizedImg.Height / (double)img.Height;
double ratio = ratioX < ratioY ? ratioX : ratioY;
int newHeight = Convert.ToInt32(img.Height * ratio);
int newWidth = Convert.ToInt32(img.Width * ratio);
using (Graphics g = Graphics.FromImage(resizedImg))
{
g.DrawImage(img, 0, 0, newWidth, newHeight);
}
resizedImg.Save(#"c:\temp\2.jpg");

C# Image Resizer with Canvas Handler

I'm incredibly new to C# (just started today)
I need to be able to make a C# Image resizer with a canvas handler. For example a 500 x 500 image needs to retain its aspect ration. it will be getting resized to 1024x500. To do this it will remain 500x500 but then fill the rest of the space with white space (the canvas).
I will also be resizing the same original image to 300 x 500, where the image will again retain its 1:1 ration and be resized to 300x300 and the remaining space again used as canvas white space.
Can anybody help me to produce a C# console application for this, that I can understand?
Here is what I have managed to find that I could reasonably understand (due to nice commenting).
What I find with code is that I can read it, but when it comes to me actually writing some I just fall apart. I mainly do HTML and CSS. Starting to branch out into JQuery and C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
namespace ImageResizer
{
class ImageResize
{
static void Main(string[] args)
{
}
public void ResizeImage(string OriginalFile, string NewFile, int NewWidth, int MaxHeight, bool OnlyResizeIfWider)
{
System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFile);
// Prevent using images internal thumbnail
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
if (OnlyResizeIfWider)
{
if (FullsizeImage.Width <= NewWidth)
{
NewWidth = FullsizeImage.Width;
}
}
int NewHeight = FullsizeImage.Height * NewWidth / FullsizeImage.Width;
if (NewHeight > MaxHeight)
{
// Resize with height instead
NewWidth = FullsizeImage.Width * MaxHeight / FullsizeImage.Height;
NewHeight = MaxHeight;
}
System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero);
// Clear handle to original file so that we can overwrite it if necessary
FullsizeImage.Dispose();
// Save resized picture
NewImage.Save(NewFile);
}
}
}
Try To Go For This>>
private void resizeImage(string path, string originalFilename,
/* note changed names */
int canvasWidth, int canvasHeight,
/* new */
int originalWidth, int originalHeight)
{
Image image = Image.FromFile(path + originalFilename);
System.Drawing.Image thumbnail =
new Bitmap(canvasWidth, canvasHeight); // changed parm names
System.Drawing.Graphics graphic =
System.Drawing.Graphics.FromImage(thumbnail);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
/* ------------------ new code --------------- */
// Figure out the ratio
double ratioX = (double) canvasWidth / (double) originalWidth;
double ratioY = (double) canvasHeight / (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);
// Now calculate the X,Y position of the upper-left corner
// (one of these will always be zero)
int posX = Convert.ToInt32((canvasWidth - (originalWidth * ratio)) / 2);
int posY = Convert.ToInt32((canvasHeight - (originalHeight * ratio)) / 2);
graphic.Clear(Color.White); // white padding
graphic.DrawImage(image, posX, posY, newWidth, newHeight);
/* ------------- end new code ---------------- */
System.Drawing.Imaging.ImageCodecInfo[] info =
ImageCodecInfo.GetImageEncoders();
EncoderParameters encoderParameters;
encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,
100L);
thumbnail.Save(path + width + "." + originalFilename, info[1],
encoderParameters);
}

Categories