C#:如何按比例调整图像大小并设置最大高度

4

我需要按比例调整图片大小而不改变其纵横比。我已经有了用固定高度和宽度调整大小的代码,但我需要根据最大高度(比如600像素)等比缩放图像。我该如何修改代码以满足我的需求?

public static void Main()
{
  var image = Image.FromFile(@"c:\logo.png");
  var newImage = ScaleImage(image, 300, 400);
  newImage.Save(@"c:\test.png", ImageFormat.Png);
}

public static Image 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);
  return newImage;
}

请提供你宝贵的想法。

这段代码有什么问题? - Likurg
请恕我直言,请仔细阅读我的要求。该代码使用最大高度和最大宽度,而我需要按比例更改图像尺寸,只保持高度到最大值(比如600)。 - user735647
我不知道问题出在哪里,但如果我没记错的话,你的代码确实可以调整图像大小而不改变纵横比。你能否提供一个你期望发生的示例? - Remko Jansen
使用ratioY而不是ratio来计算新的宽度和高度。 - axl g
@remko:是的,你说得完全正确,但在我的代码中,我将固定的高度和宽度传递给了ScaleImage方法。实际上,我需要传递一个固定高度但是宽度成比例的尺寸。这可能吗? - user735647
4个回答

4
这感觉太简单了,我觉得我可能漏掉了什么。无论如何,这样做行得通吗?
public static Image ScaleImage(Image image, int maxHeight) 
{ 
    var ratio = (double)maxHeight / image.Height; 

    var newWidth = (int)(image.Width * ratio); 
    var newHeight = (int)(image.Height * ratio); 

    var newImage = new Bitmap(newWidth, newHeight); 
    using (var g = Graphics.FromImage(newImage))
    {
        g.DrawImage(image, 0, 0, newWidth, newHeight); 
    }
    return newImage; 
} 

非常感谢。让我试一下。 - user735647
我需要添加什么来防止缩放图像,使其适合最大高度或最大宽度,并且如果其中一侧较大,则只需减小大小直到它适合所需区域,同时保持比例。 - Liron Harel

1
请使用以下函数。
public Bitmap ProportionallyResizeBitmapByHeight(Bitmap imgToResize, int height)
{
  int sourceWidth = imgToResize.Width;
  int sourceHeight = imgToResize.Height;

  float scale = 0;

  scale = (height / (float)sourceHeight);

  int destWidth = (int)(sourceWidth * scale);
  int destHeight = (int)(sourceHeight * scale);

  Bitmap result = new Bitmap(destWidth, destHeight);
  result.SetResolution(imgToResize.HorizontalResolution, imgToResize.VerticalResolution);
  Graphics g = Graphics.FromImage(result);
  g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
  g.Dispose();

  return result;
}

@Imran 非常感谢。让我试一下。 - user735647

1

好的,思考这个过程: 如果你有一张大小为800 x 600的图片,并想将其调整为新的宽度x400高度(加上相应的新宽度),那么你需要通过将新高度(在您的情况下为最大高度)除以600来获得比例,并将800乘以此比例,对吧?

因此,在这种情况下,您需要将maxWidth和maxHeight更改为可选参数(比如800 x 600),以便给自己一些动态性,并获得以下结果:

public static Image ScaleImage(Image image, int maxWidth = 800, int maxHeight = 600)
 {

  int newWidth;
  int newHeight;
  double ratio = image.Height / image.Width;

  if(maxHeight != 600) {

     newWidth = image.Width * ratio;
     newHeight = maxHeight;

  }   

  Bitmap newImage = new Bitmap(newWidth, newHeight);
  Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
  return newImage;
}

希望这可以帮到你。我没有测试过它,但我已经重写了我的VB代码,所以理论上应该没问题...

这里还有一个ResizeStream方法:http://forums.asp.net/t/1576697.aspx/1,你可能会觉得很有用。 如果你想保持图像质量,你可以使用CompositingQuality和SmoothingMode等变量。


非常感谢。让我试试看。 - user735647
1
没问题。希望能帮到你。如果你遇到了问题,请告诉我。另外一件事:这是基于最大高度的,所以你可能也想检查一下 else if (maxWidth != 800),并相应地更改 newWidth 和 newHeight。但是,我包含的链接非常方便。 - army

0

100% 工作正常

   private static BitmapFrame CreateResizedImage(ImageSource source, int Max_width, int Max_height, int margin)
{
    float scaleHeight = (float)Max_width / (float)source.Height;
    float scaleWidth = (float)Max_height / (float)source.Width;
    float scale = Math.Min(scaleHeight, scaleWidth);

     int width = (int)(source.Width * scale);
     int height = (int)(source.Height * scale);


    var rect = new Rect(margin, margin, width - margin * 2, height - margin * 2);

    var group = new DrawingGroup();
    RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);
    group.Children.Add(new ImageDrawing(source, rect));

    var drawingVisual = new DrawingVisual();
    using (var drawingContext = drawingVisual.RenderOpen())
        drawingContext.DrawDrawing(group);

    var resizedImage = new RenderTargetBitmap(
        width, height,         // Resized dimensions
        96, 96,                // Default DPI values
        PixelFormats.Default); // Default pixel format
    resizedImage.Render(drawingVisual);

    return BitmapFrame.Create(resizedImage);
}


//--------Main------------//

  BitmapImage imageSource = (BitmapImage)ImagePreview.Source;
  var NewImage= CreateResizedImage(imageSource , 300, 300, 0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接