将图像缩放以完全填充边界框

8
例如,如果我需要填充一个100像素宽、50像素高的边界框,以下输入图像将具有以下行为:
  1. 200w x 200h缩小50%,顶部和底部各裁剪25%。

  2. 200w x 100h缩小50%,不裁剪。

  3. 100w x 200h不缩放,但顶部和底部各裁剪75像素。

这似乎是一种常见的调整大小函数,但我还没有找到算法的示例。
接受任何语言的答案,包括伪代码。链接到包含答案的页面也很好!

有人在我的回答下留了评论,我以为是你,但实际上不是 - 你能否就你的实际限制澄清一下问题?谢谢。 - Mark Ransom
我想要的是一般情况。谢谢。 - Larsenal
谢谢。我已经编辑掉了我回答中误导性的部分。 - Mark Ransom
3个回答

13

你所需要的很容易实现。计算宽度和高度的不同缩放因子,然后选择其中较大的作为实际缩放因子。将输入大小乘以该比例,如果有超出则进行裁剪。

scale = max(maxwidth/oldwidth, maxheight/oldheight)
scaledwidth = oldwidth * scale
scaledheight = oldheight * scale
if scaledheight > maxheight:
    croptop = (scaledheight - maxheight) / 2
    cropbottom = (scaledheight - maxheight) - croptop
if scaledwidth > maxwidth:
    cropleft = (scaledwidth - maxwidth) / 2
    cropright = (scaledwidth - maxwidth) - cropleft

只有X(宽度)受到调整大小的限制,另一个Y(高度)会被裁剪。 - Suroot
那个限制条件没有被说明,也没有从您的示例中明显地表现出来。在这种情况下,使用scale=maxwidth/oldwidth,然后删除cropleft/cropright计算,其余部分保持不变。 - Mark Ransom
我们应该将输出数字四舍五入吗?因为它们通常是像素的一部分。 - Gringo Suave
@GringoSuave 是的,对于 scaledwidthscaledheight 进行四舍五入取整是个不错的主意,特别是因为截断可能会由于浮点数精度造成误差偏移一个单位。 - Mark Ransom

1

在这里,我们确保只有当X大于100%时才进行缩放;然后,在完成此操作后,我们确保我们在Y轴上仅为50像素。如果我们大于50,则取差值并除以2,以获取从顶部/底部移除的量。

double percent_x = 1.0;

if(X > 100) {
 percent_x = (float)100/X;
 X *= percent_x;
 Y *= percent_x;
}

int diff_y;
int top_cut, bott_cut;
if( Y > 50 ) {
 diff_y = (Y - 50) / 2;
 top_cut = bott_cut = diff_y;
}

0
受马克·兰索姆的回答启发(非常感谢您-您救了我),我大力推荐。对于那些想要在不裁剪图像的情况下使其适合边界的人,我发现这很有效:
if (maxWidth > width && maxHeight > height) {
  return { width, height };
}

aspectRatio = width / height,
scale       = max(maxWidth / width, maxHeight / height);

scaledHeight = height * scale,
scaledWidth  = width * scale;

if (scaledHeight > maxHeight) {
  scaledHeight = maxHeight;
  scaledWidth  = aspectRatio * scaledHeight;
} else if (scaledWidth > maxWidth) {
  scaledWidth  = maxWidth;
  scaledHeight = scaledWidth / aspectRatio;
}

return { scaledHeight, scaledWidth };

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