图像在C#中调整大小 - 确定调整大小尺寸(高度和宽度)的算法

noc*_*ier 5 c# system.drawing image-manipulation bitmap image-processing

我需要缩小高度或宽度大于预定义像素值的图像.

我编写了一些代码来查看原始图像,检查宽度,高度或高度和宽度是否大于最大宽度/最大高度设置.

我现在需要根据后一个值的最大值找出要调整大小的尺寸.

例如:如果图像是900h x 300w和MAX高度是700h我需要调整高度700和宽度????< - 这是我需要计算的..

创建和保存图像文件很简单,超出了本文的范围:

// First I get the max height and width allowed:

int resizeMaxHeight =  int.Parse(Utility.GetConfigValue("ResizeMaxHeight")); // in config: 700px
int resizeMaxWidth =  int.Parse(Utility.GetConfigValue("ResizeMaxWidth"));  //  in config: 500px

// Save original: 
try
{
    filebase.SaveAs(savedFileName);
}
catch (System.IO.DirectoryNotFoundException ex)
{
    Logger.Instance.LogException(ex, 0, "FileTransfer");
}

// Determin original dimensions:
Image image = System.Drawing.Image.FromFile(Server.MapPath(savedFileName));

int resizeHeight, resizeWidth;
bool doResize = true;

// both height and width are greater than the allowed height and width:
if (image.Width > resizeMaxWidth && image.Height > resizeMaxHeight)
{
    if (image.Height > image.Width) 
        resizeHeight = resizeMaxHeight;
    else
        resizeWidth = resizeMaxWidth;
}
else if (image.Width > resizeMaxWidth)
{
    // width is too great, but height is ok
    resizeWidth = resizeMaxWidth;
}
else if (image.Height > resizeMaxHeight)
{
    // height is too great, but width is ok
    resizeHeight = resizeMaxHeight;
}
else
{
    // image is ok size, don't resize:
    doResize = false;
}
Run Code Online (Sandbox Code Playgroud)

创建缩略图:这就是我现在正在工作的......不完整:

if (doResize)
{
    ImageUtilities.ResizeImage(image, resizeWidth, resizeHeight);
}
Run Code Online (Sandbox Code Playgroud)

jbc*_*jbc 14

如果图像高度大于图像宽度,Nathaniel发布的解决方案实际上失败了.以下示例生成正确的结果:

private Size ResizeFit(Size originalSize, Size maxSize)
{
    var widthRatio = (double)maxSize.Width / (double)originalSize.Width;
    var heightRatio = (double) maxSize.Height/(double) originalSize.Height;
    var minAspectRatio = Math.Min(widthRatio, heightRatio);
    if (minAspectRatio > 1)
        return originalSize;
    return new Size((int)(originalSize.Width*minAspectRatio), (int)(originalSize.Height*minAspectRatio));
}
Run Code Online (Sandbox Code Playgroud)


Lil*_*ver 7

以下是两种进行此计算的方法.根据您对问题的看法,可能看起来比另一个更直观.它们在数学上等效于几个小数位.

两者对Math.Round都是安全的,但只有ConstrainVerbose产生的结果总是小于maxWidth/maxHeight.

SizeF ConstrainConcise(int imageWidth, int imageHeight, int maxWidth, int maxHeight){
    // Downscale by the smallest ratio (never upscale)
    var scale = Math.Min(1, Math.Min(maxWidth / (float)imageWidth, maxHeight / (float) imageHeight));
    return new SizeF(scale * imageWidth, scale * imageHeight);
}

SizeF ConstrainVerbose(int imageWidth, int imageHeight, int maxWidth, int maxHeight){
    // Coalculate the aspect ratios of the image and bounding box
    var maxAspect = (float) maxWidth / (float) maxHeight;
    var aspect =  (float) imageWidth / (float) imageHeight;
    // Bounding box aspect is narrower
    if (maxAspect <= aspect && imageWidth > maxWidth)
    {
        // Use the width bound and calculate the height
        return new SizeF(maxWidth, Math.Min(maxHeight, maxWidth / aspect));
    }
    else if (maxAspect > aspect && imageHeight > maxHeight)
    {
        // Use the height bound and calculate the width
        return new SizeF(Math.Min(maxWidth, maxHeight * aspect), maxHeight);
    }else{
        return new SizeF(imageWidth, imageHeight);
    }
}
Run Code Online (Sandbox Code Playgroud)

蛮力单位测试在这里

  • 别客气.我建议你也阅读这篇文章 - 在.NET图像大小调整中有很多陷阱你应该避开:http://nathanaeljones.com/163/20-image-resizing-pitfalls/ (2认同)

And*_*y S 6

您可以使用一些整数技巧来避免计算纵横比(并使用双精度数).

// You have the new height, you need the new width
int orgHeight = 1200;
int orgWidth = 1920;

int newHeight = 400;
int newWidth = (newHeight * orgWidth) / orgHeight; // 640
Run Code Online (Sandbox Code Playgroud)

要么...

// You have the new width, you need the new height.
int orgWidth = 1920;
int orgHeight = 1200;

int newWidth = 800;
int newHeight = (newWidth * orgHeight) / orgWidth; // 500
Run Code Online (Sandbox Code Playgroud)

以下示例将图像调整为任何所需的矩形(desWidth和desHeight),并将图像置于该矩形内.

static Image ResizeImage(Image image, int desWidth, int desHeight)
{
    int x, y, w, h;

    if (image.Height > image.Width)
    {
        w = (image.Width * desHeight) / image.Height;
        h = desHeight;
        x = (desWidth - w) / 2;
        y = 0;
    }
    else
    {
        w = desWidth;
        h = (image.Height * desWidth) / image.Width;
        x = 0;
        y = (desHeight - h) / 2;
    }

    var bmp = new Bitmap(desWidth, desHeight);

    using (Graphics g = Graphics.FromImage(bmp))
    {
        g.CompositingQuality = CompositingQuality.HighQuality;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(image, x, y, w, h);
    }

    return bmp;
}
Run Code Online (Sandbox Code Playgroud)