簡體   English   中英

如何調整圖像大小以保持 C# 中的縱橫比

[英]How to resize an image maintaining the aspect ratio in C#

我需要知道一種方法來調整圖像大小以適合盒子而不會使圖像拉伸太多。 該框已設置寬度和高度,我希望圖像盡可能多地填充框,但保持其原始縱橫比。

//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)
 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);
                }
            }

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);

接受的答案可能有效,但我盯着它看了很長時間,無法確切理解,所以我想我會分享我的想法:先縮小高度,然后檢查寬度,如果需要再縮小,始終保持縱橫比比率。

我使用SixLabors.ImageSharp是因為它與 Linux 兼容,但是一旦您擁有newHeight和 newWidth ,就可以輕松地換掉調整大小的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;
    }
}

我相信,如果您只更改高度或僅更改寬度,它將保持更好的比率,並且寬度/高度會隨之改變。 所以你可以試試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM