C# 调整图像大小以适合边界框
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1106339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Resize Image to fit in bounding box
提问by Eric Petroelje
An easy problem, but for some reason I just can't figure this out today.
一个简单的问题,但由于某种原因,我今天无法解决这个问题。
I need to resize an image to the maximum possible size that will fit in a bounding box while maintaining the aspect ratio.
我需要将图像调整为适合边界框的最大可能尺寸,同时保持纵横比。
Basicly I'm looking for the code to fill in this function:
基本上我正在寻找代码来填充这个函数:
void CalcNewDimensions(ref int w, ref int h, int MaxWidth, int MaxHeight);
Where w & h are the original height and width (in) and the new height and width (out) and MaxWidth and MaxHeight define the bounding box that the image must fit in.
其中 w & h 是原始高度和宽度 (in) 和新的高度和宽度 (out) 以及 MaxWidth 和 MaxHeight 定义图像必须适合的边界框。
采纳答案by Shawn J. Goff
Find which is smaller: MaxWidth / w
or MaxHeight / h
Then multiply w
and h
by that number
查找哪一个较小:MaxWidth / w
或 MaxHeight / h
再乘以w
和h
由数
Explanation:
解释:
You need to find the scaling factor which makes the image fit.
您需要找到使图像适合的缩放因子。
To find the scaling factor, s
, for the width, then s
must be such that:
s * w = MaxWidth
.
Therefore, the scaling factor is MaxWidth / w
.
要找到s
宽度的缩放因子 ,则s
必须是这样的:
s * w = MaxWidth
。因此,比例因子为MaxWidth / w
。
Similarly for height.
身高也是一样。
The one that requires the most scaling (smaller s
) is the factor by which you must scale the whole image.
需要最大缩放(更小s
)的那个是您必须缩放整个图像的因子。
回答by Jason Creighton
Python code, but maybe it will point you in the right direction:
Python 代码,但也许它会为您指明正确的方向:
def fit_within_box(box_width, box_height, width, height):
"""
Returns a tuple (new_width, new_height) which has the property
that it fits within box_width and box_height and has (close to)
the same aspect ratio as the original size
"""
new_width, new_height = width, height
aspect_ratio = float(width) / float(height)
if new_width > box_width:
new_width = box_width
new_height = int(new_width / aspect_ratio)
if new_height > box_height:
new_height = box_height
new_width = int(new_height * aspect_ratio)
return (new_width, new_height)
回答by Matt Warren
Based on Eric's suggestion I'd do something like this:
根据埃里克的建议,我会做这样的事情:
private static Size ExpandToBound(Size image, Size boundingBox)
{
double widthScale = 0, heightScale = 0;
if (image.Width != 0)
widthScale = (double)boundingBox.Width / (double)image.Width;
if (image.Height != 0)
heightScale = (double)boundingBox.Height / (double)image.Height;
double scale = Math.Min(widthScale, heightScale);
Size result = new Size((int)(image.Width * scale),
(int)(image.Height * scale));
return result;
}
I might have gone a bit overboard on the casts, but I was just trying to preserve precision in the calculations.
我可能在演员表上有点过分,但我只是想保持计算的精度。
回答by vocaro
To perform an aspect fill instead of an aspect fit, use the larger ratio instead. That is, change Matt's code from Math.Min to Math.Max.
要执行纵横比填充而不是纵横匹配,请改用较大的比率。即,将 Matt 的代码从 Math.Min 改为 Math.Max。
(An aspect fill leaves none of the bounding box empty but may put some of the image outside the bounds, while an aspect fit leaves none of the image outside the bounds but may leave some of the bounding box empty.)
(纵横填充不会让边界框为空,但可能会将某些图像放在边界之外,而纵横匹配不会使任何图像超出边界,但可能会使某些边界框为空。)
回答by Brian Chavez
Tried Mr. Warren's code, but it didn't produce reliable results.
尝试了 Warren 先生的代码,但没有产生可靠的结果。
For example,
例如,
ExpandToBound(new Size(640,480), new Size(66, 999)).Dump();
// {Width=66, Height=49}
ExpandToBound(new Size(640,480), new Size(999,50)).Dump();
// {Width=66, Height=50}
You can see, height = 49 and height = 50 in another.
你可以看到,另一个高度 = 49 和高度 = 50。
Here's mine (based version of Mr. Warren's code) without the discrepancy and a slight refactor:
这是我的(基于 Warren 先生代码的版本)没有差异和轻微的重构:
// Passing null for either maxWidth or maxHeight maintains aspect ratio while
// the other non-null parameter is guaranteed to be constrained to
// its maximum value.
//
// Example: maxHeight = 50, maxWidth = null
// Constrain the height to a maximum value of 50, respecting the aspect
// ratio, to any width.
//
// Example: maxHeight = 100, maxWidth = 90
// Constrain the height to a maximum of 100 and width to a maximum of 90
// whichever comes first.
//
private static Size ScaleSize( Size from, int? maxWidth, int? maxHeight )
{
if ( !maxWidth.HasValue && !maxHeight.HasValue ) throw new ArgumentException( "At least one scale factor (toWidth or toHeight) must not be null." );
if ( from.Height == 0 || from.Width == 0 ) throw new ArgumentException( "Cannot scale size from zero." );
double? widthScale = null;
double? heightScale = null;
if ( maxWidth.HasValue )
{
widthScale = maxWidth.Value / (double)from.Width;
}
if ( maxHeight.HasValue )
{
heightScale = maxHeight.Value / (double)from.Height;
}
double scale = Math.Min( (double)(widthScale ?? heightScale),
(double)(heightScale ?? widthScale) );
return new Size( (int)Math.Floor( from.Width * scale ), (int)Math.Ceiling( from.Height * scale ) );
}
回答by M. Mennan Kara
Following code produces more accurate results:
以下代码产生更准确的结果:
public static Size CalculateResizeToFit(Size imageSize, Size boxSize)
{
// TODO: Check for arguments (for null and <=0)
var widthScale = boxSize.Width / (double)imageSize.Width;
var heightScale = boxSize.Height / (double)imageSize.Height;
var scale = Math.Min(widthScale, heightScale);
return new Size(
(int)Math.Round((imageSize.Width * scale)),
(int)Math.Round((imageSize.Height * scale))
);
}
回答by Nicolas Le Thierry d'Ennequin
Based on the previous answers, here's a Javascript function:
根据之前的答案,这里有一个 Javascript 函数:
/**
* fitInBox
* Constrains a box (width x height) to fit in a containing box (maxWidth x maxHeight), preserving the aspect ratio
* @param width width of the box to be resized
* @param height height of the box to be resized
* @param maxWidth width of the containing box
* @param maxHeight height of the containing box
* @param expandable (Bool) if output size is bigger than input size, output is left unchanged (false) or expanded (true)
* @return {width, height} of the resized box
*/
function fitInBox(width, height, maxWidth, maxHeight, expandable) {
"use strict";
var aspect = width / height,
initWidth = width,
initHeight = height;
if (width > maxWidth || height < maxHeight) {
width = maxWidth;
height = Math.floor(width / aspect);
}
if (height > maxHeight || width < maxWidth) {
height = maxHeight;
width = Math.floor(height * aspect);
}
if (!!expandable === false && (width >= initWidth || height >= initHeight)) {
width = initWidth;
height = initHeight;
}
return {
width: width,
height: height
};
}
回答by Toma? ?tih
über simple. :) The issue is to find a factor by which you need to multiply width and height. The solution is to try using one and if it doesn't fit, use the other. So...
超级简单。:) 问题是找到一个需要乘以宽度和高度的因子。解决方案是尝试使用一种,如果不合适,则使用另一种。所以...
private float ScaleFactor(Rectangle outer, Rectangle inner)
{
float factor = (float)outer.Height / (float)inner.Height;
if ((float)inner.Width * factor > outer.Width) // Switch!
factor = (float)outer.Width / (float)inner.Width;
return factor;
}
To fit picture (pctRect) to window (wndRect) call like this
使图片 (pctRect) 适合窗口 (wndRect) 像这样调用
float factor=ScaleFactor(wndRect, pctRect); // Outer, inner
RectangleF resultRect=new RectangleF(0,0,pctRect.Width*factor,pctRect.Height*Factor)