一个简单的问题,但由于某种原因,我今天无法弄清楚这一点.
我需要将图像调整到适合边框的最大可能尺寸,同时保持纵横比.
基本上我正在寻找填写此功能的代码:
void CalcNewDimensions(ref int w, ref int h, int MaxWidth, int MaxHeight);
其中w&h是原始高度和宽度(in),新的高度和宽度(out)以及MaxWidth和MaxHeight定义图像必须适合的边界框.
查找哪一个较小:MaxWidth / w
或 MaxHeight / h
再乘以w
和h
由数
说明:
您需要找到使图像适合的缩放系数.
要找到比例因子,s
对于宽度,则s
必须如此:
s * w = MaxWidth
.因此,缩放因子是MaxWidth / w
.
同样适合身高.
需要最大缩放(较小s
)的那个是您必须缩放整个图像的因素.
根据Eric的建议,我会做这样的事情:
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; }
我可能在演员阵容上有点过分,但我只是想在计算中保持精确度.
试过沃伦先生的代码,但它没有产生可靠的结果.
例如,
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}
你可以在另一个中看到,height = 49和height = 50.
这是我的(沃伦先生的代码版本)没有差异和轻微的重构:
// 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 ) ); }
要执行方面填充而不是宽高比,请使用较大的比例.也就是说,将Matt的代码从Math.Min更改为Math.Max.
(方面填充不会使边界框为空,但可能会将某些图像放在边界之外,而方面适合不会使边界外的任何图像留下,但可能会使某些边界框为空.)
以下代码可生成更准确的结果:
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)) ); }