如何在C#中调整图像大小以保持纵横比
本文关键字:图像 调整 | 更新日期: 2023-09-27 18:27:15
我需要知道一种方法,可以调整图像的大小,使其适合盒子,而不会使图像拉伸过大。盒子已经设置了宽度和高度,我希望图像尽可能多地填充盒子,但保持原来的纵横比。
//calculate the ratio
double dbl = (double)image.Width / (double)image.Height;
//set height of image to boxHeight and check if resulting width is less than boxWidth,
//else set width of image to boxWidth and calculate new height
if( (int)((double)boxHeight * dbl) <= boxWidth )
{
resizedImage = new Bitmap(original, (int)((double)boxHeight * dbl), boxHeight);
}
else
{
resizedImage = new Bitmap(original, boxWidth, (int)((double)boxWidth / dbl) );
}
相同比例缩放的公式为:
newWidth = (int)((double)boxHeight * dbl)
or
newHeight = (int)((double)boxWidth / dbl)
Math.Max可以简化问题:
double ratio = Math.Max((double)image.width / (double)box.width , (double)image.height / (double)box.height);
image.width = (int)(image.width / ratio);
image.height = (int)(image.height / ratio);
Bitmap original,resizedImage;
try
{
using (FileStream fs = new System.IO.FileStream(imageLabel.Text, System.IO.FileMode.Open))
{
original = new Bitmap(fs);
}
int rectHeight = BOXWIDTH;
int rectWidth = BOXWIDTH;
//if the image is squared set it's height and width to the smallest of the desired dimensions (our box). In the current example rectHeight<rectWidth
if (original.Height == original.Width)
{
resizedImage = new Bitmap(original, rectHeight, rectHeight);
}
else
{
//calculate aspect ratio
float aspect = original.Width / (float)original.Height;
int newWidth, newHeight;
//calculate new dimensions based on aspect ratio
newWidth = (int)(rectWidth * aspect);
newHeight = (int)(newWidth / aspect);
//if one of the two dimensions exceed the box dimensions
if (newWidth > rectWidth || newHeight > rectHeight)
{
//depending on which of the two exceeds the box dimensions set it as the box dimension and calculate the other one based on the aspect ratio
if (newWidth > newHeight)
{
newWidth = rectWidth;
newHeight = (int)(newWidth / aspect);
}
else
{
newHeight = rectHeight;
newWidth = (int)(newHeight * aspect);
}
}
resizedImage = new Bitmap(original, newWidth, newHeight);
}
}
catch (Exception ex)
{
MessageBox.Show( ex.Message);
}
}
接受的答案可能有效,但我盯着它看了很长时间,不明白具体是怎么做的,所以我想分享我的想法:首先缩小高度,然后检查宽度,如果需要,再缩小一次,始终保持长宽比。
我使用SixLabors.ImageSharp
是因为它与Linux兼容,但一旦有了newHeight
和newWidth
,就可以很容易地交换大小调整功能。
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
public class ImageSharpService : IImageService
{
public async Task ShrinkAndSaveAsync(Stream stream, string savePath, int maxHeight, int maxWidth)
{
using Image image = Image.Load(stream);
// check if resize is needed
if (ResizeNeeded(image.Height, image.Width, maxHeight, maxWidth, out int newHeight, out int newWidth))
// swap this part out if not using ImageSharp
image.Mutate(x => x.Resize(new ResizeOptions
{
Size = new Size(newWidth, newHeight)
}));
await image.SaveAsync(savePath);
}
private bool ResizeNeeded(int height, int width, int maxHeight, int maxWidth, out int newHeight, out int newWidth)
{
// first use existing dimensions
newHeight = height;
newWidth = width;
// if below max on both then do nothing
if (height <= maxHeight && width <= maxWidth) return false;
// naively check height first
if (height > maxHeight)
{
// set down to max height
newHeight = maxHeight;
// calculate what new width would be
var heightReductionRatio = maxHeight / height; // ratio of maxHeight:image.Height
newWidth = width * heightReductionRatio; // apply ratio to image.Width
}
// does width need to be reduced?
// (this will also re-check width after shrinking by height dimension)
if (newWidth > maxWidth)
{
// if so, re-calculate height to fit for maxWidth
var widthReductionRatio = maxWidth / newWidth; // ratio of maxWidth:newWidth (height reduction ratio may have been applied)
newHeight = maxHeight * widthReductionRatio; // apply new ratio to maxHeight to get final height
newWidth = maxWidth;
}
// if we got here, resize needed and out vars have been set
return true;
}
}
我相信,如果你只改变高度或宽度,它将保持更好的比例,宽度/高度也会随之改变。所以你可以尝试